1 #include "edit_via.hpp"
2 #include "widgets/parameter_set_editor.hpp"
3 #include "board/via.hpp"
4 #include "pool/ipool.hpp"
5 #include "util/geom_util.hpp"
6 #include "block/net.hpp"
7 #include <iostream>
8 #include <deque>
9 #include <algorithm>
10 #include "widgets/pool_browser_button.hpp"
11 #include "widgets/pool_browser_padstack.hpp"
12
13 namespace horizon {
14
EditViaDialog(Gtk::Window * parent,std::set<Via * > & vias,IPool & pool,IPool & pool_caching)15 EditViaDialog::EditViaDialog(Gtk::Window *parent, std::set<Via *> &vias, IPool &pool, IPool &pool_caching)
16 : Gtk::Dialog("Edit via", *parent, Gtk::DialogFlags::DIALOG_MODAL | Gtk::DialogFlags::DIALOG_USE_HEADER_BAR)
17 {
18 set_default_size(400, 300);
19 add_button("Cancel", Gtk::ResponseType::RESPONSE_CANCEL);
20 add_button("OK", Gtk::ResponseType::RESPONSE_OK);
21 set_default_response(Gtk::ResponseType::RESPONSE_OK);
22
23 auto box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 0));
24 auto combo = Gtk::manage(new Gtk::ComboBoxText());
25 combo->set_margin_start(8);
26 combo->set_margin_end(8);
27 combo->set_margin_top(8);
28 combo->set_margin_bottom(8);
29 box->pack_start(*combo, false, false, 0);
30
31 auto grid = Gtk::manage(new Gtk::Grid());
32 grid->set_row_spacing(8);
33 grid->set_column_spacing(8);
34 grid->set_margin_start(8);
35 grid->set_margin_end(8);
36 {
37 auto la = Gtk::manage(new Gtk::Label("Padstack"));
38 la->get_style_context()->add_class("dim-label");
39 la->set_halign(Gtk::ALIGN_END);
40 grid->attach(*la, 0, 0, 1, 1);
41 }
42
43 auto padstack_apply_all_button = Gtk::manage(new Gtk::Button);
44 padstack_apply_all_button->set_image_from_icon_name("object-select-symbolic", Gtk::ICON_SIZE_BUTTON);
45 padstack_apply_all_button->set_tooltip_text("Apply to all selected vias");
46 padstack_apply_all_button->signal_clicked().connect([this, vias, &pool_caching] {
47 for (auto &via : vias) {
48 if (!via->from_rules) {
49 via->pool_padstack = pool_caching.get_padstack(button_vp->property_selected_uuid());
50 }
51 }
52 });
53 grid->attach(*padstack_apply_all_button, 2, 0, 1, 1);
54
55 auto rules_apply_all_button = Gtk::manage(new Gtk::Button);
56 rules_apply_all_button->set_image_from_icon_name("object-select-symbolic", Gtk::ICON_SIZE_BUTTON);
57 rules_apply_all_button->set_tooltip_text("Apply to all selected vias");
58 rules_apply_all_button->signal_clicked().connect([this, vias] {
59 for (auto &via : vias) {
60 via->from_rules = cb_from_rules->get_active();
61 update_sensitive();
62 }
63 });
64 grid->attach(*rules_apply_all_button, 2, 1, 1, 1);
65
66 box->pack_start(*grid, false, false, 0);
67
68 std::map<UUID, Via *> viamap;
69
70 for (auto via : vias) {
71 std::string name;
72 if (via->junction->net) {
73 name = via->junction->net->name;
74 }
75 else {
76 name = "<no net>";
77 }
78 combo->append(static_cast<std::string>(via->uuid), coord_to_string(via->junction->position) + " " + name);
79 viamap.emplace(via->uuid, via);
80 }
81
82 combo->signal_changed().connect([this, combo, viamap, box, grid, vias, &pool, &pool_caching] {
83 UUID uu(combo->get_active_id());
84 auto via = viamap.at(uu);
85 if (editor)
86 delete editor;
87 editor = Gtk::manage(new ParameterSetEditor(&via->parameter_set, false));
88 editor->set_has_apply_all("Apply to all selected vias (Shift+Enter)");
89 editor->populate();
90 editor->signal_apply_all().connect([vias, via](ParameterID id) {
91 for (auto it : vias) {
92 it->parameter_set[id] = via->parameter_set.at(id);
93 }
94 });
95 editor->signal_activate_last().connect([this] { response(Gtk::RESPONSE_OK); });
96 box->pack_start(*editor, true, true, 0);
97 editor->show();
98
99 if (button_vp)
100 delete button_vp;
101
102 button_vp = Gtk::manage(new PoolBrowserButton(ObjectType::PADSTACK, pool));
103 {
104 auto &br = dynamic_cast<PoolBrowserPadstack &>(button_vp->get_browser());
105 br.set_padstacks_included({Padstack::Type::VIA});
106 }
107 button_vp->property_selected_uuid() = via->pool_padstack->uuid;
108 button_vp->property_selected_uuid().signal_changed().connect([this, via, &pool_caching] {
109 if (!via->from_rules)
110 via->pool_padstack = pool_caching.get_padstack(button_vp->property_selected_uuid());
111 });
112 button_vp->set_hexpand(true);
113 grid->attach(*button_vp, 1, 0, 1, 1);
114 button_vp->show();
115
116 if (cb_from_rules)
117 delete cb_from_rules;
118 cb_from_rules = Gtk::manage(new Gtk::CheckButton("From rules"));
119 cb_from_rules->set_active(via->from_rules);
120 cb_from_rules->signal_toggled().connect([this, via] {
121 via->from_rules = cb_from_rules->get_active();
122 update_sensitive();
123 });
124 grid->attach(*cb_from_rules, 1, 1, 1, 1);
125 cb_from_rules->show();
126
127 update_sensitive();
128 });
129
130 combo->set_active(0);
131 editor->focus_first();
132 update_sensitive();
133
134 get_content_area()->pack_start(*box, true, true, 0);
135 get_content_area()->set_border_width(0);
136
137 show_all();
138 }
139
update_sensitive()140 void EditViaDialog::update_sensitive()
141 {
142 auto s = !cb_from_rules->get_active();
143 button_vp->set_sensitive(s);
144 editor->set_sensitive(s);
145 }
146 } // namespace horizon
147