1 #include "imp_schematic.hpp"
2 #include "canvas/canvas_gl.hpp"
3 #include "export_pdf/export_pdf.hpp"
4 #include "pool/part.hpp"
5 #include "rules/rules_window.hpp"
6 #include "widgets/sheet_box.hpp"
7 #include "util/gtk_util.hpp"
8 #include "util/util.hpp"
9 #include "util/str_util.hpp"
10 #include "util/selection_util.hpp"
11 #include "bom_export_window.hpp"
12 #include "pdf_export_window.hpp"
13 #include "nlohmann/json.hpp"
14 #include "core/tools/tool_backannotate_connection_lines.hpp"
15 #include "core/tools/tool_add_part.hpp"
16 #include "core/tools/tool_map_symbol.hpp"
17 #include "widgets/unplaced_box.hpp"
18 #include "core/tool_id.hpp"
19 #include "actions.hpp"
20 #include "widgets/action_button.hpp"
21
22 namespace horizon {
ImpSchematic(const std::string & schematic_filename,const std::string & block_filename,const std::string & pictures_dir,const PoolParams & pool_params)23 ImpSchematic::ImpSchematic(const std::string &schematic_filename, const std::string &block_filename,
24 const std::string &pictures_dir, const PoolParams &pool_params)
25 : ImpBase(pool_params), core_schematic(schematic_filename, block_filename, pictures_dir, *pool, *pool_caching),
26 project_dir(Glib::path_get_dirname(schematic_filename)), searcher(core_schematic)
27 {
28 core = &core_schematic;
29 core_schematic.signal_tool_changed().connect(sigc::mem_fun(*this, &ImpSchematic::handle_tool_change));
30 core_schematic.signal_rebuilt().connect(sigc::mem_fun(*this, &ImpSchematic::handle_core_rebuilt));
31 }
32
canvas_update()33 void ImpSchematic::canvas_update()
34 {
35 canvas->update(core_schematic.get_canvas_data());
36 warnings_box->update(core_schematic.get_sheet()->warnings);
37 update_highlights();
38 }
39
handle_select_sheet(Sheet * sh)40 void ImpSchematic::handle_select_sheet(Sheet *sh)
41 {
42 if (sh == core_schematic.get_sheet())
43 return;
44
45 auto v = canvas->get_scale_and_offset();
46 sheet_views[core_schematic.get_sheet()->uuid] = v;
47 sheet_selections[core_schematic.get_sheet()->uuid] = canvas->get_selection();
48 auto highlights_saved = highlights;
49 core_schematic.set_sheet(sh->uuid);
50 canvas_update();
51 if (sheet_views.count(sh->uuid)) {
52 auto v2 = sheet_views.at(sh->uuid);
53 canvas->set_scale_and_offset(v2.first, v2.second);
54 }
55 if (sheet_selections.count(sh->uuid)) {
56 canvas->set_selection(sheet_selections.at(sh->uuid));
57 }
58 else {
59 canvas->set_selection({});
60 }
61 highlights = highlights_saved;
62 update_highlights();
63 }
64
handle_remove_sheet(Sheet * sh)65 void ImpSchematic::handle_remove_sheet(Sheet *sh)
66 {
67 core_schematic.delete_sheet(sh->uuid);
68 canvas_update();
69 }
70
handle_next_prev_sheet(const ActionConnection & conn)71 void ImpSchematic::handle_next_prev_sheet(const ActionConnection &conn)
72 {
73 const auto &sch = *core_schematic.get_schematic();
74 const int sheet_idx_current = core_schematic.get_sheet()->index;
75 const int inc = conn.action_id == ActionID::PREV_SHEET ? -1 : 1;
76 const int sheet_idx_next = sheet_idx_current + inc;
77 auto next_sheet = std::find_if(sch.sheets.begin(), sch.sheets.end(),
78 [sheet_idx_next](const auto &x) { return (int)x.second.index == sheet_idx_next; });
79 if (next_sheet != sch.sheets.end()) {
80 sheet_box->select_sheet(next_sheet->second.uuid);
81 }
82 }
83
update_highlights()84 void ImpSchematic::update_highlights()
85 {
86 std::map<UUID, std::set<ObjectRef>> highlights_for_sheet;
87 auto sch = core_schematic.get_schematic();
88 for (const auto &it_sheet : sch->sheets) {
89 auto sheet = &it_sheet.second;
90 for (const auto &it : highlights) {
91 if (it.type == ObjectType::NET) {
92 for (const auto &it_line : sheet->net_lines) {
93 if (it_line.second.net.uuid == it.uuid) {
94 highlights_for_sheet[sheet->uuid].emplace(ObjectType::LINE_NET, it_line.first);
95 }
96 }
97 for (const auto &it_junc : sheet->junctions) {
98 if (it_junc.second.net.uuid == it.uuid) {
99 highlights_for_sheet[sheet->uuid].emplace(ObjectType::JUNCTION, it_junc.first);
100 }
101 }
102 for (const auto &it_label : sheet->net_labels) {
103 if (it_label.second.junction->net.uuid == it.uuid) {
104 highlights_for_sheet[sheet->uuid].emplace(ObjectType::NET_LABEL, it_label.first);
105 }
106 }
107 for (const auto &it_sym : sheet->power_symbols) {
108 if (it_sym.second.junction->net.uuid == it.uuid) {
109 highlights_for_sheet[sheet->uuid].emplace(ObjectType::POWER_SYMBOL, it_sym.first);
110 }
111 }
112 for (const auto &it_sym : sheet->symbols) {
113 auto component = it_sym.second.component;
114 for (const auto &it_pin : it_sym.second.symbol.pins) {
115 UUIDPath<2> connpath(it_sym.second.gate->uuid, it_pin.second.uuid);
116 if (component->connections.count(connpath)) {
117 auto net = component->connections.at(connpath).net;
118 if (net.uuid == it.uuid) {
119 highlights_for_sheet[sheet->uuid].emplace(ObjectType::SYMBOL_PIN, it_pin.first,
120 it_sym.first);
121 }
122 }
123 }
124 }
125 }
126 else if (it.type == ObjectType::COMPONENT) {
127 for (const auto &it_sym : sheet->symbols) {
128 auto component = it_sym.second.component;
129 if (component->uuid == it.uuid) {
130 highlights_for_sheet[sheet->uuid].emplace(ObjectType::SCHEMATIC_SYMBOL, it_sym.first);
131 }
132 }
133 }
134 else if (it.type == ObjectType::SCHEMATIC_SYMBOL) {
135 if (sheet->symbols.count(it.uuid))
136 highlights_for_sheet[sheet->uuid].emplace(it);
137 }
138 else if (it.type == ObjectType::SYMBOL_PIN) {
139 if (sheet->symbols.count(it.uuid2))
140 highlights_for_sheet[sheet->uuid].emplace(it);
141 }
142 }
143 sheet_box->update_highlights(sheet->uuid, highlights_for_sheet[sheet->uuid].size());
144 }
145
146 auto sheet = core_schematic.get_sheet();
147 canvas->set_flags_all(0, TriangleInfo::FLAG_HIGHLIGHT);
148 canvas->set_highlight_enabled(highlights_for_sheet[sheet->uuid].size());
149 for (const auto &it : highlights_for_sheet[sheet->uuid]) {
150 canvas->set_flags(it, TriangleInfo::FLAG_HIGHLIGHT, 0);
151 }
152 }
153
handle_broadcast(const json & j)154 bool ImpSchematic::handle_broadcast(const json &j)
155 {
156 if (!ImpBase::handle_broadcast(j)) {
157 std::string op = j.at("op");
158 guint32 timestamp = j.value("time", 0);
159 if (op == "place-part") {
160 force_end_tool();
161 main_window->present(timestamp);
162 auto data = std::make_unique<ToolAddPart::ToolDataAddPart>(j.at("part").get<std::string>());
163 tool_begin(ToolID::ADD_PART, false, {}, std::move(data));
164 }
165 else if (op == "assign-part" && !core->tool_is_active()) {
166 main_window->present(timestamp);
167 auto data = std::make_unique<ToolAddPart::ToolDataAddPart>(j.at("part").get<std::string>());
168 tool_begin(ToolID::ASSIGN_PART, false, {}, std::move(data));
169 }
170 else if (op == "highlight" && cross_probing_enabled && !core->tool_is_active()) {
171 highlights.clear();
172 const json &o = j["objects"];
173 for (auto it = o.cbegin(); it != o.cend(); ++it) {
174 auto type = static_cast<ObjectType>(it.value().at("type").get<int>());
175 UUID uu(it.value().at("uuid").get<std::string>());
176 highlights.emplace(type, uu);
177 }
178 update_highlights();
179 }
180 else if (op == "backannotate") {
181 auto data = std::make_unique<ToolBackannotateConnectionLines::ToolDataBackannotate>();
182 const json &o = j.at("connections");
183 for (auto it = o.cbegin(); it != o.cend(); ++it) {
184 auto &v = it.value();
185 std::pair<ToolBackannotateConnectionLines::ToolDataBackannotate::Item,
186 ToolBackannotateConnectionLines::ToolDataBackannotate::Item>
187 item;
188 auto &block = *core_schematic.get_block();
189 item.first.from_json(block, v.at("from"));
190 item.second.from_json(block, v.at("to"));
191 if (item.first.is_valid() && item.second.is_valid())
192 data->connections.push_back(item);
193 }
194 if (data->connections.size()) {
195 force_end_tool();
196 main_window->present(timestamp);
197 tool_begin(ToolID::BACKANNOTATE_CONNECTION_LINES, true, {}, std::move(data));
198 }
199 }
200 else if (op == "edit-meta") {
201 force_end_tool();
202 main_window->present(timestamp);
203 tool_begin(ToolID::EDIT_SCHEMATIC_PROPERTIES);
204 }
205 }
206 return true;
207 }
208
handle_selection_cross_probe()209 void ImpSchematic::handle_selection_cross_probe()
210 {
211 json j;
212 j["op"] = "schematic-select";
213 j["selection"] = nullptr;
214 for (const auto &it : canvas->get_selection()) {
215 json k;
216 ObjectType type = ObjectType::INVALID;
217 UUID uu;
218 auto sheet = core_schematic.get_sheet();
219 switch (it.type) {
220 case ObjectType::LINE_NET: {
221 auto &li = sheet->net_lines.at(it.uuid);
222 if (li.net) {
223 type = ObjectType::NET;
224 uu = li.net->uuid;
225 }
226 } break;
227 case ObjectType::NET_LABEL: {
228 auto &la = sheet->net_labels.at(it.uuid);
229 if (la.junction->net) {
230 type = ObjectType::NET;
231 uu = la.junction->net->uuid;
232 }
233 } break;
234 case ObjectType::POWER_SYMBOL: {
235 auto &sym = sheet->power_symbols.at(it.uuid);
236 if (sym.junction->net) {
237 type = ObjectType::NET;
238 uu = sym.junction->net->uuid;
239 }
240 } break;
241 case ObjectType::JUNCTION: {
242 auto &ju = sheet->junctions.at(it.uuid);
243 if (ju.net) {
244 type = ObjectType::NET;
245 uu = ju.net->uuid;
246 }
247 } break;
248 case ObjectType::SCHEMATIC_SYMBOL: {
249 auto &sym = sheet->symbols.at(it.uuid);
250 type = ObjectType::COMPONENT;
251 uu = sym.component->uuid;
252 } break;
253 default:;
254 }
255
256 if (type != ObjectType::INVALID) {
257 k["type"] = static_cast<int>(type);
258 k["uuid"] = (std::string)uu;
259 j["selection"].push_back(k);
260 }
261 }
262 send_json(j);
263 }
264
get_board_pid()265 int ImpSchematic::get_board_pid()
266 {
267 json j;
268 j["op"] = "get-board-pid";
269 return this->send_json(j);
270 }
271
construct()272 void ImpSchematic::construct()
273 {
274 state_store = std::make_unique<WindowStateStore>(main_window, "imp-schematic");
275
276 sheet_box = Gtk::manage(new SheetBox(&core_schematic));
277 sheet_box->show_all();
278 sheet_box->signal_add_sheet().connect([this] {
279 core_schematic.add_sheet();
280 std::cout << "add sheet" << std::endl;
281 });
282 sheet_box->signal_remove_sheet().connect(sigc::mem_fun(*this, &ImpSchematic::handle_remove_sheet));
283 sheet_box->signal_select_sheet().connect(sigc::mem_fun(*this, &ImpSchematic::handle_select_sheet));
284 main_window->left_panel->pack_start(*sheet_box, false, false, 0);
285
286 hamburger_menu->append("Annotate", "win.annotate");
287 add_tool_action(ToolID::ANNOTATE, "annotate");
288
289 hamburger_menu->append("Buses…", "win.manage_buses");
290 add_tool_action(ToolID::MANAGE_BUSES, "manage_buses");
291
292 hamburger_menu->append("Net classes…", "win.manage_nc");
293 add_tool_action(ToolID::MANAGE_NET_CLASSES, "manage_nc");
294
295 hamburger_menu->append("Power Nets…", "win.manage_pn");
296 add_tool_action(ToolID::MANAGE_POWER_NETS, "manage_pn");
297
298 hamburger_menu->append("Schematic properties", "win.sch_properties");
299 add_tool_action(ToolID::EDIT_SCHEMATIC_PROPERTIES, "sch_properties");
300
301 hamburger_menu->append("BOM Export", "win.bom_export");
302 main_window->add_action("bom_export", [this] { trigger_action(ActionID::BOM_EXPORT_WINDOW); });
303
304 hamburger_menu->append("PDF Export", "win.export_pdf");
305
306 main_window->add_action("export_pdf", [this] { trigger_action(ActionID::PDF_EXPORT_WINDOW); });
307
308 if (sockets_connected) {
309 hamburger_menu->append("Cross probing", "win.cross_probing");
310 auto cp_action = main_window->add_action_bool("cross_probing", true);
311 cross_probing_enabled = true;
312 cp_action->signal_change_state().connect([this, cp_action](const Glib::VariantBase &v) {
313 cross_probing_enabled = Glib::VariantBase::cast_dynamic<Glib::Variant<bool>>(v).get();
314 g_simple_action_set_state(cp_action->gobj(), g_variant_new_boolean(cross_probing_enabled));
315 if (!cross_probing_enabled && !core_schematic.tool_is_active()) {
316 highlights.clear();
317 update_highlights();
318 }
319 });
320 }
321
322 canvas->set_highlight_mode(CanvasGL::HighlightMode::DIM);
323
324 connect_action(ActionID::PLACE_PART, [this](const auto &conn) {
325 if (!sockets_connected) {
326 this->tool_begin(ToolID::ADD_PART);
327 }
328 else {
329 json j;
330 j["op"] = "show-browser";
331 j["time"] = gtk_get_current_event_time();
332 allow_set_foreground_window(mgr_pid);
333 this->send_json(j);
334 }
335 });
336
337 connect_action(ActionID::PREV_SHEET, sigc::mem_fun(*this, &ImpSchematic::handle_next_prev_sheet));
338 connect_action(ActionID::NEXT_SHEET, sigc::mem_fun(*this, &ImpSchematic::handle_next_prev_sheet));
339
340 if (sockets_connected) {
341 connect_action(ActionID::TO_BOARD, [this](const auto &conn) {
342 json j;
343 j["op"] = "to-board";
344 j["time"] = gtk_get_current_event_time();
345 j["selection"] = nullptr;
346 for (const auto &it : canvas->get_selection()) {
347 auto sheet = core_schematic.get_sheet();
348 if (it.type == ObjectType::SCHEMATIC_SYMBOL) {
349 auto &sym = sheet->symbols.at(it.uuid);
350 json k;
351 k["type"] = static_cast<int>(ObjectType::COMPONENT);
352 k["uuid"] = (std::string)sym.component->uuid;
353 j["selection"].push_back(k);
354 }
355 }
356 canvas->set_selection({});
357 allow_set_foreground_window(this->get_board_pid());
358 this->send_json(j);
359 });
360 set_action_sensitive(make_action(ActionID::TO_BOARD), false);
361
362 connect_action(ActionID::SHOW_IN_BROWSER, [this](const auto &conn) {
363 for (const auto &it : canvas->get_selection()) {
364 auto sheet = core_schematic.get_sheet();
365 if (it.type == ObjectType::SCHEMATIC_SYMBOL) {
366 auto &sym = sheet->symbols.at(it.uuid);
367 if (sym.component->part) {
368 auto ev = gtk_get_current_event();
369 json j;
370 j["op"] = "show-in-browser";
371 j["part"] = (std::string)sym.component->part->uuid;
372 j["time"] = gdk_event_get_time(ev);
373 this->send_json(j);
374 break;
375 }
376 }
377 }
378 });
379
380 connect_action(ActionID::SAVE_RELOAD_NETLIST, [this](const auto &conn) {
381 this->trigger_action(ActionID::SAVE);
382 json j;
383 j["time"] = gtk_get_current_event_time();
384 j["op"] = "reload-netlist";
385 this->send_json(j);
386 });
387 set_action_sensitive(make_action(ActionID::SAVE_RELOAD_NETLIST), false);
388
389 connect_action(ActionID::GO_TO_BOARD, [this](const auto &conn) {
390 json j;
391 j["time"] = gtk_get_current_event_time();
392 j["op"] = "present-board";
393 auto board_pid = this->get_board_pid();
394 if (board_pid != -1)
395 allow_set_foreground_window(board_pid);
396 this->send_json(j);
397 });
398
399 connect_action(ActionID::SHOW_IN_POOL_MANAGER, [this](const auto &conn) {
400 for (const auto &it : canvas->get_selection()) {
401 auto sheet = core_schematic.get_sheet();
402 if (it.type == ObjectType::SCHEMATIC_SYMBOL) {
403 auto &sym = sheet->symbols.at(it.uuid);
404 if (sym.component->part) {
405 json j;
406 j["op"] = "show-in-pool-mgr";
407 j["type"] = "part";
408 UUID pool_uuid;
409 pool->get_filename(ObjectType::PART, sym.component->part->uuid, &pool_uuid);
410 j["pool_uuid"] = (std::string)pool_uuid;
411 j["uuid"] = (std::string)sym.component->part->uuid;
412 this->send_json(j);
413 break;
414 }
415 }
416 }
417 });
418 set_action_sensitive(make_action(ActionID::SHOW_IN_POOL_MANAGER), false);
419 }
420
421 connect_action(ActionID::MOVE_TO_OTHER_SHEET,
422 std::bind(&ImpSchematic::handle_move_to_other_sheet, this, std::placeholders::_1));
423
424 connect_action(ActionID::HIGHLIGHT_NET, [this](const auto &a) {
425 highlights.clear();
426 for (const auto &it : canvas->get_selection()) {
427 if (auto uu = net_from_selectable(it)) {
428 highlights.emplace(ObjectType::NET, uu);
429 }
430 }
431 this->update_highlights();
432 });
433
434 connect_action(ActionID::HIGHLIGHT_NET_CLASS, [this](const auto &a) {
435 highlights.clear();
436 for (const auto &it : canvas->get_selection()) {
437 if (auto uu = net_from_selectable(it)) {
438 const auto &net_sel = core_schematic.get_block()->nets.at(uu);
439 for (const auto &[net_uu, net] : core_schematic.get_block()->nets) {
440 if (net.net_class == net_sel.net_class)
441 highlights.emplace(ObjectType::NET, net_uu);
442 }
443 }
444 }
445 this->update_highlights();
446 });
447
448 connect_action(ActionID::HIGHLIGHT_GROUP, sigc::mem_fun(*this, &ImpSchematic::handle_highlight_group_tag));
449 connect_action(ActionID::HIGHLIGHT_TAG, sigc::mem_fun(*this, &ImpSchematic::handle_highlight_group_tag));
450
451 bom_export_window = BOMExportWindow::create(main_window, *core_schematic.get_block(),
452 *core_schematic.get_bom_export_settings(), *pool.get(), project_dir);
453
454 connect_action(ActionID::BOM_EXPORT_WINDOW, [this](const auto &c) { bom_export_window->present(); });
455 connect_action(ActionID::EXPORT_BOM, [this](const auto &c) {
456 bom_export_window->present();
457 bom_export_window->generate();
458 });
459
460 bom_export_window->signal_changed().connect([this] { core_schematic.set_needs_save(); });
461 core->signal_tool_changed().connect([this](ToolID t) { bom_export_window->set_can_export(t == ToolID::NONE); });
462 core->signal_rebuilt().connect([this] { bom_export_window->update(); });
463
464 pdf_export_window = PDFExportWindow::create(main_window, core_schematic, *core_schematic.get_pdf_export_settings(),
465 project_dir);
466 pdf_export_window->signal_changed().connect([this] { core_schematic.set_needs_save(); });
467 connect_action(ActionID::PDF_EXPORT_WINDOW, [this](const auto &c) { pdf_export_window->present(); });
468 connect_action(ActionID::EXPORT_PDF, [this](const auto &c) {
469 pdf_export_window->present();
470 pdf_export_window->generate();
471 });
472
473 unplaced_box = Gtk::manage(new UnplacedBox("Symbol"));
474 unplaced_box->show();
475 main_window->left_panel->pack_end(*unplaced_box, true, true, 0);
476 unplaced_box->signal_place().connect([this](const auto &items) {
477 auto d = std::make_unique<ToolMapSymbol::ToolDataMapSymbol>(items);
478 this->tool_begin(ToolID::MAP_SYMBOL, false, {}, std::move(d));
479 });
480 core_schematic.signal_rebuilt().connect(sigc::mem_fun(*this, &ImpSchematic::update_unplaced));
481 update_unplaced();
482 core_schematic.signal_tool_changed().connect(
483 [this](ToolID tool_id) { unplaced_box->set_sensitive(tool_id == ToolID::NONE); });
484
485 grid_controller->disable();
486 canvas->snap_to_targets = false;
487
488 connect_action(ActionID::TOGGLE_SNAP_TO_TARGETS, [this](const ActionConnection &c) {
489 canvas->snap_to_targets = !canvas->snap_to_targets;
490 g_simple_action_set_state(toggle_snap_to_targets_action->gobj(),
491 g_variant_new_boolean(canvas->snap_to_targets));
492 });
493 view_options_menu_append_action("Snap to targets", "win.snap_to_targets");
494
495 toggle_snap_to_targets_action = main_window->add_action_bool("snap_to_targets", canvas->snap_to_targets);
496 toggle_snap_to_targets_action->signal_change_state().connect([this](const Glib::VariantBase &v) {
497 auto b = Glib::VariantBase::cast_dynamic<Glib::Variant<bool>>(v).get();
498 if (b != canvas->snap_to_targets) {
499 trigger_action(ActionID::TOGGLE_SNAP_TO_TARGETS);
500 }
501 });
502
503
504 rules_window->signal_goto().connect([this](Coordi location, UUID sheet) {
505 auto sch = core_schematic.get_schematic();
506 if (sch->sheets.count(sheet)) {
507 sheet_box->select_sheet(sheet);
508 canvas->center_and_zoom(location);
509 }
510 });
511
512 canvas->signal_motion_notify_event().connect([this](GdkEventMotion *ev) {
513 if (target_drag_begin.type != ObjectType::INVALID) {
514 handle_drag();
515 }
516 return false;
517 });
518
519 canvas->signal_button_release_event().connect([this](GdkEventButton *ev) {
520 target_drag_begin = Target();
521 return false;
522 });
523
524 main_window->signal_activate_hud_link().connect(
525 [this](const std::string &url) {
526 if (url.find("s:") == 0) {
527 std::string sheet = url.substr(2);
528 auto uuid = UUID(sheet);
529 auto sch = core_schematic.get_schematic();
530 if (sch->sheets.count(uuid)) {
531 sheet_box->select_sheet(uuid);
532 }
533 return true;
534 }
535 return false;
536 },
537 false);
538
539 add_action_button(make_action(ActionID::PLACE_PART));
540 add_action_button(make_action(ToolID::DRAW_NET));
541 {
542 auto &b = add_action_button(make_action(ToolID::PLACE_NET_LABEL));
543 b.add_action(make_action(ToolID::PLACE_BUS_LABEL));
544 b.add_action(make_action(ToolID::PLACE_BUS_RIPPER));
545 }
546 add_action_button(make_action(ToolID::PLACE_POWER_SYMBOL));
547 add_action_button_line();
548 add_action_button(make_action(ToolID::PLACE_TEXT));
549
550 update_monitor();
551
552 if (!core_schematic.get_project_meta_loaded_from_block())
553 core_schematic.set_needs_save();
554 }
555
update_action_sensitivity()556 void ImpSchematic::update_action_sensitivity()
557 {
558 auto sel = canvas->get_selection();
559 if (sockets_connected) {
560 json req;
561 req["op"] = "has-board";
562 bool has_board = send_json(req);
563 set_action_sensitive(make_action(ActionID::SAVE_RELOAD_NETLIST), has_board);
564 auto n_sym = std::count_if(sel.begin(), sel.end(),
565 [](const auto &x) { return x.type == ObjectType::SCHEMATIC_SYMBOL; });
566 set_action_sensitive(make_action(ActionID::SHOW_IN_BROWSER), n_sym == 1);
567 set_action_sensitive(make_action(ActionID::SHOW_IN_POOL_MANAGER), n_sym == 1);
568 if (!has_board) {
569 set_action_sensitive(make_action(ActionID::TO_BOARD), false);
570 }
571 else {
572 set_action_sensitive(make_action(ActionID::TO_BOARD), n_sym);
573 }
574 }
575 else {
576 set_action_sensitive(make_action(ActionID::TO_BOARD), false);
577 set_action_sensitive(make_action(ActionID::SHOW_IN_BROWSER), false);
578 set_action_sensitive(make_action(ActionID::SHOW_IN_POOL_MANAGER), false);
579 }
580 set_action_sensitive(make_action(ActionID::MOVE_TO_OTHER_SHEET), sel.size() > 0);
581 set_action_sensitive(make_action(ActionID::GO_TO_BOARD), sockets_connected);
582
583 const bool can_highlight_net = std::any_of(sel.begin(), sel.end(), [](const auto &x) {
584 switch (x.type) {
585 case ObjectType::LINE_NET:
586 case ObjectType::NET_LABEL:
587 case ObjectType::JUNCTION:
588 case ObjectType::POWER_SYMBOL:
589 return true;
590
591 default:
592 return false;
593 }
594 });
595 set_action_sensitive(make_action(ActionID::HIGHLIGHT_NET), can_highlight_net);
596 set_action_sensitive(make_action(ActionID::HIGHLIGHT_NET_CLASS), can_highlight_net);
597 bool can_higlight_group = false;
598 bool can_higlight_tag = false;
599 if (sel.size() == 1 && (*sel.begin()).type == ObjectType::SCHEMATIC_SYMBOL) {
600 auto uu = (*sel.begin()).uuid;
601 if (core_schematic.get_sheet()->symbols.count(uu)) {
602 auto comp = core_schematic.get_schematic_symbol(uu)->component;
603 can_higlight_group = comp->group;
604 can_higlight_tag = comp->tag;
605 }
606 }
607
608 set_action_sensitive(make_action(ActionID::HIGHLIGHT_GROUP), can_higlight_group);
609 set_action_sensitive(make_action(ActionID::HIGHLIGHT_TAG), can_higlight_tag);
610
611 ImpBase::update_action_sensitivity();
612 }
613
net_from_selectable(const SelectableRef & sr)614 UUID ImpSchematic::net_from_selectable(const SelectableRef &sr)
615 {
616 const auto &sheet = *core_schematic.get_sheet();
617 switch (sr.type) {
618 case ObjectType::LINE_NET: {
619 auto &li = sheet.net_lines.at(sr.uuid);
620 if (li.net) {
621 return li.net->uuid;
622 }
623 } break;
624 case ObjectType::NET_LABEL: {
625 auto &la = sheet.net_labels.at(sr.uuid);
626 if (la.junction->net) {
627 return la.junction->net->uuid;
628 }
629 } break;
630 case ObjectType::POWER_SYMBOL: {
631 auto &sym = sheet.power_symbols.at(sr.uuid);
632 if (sym.junction->net) {
633 return sym.junction->net->uuid;
634 }
635 } break;
636 case ObjectType::JUNCTION: {
637 auto &ju = sheet.junctions.at(sr.uuid);
638 if (ju.net) {
639 return ju.net->uuid;
640 }
641 } break;
642 default:;
643 }
644 return UUID();
645 }
646
get_hud_text(std::set<SelectableRef> & sel)647 std::string ImpSchematic::get_hud_text(std::set<SelectableRef> &sel)
648 {
649 std::string s;
650 if (auto it = sel_find_exactly_one(sel, ObjectType::SCHEMATIC_SYMBOL)) {
651 const auto &sym = core_schematic.get_sheet()->symbols.at(it->uuid);
652 s += "<b>Symbol " + sym.component->refdes + "</b>\n";
653 s += get_hud_text_for_component(sym.component);
654 sel_erase_type(sel, ObjectType::SCHEMATIC_SYMBOL);
655 }
656
657 if (auto it = sel_find_exactly_one(sel, ObjectType::TEXT)) {
658 const auto text = core->get_text(it->uuid);
659 const auto txt = Glib::ustring(text->text);
660 Glib::MatchInfo ma;
661 if (core_schematic.get_schematic()->get_sheetref_regex()->match(txt, ma)) {
662 s += "\n\n<b>Text with sheet references</b>\n";
663 do {
664 auto uuid = ma.fetch(1);
665 std::string url = "s:" + uuid;
666 if (core_schematic.get_schematic()->sheets.count(UUID(uuid))) {
667 s += make_link_markup(url, core_schematic.get_schematic()->sheets.at(UUID(uuid)).name);
668 }
669 else {
670 s += "Unknown Sheet";
671 }
672 s += "\n";
673 } while (ma.next());
674 sel_erase_type(sel, ObjectType::TEXT);
675 }
676 }
677 trim(s);
678 return s;
679 }
680
handle_core_rebuilt()681 void ImpSchematic::handle_core_rebuilt()
682 {
683 sheet_box->update();
684 }
685
handle_tool_change(ToolID id)686 void ImpSchematic::handle_tool_change(ToolID id)
687 {
688 ImpBase::handle_tool_change(id);
689 sheet_box->set_sensitive(id == ToolID::NONE);
690 }
691
handle_highlight_group_tag(const ActionConnection & a)692 void ImpSchematic::handle_highlight_group_tag(const ActionConnection &a)
693 {
694 bool tag_mode = a.action_id == ActionID::HIGHLIGHT_TAG;
695 auto sel = canvas->get_selection();
696 if (sel.size() == 1 && (*sel.begin()).type == ObjectType::SCHEMATIC_SYMBOL) {
697 auto comp = core_schematic.get_schematic_symbol((*sel.begin()).uuid)->component;
698 UUID uu = tag_mode ? comp->tag : comp->group;
699 if (!uu)
700 return;
701 highlights.clear();
702 for (const auto &it_sheet : core_schematic.get_schematic()->sheets) {
703 for (const auto &it_sym : it_sheet.second.symbols) {
704 if ((tag_mode && (it_sym.second.component->tag == uu))
705 || (!tag_mode && (it_sym.second.component->group == uu))) {
706 highlights.emplace(ObjectType::COMPONENT, it_sym.second.component->uuid);
707 }
708 }
709 }
710 this->update_highlights();
711 }
712 }
713
handle_maybe_drag(bool ctrl)714 void ImpSchematic::handle_maybe_drag(bool ctrl)
715 {
716 if (!preferences.schematic.drag_start_net_line) {
717 ImpBase::handle_maybe_drag(ctrl);
718 return;
719 }
720
721 auto target = canvas->get_current_target();
722 if (target.type == ObjectType::SYMBOL_PIN || target.type == ObjectType::JUNCTION) {
723 std::cout << "click pin" << std::endl;
724 canvas->inhibit_drag_selection();
725 target_drag_begin = target;
726 cursor_pos_drag_begin = canvas->get_cursor_pos_win();
727 }
728 else {
729 ImpBase::handle_maybe_drag(ctrl);
730 }
731 }
732
drag_does_start(const Coordf & delta,Orientation orientation)733 static bool drag_does_start(const Coordf &delta, Orientation orientation)
734 {
735 float thr = 50;
736 switch (orientation) {
737 case Orientation::DOWN:
738 return delta.y > thr;
739
740 case Orientation::UP:
741 return -delta.y > thr;
742
743 case Orientation::RIGHT:
744 return delta.x > thr;
745
746 case Orientation::LEFT:
747 return -delta.x > thr;
748
749 default:
750 return false;
751 }
752 }
753
handle_drag()754 void ImpSchematic::handle_drag()
755 {
756 auto pos = canvas->get_cursor_pos_win();
757 auto delta = pos - cursor_pos_drag_begin;
758 bool start = false;
759
760 if (target_drag_begin.type == ObjectType::SYMBOL_PIN) {
761 const auto sym = core_schematic.get_schematic_symbol(target_drag_begin.path.at(0));
762 const auto &pin = sym->symbol.pins.at(target_drag_begin.path.at(1));
763 auto orientation = pin.get_orientation_for_placement(sym->placement);
764 start = drag_does_start(delta, orientation);
765 }
766 else if (target_drag_begin.type == ObjectType::JUNCTION) {
767 start = delta.mag_sq() > (50 * 50);
768 }
769
770 if (start) {
771 {
772 highlights.clear();
773 update_highlights();
774 ToolArgs args;
775 args.coords = target_drag_begin.p;
776 ToolResponse r = core->tool_begin(ToolID::DRAW_NET, args, imp_interface.get());
777 tool_process(r);
778 }
779 {
780 ToolArgs args;
781 args.type = ToolEventType::ACTION;
782 args.coords = target_drag_begin.p;
783 args.action = InToolActionID::LMB;
784 args.target = target_drag_begin;
785 args.work_layer = canvas->property_work_layer();
786 ToolResponse r = core->tool_update(args);
787 tool_process(r);
788 }
789 target_drag_begin = Target();
790 }
791 }
792
search_center(const Searcher::SearchResult & res)793 void ImpSchematic::search_center(const Searcher::SearchResult &res)
794 {
795 if (res.sheet != core_schematic.get_sheet()->uuid) {
796 sheet_box->select_sheet(res.sheet);
797 }
798 ImpBase::search_center(res);
799 }
800
801 class SelectSheetDialog : public Gtk::Dialog {
802 public:
803 SelectSheetDialog(const Schematic *sch, const Sheet *skip);
804 UUID selected_sheet;
805
806 private:
807 const Schematic *sch;
808 };
809
810 class MyLabel : public Gtk::Label {
811 public:
MyLabel(const std::string & txt,const UUID & uu)812 MyLabel(const std::string &txt, const UUID &uu) : Gtk::Label(txt), uuid(uu)
813 {
814 set_xalign(0);
815 property_margin() = 5;
816 }
817
818 const UUID uuid;
819 };
820
SelectSheetDialog(const Schematic * s,const Sheet * skip)821 SelectSheetDialog::SelectSheetDialog(const Schematic *s, const Sheet *skip)
822 : Gtk::Dialog("Select sheet", Gtk::DIALOG_MODAL | Gtk::DIALOG_USE_HEADER_BAR), sch(s)
823 {
824 auto sc = Gtk::manage(new Gtk::ScrolledWindow);
825 sc->set_propagate_natural_height(true);
826 sc->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
827
828 auto lb = Gtk::manage(new Gtk::ListBox);
829 lb->set_selection_mode(Gtk::SELECTION_NONE);
830 lb->set_activate_on_single_click(true);
831 lb->set_header_func(sigc::ptr_fun(header_func_separator));
832 sc->add(*lb);
833
834 std::vector<const Sheet *> sheets;
835 for (const auto &it : sch->sheets) {
836 sheets.push_back(&it.second);
837 }
838 std::sort(sheets.begin(), sheets.end(), [](auto a, auto b) { return a->index < b->index; });
839
840 for (const auto it : sheets) {
841 if (it != skip) {
842 auto la = Gtk::manage(new MyLabel(std::to_string(it->index) + " " + it->name, it->uuid));
843 lb->append(*la);
844 }
845 }
846 lb->signal_row_activated().connect([this](Gtk::ListBoxRow *row) {
847 auto la = dynamic_cast<MyLabel *>(row->get_child());
848 selected_sheet = la->uuid;
849 response(Gtk::RESPONSE_OK);
850 });
851
852 sc->show_all();
853 get_content_area()->set_border_width(0);
854 get_content_area()->pack_start(*sc, true, true, 0);
855 }
856
handle_move_to_other_sheet(const ActionConnection & conn)857 void ImpSchematic::handle_move_to_other_sheet(const ActionConnection &conn)
858 {
859 bool added = true;
860 auto selection = canvas->get_selection();
861 // try to find everything that's connected to the selection in some way
862 while (added) {
863 std::set<SelectableRef> new_sel;
864 for (const auto &it : selection) {
865 switch (it.type) {
866 case ObjectType::NET_LABEL: {
867 auto &la = core_schematic.get_sheet()->net_labels.at(it.uuid);
868 new_sel.emplace(la.junction->uuid, ObjectType::JUNCTION);
869 } break;
870 case ObjectType::BUS_LABEL: {
871 auto &la = core_schematic.get_sheet()->bus_labels.at(it.uuid);
872 new_sel.emplace(la.junction->uuid, ObjectType::JUNCTION);
873 } break;
874 case ObjectType::POWER_SYMBOL: {
875 auto &ps = core_schematic.get_sheet()->power_symbols.at(it.uuid);
876 new_sel.emplace(ps.junction->uuid, ObjectType::JUNCTION);
877 } break;
878 case ObjectType::BUS_RIPPER: {
879 auto &rip = core_schematic.get_sheet()->bus_rippers.at(it.uuid);
880 new_sel.emplace(rip.junction->uuid, ObjectType::JUNCTION);
881 } break;
882
883 case ObjectType::LINE_NET: {
884 auto line = &core_schematic.get_sheet()->net_lines.at(it.uuid);
885 for (auto &it_ft : {line->from, line->to}) {
886 if (it_ft.is_junc()) {
887 new_sel.emplace(it_ft.junc->uuid, ObjectType::JUNCTION);
888 }
889 else if (it_ft.is_bus_ripper()) {
890 new_sel.emplace(it_ft.bus_ripper->uuid, ObjectType::BUS_RIPPER);
891 }
892 else if (it_ft.is_pin()) {
893 new_sel.emplace(it_ft.symbol->uuid, ObjectType::SCHEMATIC_SYMBOL);
894 }
895 }
896 } break;
897
898 case ObjectType::LINE: {
899 auto line = &core_schematic.get_sheet()->lines.at(it.uuid);
900 for (auto &it_ft : {line->from, line->to}) {
901 new_sel.emplace(it_ft->uuid, ObjectType::JUNCTION);
902 }
903 } break;
904
905 case ObjectType::ARC: {
906 auto arc = &core_schematic.get_sheet()->arcs.at(it.uuid);
907 for (auto &it_ft : {arc->from, arc->to, arc->center}) {
908 new_sel.emplace(it_ft->uuid, ObjectType::JUNCTION);
909 }
910 } break;
911
912 case ObjectType::SCHEMATIC_SYMBOL: {
913 auto sym = core_schematic.get_schematic_symbol(it.uuid);
914 for (const auto &itt : sym->texts) {
915 new_sel.emplace(itt->uuid, ObjectType::TEXT);
916 }
917 } break;
918
919 default:;
920 }
921 }
922
923 // other direction
924 for (const auto &it : core_schematic.get_sheet()->net_labels) {
925 if (selection.count(SelectableRef(it.second.junction->uuid, ObjectType::JUNCTION))) {
926 new_sel.emplace(it.first, ObjectType::NET_LABEL);
927 }
928 }
929 for (const auto &it : core_schematic.get_sheet()->bus_labels) {
930 if (selection.count(SelectableRef(it.second.junction->uuid, ObjectType::JUNCTION))) {
931 new_sel.emplace(it.first, ObjectType::BUS_LABEL);
932 }
933 }
934 for (const auto &it : core_schematic.get_sheet()->bus_rippers) {
935 if (selection.count(SelectableRef(it.second.junction->uuid, ObjectType::JUNCTION))) {
936 new_sel.emplace(it.first, ObjectType::BUS_RIPPER);
937 }
938 }
939 for (const auto &it : core_schematic.get_sheet()->power_symbols) {
940 if (selection.count(SelectableRef(it.second.junction->uuid, ObjectType::JUNCTION))) {
941 new_sel.emplace(it.first, ObjectType::POWER_SYMBOL);
942 }
943 }
944 for (const auto &it : core_schematic.get_sheet()->net_lines) {
945 const auto line = it.second;
946 bool add_line = false;
947 for (auto &it_ft : {line.from, line.to}) {
948 if (it_ft.is_junc()) {
949 if (selection.count(SelectableRef(it_ft.junc->uuid, ObjectType::JUNCTION))) {
950 add_line = true;
951 }
952 }
953 else if (it_ft.is_bus_ripper()) {
954 if (selection.count(SelectableRef(it_ft.bus_ripper->uuid, ObjectType::BUS_RIPPER))) {
955 add_line = true;
956 }
957 }
958 else if (it_ft.is_pin()) {
959 if (selection.count(SelectableRef(it_ft.symbol->uuid, ObjectType::SCHEMATIC_SYMBOL))) {
960 add_line = true;
961 }
962 }
963 }
964 if (add_line) {
965 new_sel.emplace(it.first, ObjectType::LINE_NET);
966 }
967 }
968 for (const auto &it : core_schematic.get_sheet()->lines) {
969 for (const auto &it_ft : {it.second.from, it.second.to}) {
970 if (selection.count(SelectableRef(it_ft->uuid, ObjectType::JUNCTION))) {
971 new_sel.emplace(it.first, ObjectType::LINE);
972 }
973 }
974 }
975 for (const auto &it : core_schematic.get_sheet()->arcs) {
976 for (const auto &it_ft : {it.second.from, it.second.to, it.second.center}) {
977 if (selection.count(SelectableRef(it_ft->uuid, ObjectType::JUNCTION))) {
978 new_sel.emplace(it.first, ObjectType::ARC);
979 }
980 }
981 }
982
983 added = false;
984 for (const auto &it : new_sel) {
985 if (selection.insert(it).second) {
986 added = true;
987 }
988 }
989 }
990 canvas->set_selection(selection);
991
992 auto old_sheet = core_schematic.get_sheet();
993 Sheet *new_sheet = nullptr;
994 {
995 SelectSheetDialog dia(core_schematic.get_schematic(), old_sheet);
996 dia.set_transient_for(*main_window);
997 if (dia.run() == Gtk::RESPONSE_OK) {
998 new_sheet = &core_schematic.get_schematic()->sheets.at(dia.selected_sheet);
999 }
1000 }
1001 if (!new_sheet)
1002 return;
1003 sheet_box->select_sheet(new_sheet->uuid);
1004 assert(core_schematic.get_sheet() == new_sheet);
1005
1006 // actually move things to new sheet
1007 for (const auto &it : selection) {
1008 switch (it.type) {
1009 case ObjectType::NET_LABEL: {
1010 new_sheet->net_labels.insert(std::make_pair(it.uuid, std::move(old_sheet->net_labels.at(it.uuid))));
1011 old_sheet->net_labels.erase(it.uuid);
1012 } break;
1013 case ObjectType::BUS_LABEL: {
1014 new_sheet->bus_labels.insert(std::make_pair(it.uuid, std::move(old_sheet->bus_labels.at(it.uuid))));
1015 old_sheet->bus_labels.erase(it.uuid);
1016 } break;
1017 case ObjectType::BUS_RIPPER: {
1018 new_sheet->bus_rippers.insert(std::make_pair(it.uuid, std::move(old_sheet->bus_rippers.at(it.uuid))));
1019 old_sheet->bus_rippers.erase(it.uuid);
1020 } break;
1021 case ObjectType::JUNCTION: {
1022 new_sheet->junctions.insert(std::make_pair(it.uuid, std::move(old_sheet->junctions.at(it.uuid))));
1023 old_sheet->junctions.erase(it.uuid);
1024 } break;
1025 case ObjectType::POWER_SYMBOL: {
1026 new_sheet->power_symbols.insert(std::make_pair(it.uuid, std::move(old_sheet->power_symbols.at(it.uuid))));
1027 old_sheet->power_symbols.erase(it.uuid);
1028 } break;
1029 case ObjectType::LINE_NET: {
1030 new_sheet->net_lines.insert(std::make_pair(it.uuid, std::move(old_sheet->net_lines.at(it.uuid))));
1031 old_sheet->net_lines.erase(it.uuid);
1032 } break;
1033 case ObjectType::SCHEMATIC_SYMBOL: {
1034 new_sheet->symbols.insert(std::make_pair(it.uuid, std::move(old_sheet->symbols.at(it.uuid))));
1035 old_sheet->symbols.erase(it.uuid);
1036 } break;
1037 case ObjectType::TEXT: {
1038 new_sheet->texts.insert(std::make_pair(it.uuid, std::move(old_sheet->texts.at(it.uuid))));
1039 old_sheet->texts.erase(it.uuid);
1040 } break;
1041 case ObjectType::LINE: {
1042 new_sheet->lines.insert(std::make_pair(it.uuid, std::move(old_sheet->lines.at(it.uuid))));
1043 old_sheet->lines.erase(it.uuid);
1044 } break;
1045 case ObjectType::ARC: {
1046 new_sheet->arcs.insert(std::make_pair(it.uuid, std::move(old_sheet->arcs.at(it.uuid))));
1047 old_sheet->arcs.erase(it.uuid);
1048 } break;
1049
1050 default:;
1051 }
1052 }
1053 core_schematic.get_schematic()->update_refs();
1054
1055 core_schematic.set_needs_save();
1056 core_schematic.rebuild();
1057 canvas_update();
1058 canvas->set_selection(selection);
1059 tool_begin(ToolID::MOVE);
1060 }
1061
get_doubleclick_action(ObjectType type,const UUID & uu)1062 ActionToolID ImpSchematic::get_doubleclick_action(ObjectType type, const UUID &uu)
1063 {
1064 auto a = ImpBase::get_doubleclick_action(type, uu);
1065 if (a.first != ActionID::NONE)
1066 return a;
1067 switch (type) {
1068 case ObjectType::NET_LABEL:
1069 case ObjectType::LINE_NET:
1070 return make_action(ToolID::ENTER_DATUM);
1071 break;
1072 default:
1073 return {ActionID::NONE, ToolID::NONE};
1074 }
1075 }
1076
update_unplaced()1077 void ImpSchematic::update_unplaced()
1078 {
1079 unplaced_box->update(core_schematic.get_schematic()->get_unplaced_gates());
1080 }
1081
get_tool_for_drag_move(bool ctrl,const std::set<SelectableRef> & sel) const1082 ToolID ImpSchematic::get_tool_for_drag_move(bool ctrl, const std::set<SelectableRef> &sel) const
1083 {
1084 if (preferences.schematic.bend_non_ortho && sel.size() == 1 && sel.begin()->type == ObjectType::LINE_NET) {
1085 const auto &ln = core_schematic.get_sheet()->net_lines.at(sel.begin()->uuid);
1086 auto from = ln.from.get_position();
1087 auto to = ln.to.get_position();
1088 if (!((from.x == to.x) || (from.y == to.y))) {
1089 return ToolID::BEND_LINE_NET;
1090 }
1091 }
1092 return ImpBase::get_tool_for_drag_move(ctrl, sel);
1093 }
1094
handle_extra_button(const GdkEventButton * button_event)1095 void ImpSchematic::handle_extra_button(const GdkEventButton *button_event)
1096 {
1097 if (!preferences.mouse.switch_sheets)
1098 return;
1099
1100 switch (button_event->button) {
1101 case 6:
1102 case 8:
1103 trigger_action(ActionID::NEXT_SHEET);
1104 break;
1105
1106 case 7:
1107 case 9:
1108 trigger_action(ActionID::PREV_SHEET);
1109 break;
1110
1111 default:;
1112 }
1113 }
1114
expand_selection_for_property_panel(std::set<SelectableRef> & sel_extra,const std::set<SelectableRef> & sel)1115 void ImpSchematic::expand_selection_for_property_panel(std::set<SelectableRef> &sel_extra,
1116 const std::set<SelectableRef> &sel)
1117 {
1118 const auto &sheet = *core_schematic.get_sheet();
1119 for (const auto &it : sel) {
1120 switch (it.type) {
1121 case ObjectType::SCHEMATIC_SYMBOL:
1122 sel_extra.emplace(core_schematic.get_schematic_symbol(it.uuid)->component->uuid, ObjectType::COMPONENT);
1123 break;
1124 case ObjectType::JUNCTION:
1125 if (sheet.junctions.at(it.uuid).net) {
1126 sel_extra.emplace(sheet.junctions.at(it.uuid).net->uuid, ObjectType::NET);
1127 }
1128 break;
1129 case ObjectType::LINE_NET: {
1130 LineNet &li = core_schematic.get_sheet()->net_lines.at(it.uuid);
1131 if (li.net) {
1132 sel_extra.emplace(li.net->uuid, ObjectType::NET);
1133 }
1134 } break;
1135 case ObjectType::NET_LABEL: {
1136 NetLabel &la = core_schematic.get_sheet()->net_labels.at(it.uuid);
1137 if (la.junction->net) {
1138 sel_extra.emplace(la.junction->net->uuid, ObjectType::NET);
1139 }
1140 } break;
1141 case ObjectType::POWER_SYMBOL: {
1142 PowerSymbol &sym = core_schematic.get_sheet()->power_symbols.at(it.uuid);
1143 if (sym.net) {
1144 sel_extra.emplace(sym.net->uuid, ObjectType::NET);
1145 }
1146 } break;
1147 default:;
1148 }
1149 }
1150 }
1151
update_monitor()1152 void ImpSchematic::update_monitor()
1153 {
1154 ItemSet mon_items = core_schematic.get_block()->get_pool_items_used();
1155 {
1156 ItemSet items = core_schematic.get_schematic()->get_pool_items_used();
1157 mon_items.insert(items.begin(), items.end());
1158 }
1159 set_monitor_items(mon_items);
1160 }
1161
1162 } // namespace horizon
1163