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