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