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