1 #include "footprint_generator_quad.hpp"
2 #include "widgets/pool_browser_button.hpp"
3 #include "document/idocument_package.hpp"
4 #include "pool/ipool.hpp"
5 #include "pool/package.hpp"
6 
7 namespace horizon {
FootprintGeneratorQuad(IDocumentPackage & c)8 FootprintGeneratorQuad::FootprintGeneratorQuad(IDocumentPackage &c)
9     : Glib::ObjectBase(typeid(FootprintGeneratorQuad)),
10       FootprintGeneratorBase("/org/horizon-eda/horizon/imp/footprint_generator/quad.svg", c)
11 {
12     update_preview();
13     sp_spacing_h = Gtk::manage(new SpinButtonDim());
14     sp_spacing_h->set_range(0, 100_mm);
15     sp_spacing_h->set_valign(Gtk::ALIGN_CENTER);
16     sp_spacing_h->set_halign(Gtk::ALIGN_START);
17     sp_spacing_h->set_value(40_mm);
18     overlay->add_at_sub(*sp_spacing_h, "#spacing_h");
19     sp_spacing_h->show();
20 
21     sp_spacing_v = Gtk::manage(new SpinButtonDim());
22     sp_spacing_v->set_range(0, 100_mm);
23     sp_spacing_v->set_valign(Gtk::ALIGN_CENTER);
24     sp_spacing_v->set_halign(Gtk::ALIGN_START);
25     sp_spacing_v->set_value(30_mm);
26     overlay->add_at_sub(*sp_spacing_v, "#spacing_v");
27     sp_spacing_v->show();
28 
29     sp_pitch = Gtk::manage(new SpinButtonDim());
30     sp_pitch->set_range(0, 50_mm);
31     sp_pitch->set_valign(Gtk::ALIGN_CENTER);
32     sp_pitch->set_halign(Gtk::ALIGN_START);
33     sp_pitch->set_value(3_mm);
34     overlay->add_at_sub(*sp_pitch, "#pitch");
35     sp_pitch->show();
36 
37     sp_pad_height = Gtk::manage(new SpinButtonDim());
38     sp_pad_height->set_range(0, 50_mm);
39     sp_pad_height->set_valign(Gtk::ALIGN_CENTER);
40     sp_pad_height->set_halign(Gtk::ALIGN_END);
41     sp_pad_height->set_value(.5_mm);
42     overlay->add_at_sub(*sp_pad_height, "#pad_height");
43     sp_pad_height->show();
44 
45     sp_pad_width = Gtk::manage(new SpinButtonDim());
46     sp_pad_width->set_range(0, 50_mm);
47     sp_pad_width->set_valign(Gtk::ALIGN_CENTER);
48     sp_pad_width->set_halign(Gtk::ALIGN_END);
49     sp_pad_width->set_value(.5_mm);
50     overlay->add_at_sub(*sp_pad_width, "#pad_width");
51     sp_pad_width->show();
52 
53     {
54         auto tbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 4));
55         auto la = Gtk::manage(new Gtk::Label("Count H:"));
56         tbox->pack_start(*la, false, false, 0);
57 
58         sp_count_h = Gtk::manage(new Gtk::SpinButton());
59         sp_count_h->set_range(1, 512);
60         sp_count_h->set_increments(1, 1);
61         tbox->pack_start(*sp_count_h, false, false, 0);
62 
63         box_top->pack_start(*tbox, false, false, 0);
64     }
65     {
66         auto tbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 4));
67         auto la = Gtk::manage(new Gtk::Label("Count V:"));
68         tbox->pack_start(*la, false, false, 0);
69 
70         sp_count_v = Gtk::manage(new Gtk::SpinButton());
71         sp_count_v->set_range(1, 512);
72         sp_count_v->set_increments(1, 1);
73         tbox->pack_start(*sp_count_v, false, false, 0);
74 
75         box_top->pack_start(*tbox, false, false, 0);
76     }
77 
78     sp_count_h->signal_value_changed().connect([this] {
79         pad_count_h = sp_count_h->get_value_as_int();
80         update_preview();
81     });
82     sp_count_v->signal_value_changed().connect([this] {
83         pad_count_v = sp_count_v->get_value_as_int();
84         update_preview();
85     });
86 
87     sp_count_h->set_value(4);
88     sp_count_v->set_value(4);
89 }
90 
generate()91 bool FootprintGeneratorQuad::generate()
92 {
93     if (!property_can_generate())
94         return false;
95     int64_t pitch = sp_pitch->get_value_as_int();
96     int64_t spacing_h = sp_spacing_h->get_value_as_int();
97     int64_t y0 = (pad_count_v - 1) * (pitch / 2);
98     int64_t pad_width = sp_pad_width->get_value_as_int();
99     int64_t pad_height = sp_pad_height->get_value_as_int();
100 
101     auto padstack = core.get_pool().get_padstack(browser_button->property_selected_uuid());
102     for (auto it : {-1, 1}) {
103         for (unsigned int i = 0; i < pad_count_v; i++) {
104             auto uu = UUID::random();
105             auto &pad = package.pads.emplace(uu, Pad(uu, padstack)).first->second;
106             pad.placement.shift = {it * spacing_h, y0 - pitch * i};
107             update_pad_parameters(*padstack, pad, pad_width, pad_height);
108             if (it < 0) {
109                 pad.placement.set_angle_deg(270);
110                 pad.name = std::to_string(i + 1);
111             }
112             else {
113                 pad.placement.set_angle_deg(90);
114                 pad.name = std::to_string(pad_count_v * 2 + pad_count_h - i);
115             }
116         }
117     }
118 
119     int64_t spacing_v = sp_spacing_v->get_value_as_int();
120     int64_t x0 = (pad_count_h - 1) * (pitch / 2) * -1;
121     for (auto it : {-1, 1}) {
122         for (unsigned int i = 0; i < pad_count_h; i++) {
123             auto uu = UUID::random();
124             auto &pad = package.pads.emplace(uu, Pad(uu, padstack)).first->second;
125             pad.placement.shift = {x0 + pitch * i, it * spacing_v};
126             update_pad_parameters(*padstack, pad, pad_width, pad_height);
127             if (it < 0) {
128                 pad.placement.set_angle_deg(0);
129                 pad.name = std::to_string(i + 1 + pad_count_v);
130             }
131             else {
132                 pad.placement.set_angle_deg(180);
133                 pad.name = std::to_string(pad_count_v * 2 + pad_count_h * 2 - i);
134             }
135         }
136     }
137     return true;
138 }
139 
update_preview()140 void FootprintGeneratorQuad::update_preview()
141 {
142     if (pad_count_v >= 4) {
143         overlay->sub_texts["#pad1"] = "1";
144         overlay->sub_texts["#pad2"] = "2";
145         overlay->sub_texts["#pad3"] = std::to_string(pad_count_v - 1);
146         overlay->sub_texts["#pad4"] = std::to_string(pad_count_v);
147 
148         overlay->sub_texts["#pad9"] = std::to_string(pad_count_h + pad_count_v + 1);
149         overlay->sub_texts["#pad10"] = std::to_string(pad_count_h + pad_count_v + 2);
150         overlay->sub_texts["#pad11"] = std::to_string(pad_count_h + pad_count_v * 2 - 1);
151         overlay->sub_texts["#pad12"] = std::to_string(pad_count_h + pad_count_v * 2);
152     }
153     else if (pad_count_v == 3) {
154         overlay->sub_texts["#pad1"] = "1";
155         overlay->sub_texts["#pad2"] = "2";
156         overlay->sub_texts["#pad3"] = "X";
157         overlay->sub_texts["#pad4"] = "3";
158 
159         overlay->sub_texts["#pad9"] = std::to_string(pad_count_h + pad_count_v + 1);
160         overlay->sub_texts["#pad10"] = std::to_string(pad_count_h + pad_count_v + 2);
161         overlay->sub_texts["#pad11"] = "X";
162         overlay->sub_texts["#pad12"] = std::to_string(pad_count_h + pad_count_v * 2);
163     }
164     else if (pad_count_v == 2) {
165         overlay->sub_texts["#pad1"] = "1";
166         overlay->sub_texts["#pad2"] = "X";
167         overlay->sub_texts["#pad3"] = "X";
168         overlay->sub_texts["#pad4"] = "2";
169 
170         overlay->sub_texts["#pad9"] = std::to_string(pad_count_h + pad_count_v + 1);
171         overlay->sub_texts["#pad10"] = "X";
172         overlay->sub_texts["#pad11"] = "X";
173         overlay->sub_texts["#pad12"] = std::to_string(pad_count_h + pad_count_v * 2);
174     }
175     else if (pad_count_v == 1) {
176         overlay->sub_texts["#pad1"] = "1";
177         overlay->sub_texts["#pad2"] = "X";
178         overlay->sub_texts["#pad3"] = "X";
179         overlay->sub_texts["#pad4"] = "X";
180 
181         overlay->sub_texts["#pad9"] = "X";
182         overlay->sub_texts["#pad10"] = "X";
183         overlay->sub_texts["#pad11"] = "X";
184         overlay->sub_texts["#pad12"] = std::to_string(pad_count_h + pad_count_v * 2);
185     }
186 
187     if (pad_count_h >= 4) {
188         overlay->sub_texts["#pad5"] = std::to_string(pad_count_v + 1);
189         overlay->sub_texts["#pad6"] = std::to_string(pad_count_v + 2);
190         overlay->sub_texts["#pad7"] = std::to_string(pad_count_v + pad_count_h - 1);
191         overlay->sub_texts["#pad8"] = std::to_string(pad_count_v + pad_count_h);
192 
193         overlay->sub_texts["#pad13"] = std::to_string(pad_count_v * 2 + pad_count_h + 1);
194         overlay->sub_texts["#pad14"] = std::to_string(pad_count_v * 2 + pad_count_h + 2);
195         overlay->sub_texts["#pad15"] = std::to_string(pad_count_v * 2 + pad_count_h * 2 - 1);
196         overlay->sub_texts["#pad16"] = std::to_string(pad_count_v * 2 + pad_count_h * 2);
197     }
198     else if (pad_count_h == 3) {
199         overlay->sub_texts["#pad5"] = std::to_string(pad_count_v + 1);
200         overlay->sub_texts["#pad6"] = std::to_string(pad_count_v + 2);
201         overlay->sub_texts["#pad7"] = "X";
202         overlay->sub_texts["#pad8"] = std::to_string(pad_count_v + pad_count_h);
203 
204         overlay->sub_texts["#pad13"] = std::to_string(pad_count_v * 2 + pad_count_h + 1);
205         overlay->sub_texts["#pad14"] = std::to_string(pad_count_v * 2 + pad_count_h + 2);
206         overlay->sub_texts["#pad15"] = "X";
207         overlay->sub_texts["#pad16"] = std::to_string(pad_count_v * 2 + pad_count_h * 2);
208     }
209     else if (pad_count_h == 2) {
210         overlay->sub_texts["#pad5"] = std::to_string(pad_count_v + 1);
211         overlay->sub_texts["#pad6"] = "X";
212         overlay->sub_texts["#pad7"] = "X";
213         overlay->sub_texts["#pad8"] = std::to_string(pad_count_v + pad_count_h);
214 
215         overlay->sub_texts["#pad13"] = std::to_string(pad_count_v * 2 + pad_count_h + 1);
216         overlay->sub_texts["#pad14"] = "X";
217         overlay->sub_texts["#pad15"] = "X";
218         overlay->sub_texts["#pad16"] = std::to_string(pad_count_v * 2 + pad_count_h * 2);
219     }
220     else if (pad_count_h == 1) {
221         overlay->sub_texts["#pad5"] = std::to_string(pad_count_v + 1);
222         overlay->sub_texts["#pad6"] = "X";
223         overlay->sub_texts["#pad7"] = "X";
224         overlay->sub_texts["#pad8"] = "X";
225 
226         overlay->sub_texts["#pad13"] = "X";
227         overlay->sub_texts["#pad14"] = "X";
228         overlay->sub_texts["#pad15"] = "X";
229         overlay->sub_texts["#pad16"] = std::to_string(pad_count_v * 2 + pad_count_h * 2);
230     }
231 
232     overlay->queue_draw();
233 }
234 } // namespace horizon
235