From 6fdad4649abce8270c6c6f51f1da332afd3e8437 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 16 Aug 2025 21:44:41 +0200 Subject: [PATCH] WIP --- src/edt/edt/edtMainService.cc | 42 ++++++++++++++++- src/edt/edt/edtMainService.h | 7 ++- src/edt/edt/edtPlugin.cc | 3 ++ src/edt/edt/edtService.cc | 6 +++ src/edt/edt/edtService.h | 5 ++ src/edt/edt/edtServiceImpl.cc | 87 +++++++++++++++++++++++++++++++++++ src/edt/edt/edtServiceImpl.h | 1 + 7 files changed, 149 insertions(+), 2 deletions(-) diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index 6cd58614e..93e99303c 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -211,6 +211,8 @@ MainService::menu_activated (const std::string &symbol) cm_make_array (); } else if (symbol == "edt::sel_make_cell_variants") { cm_make_cell_variants (); + } else if (symbol == "edt::via") { + cm_via (); } } @@ -2439,7 +2441,45 @@ MainService::cm_tap () #endif } -void +void +MainService::cm_via () +{ +#if ! defined(HAVE_QT) + tl_assert (false); // see TODO +#endif + +#if defined(HAVE_QT) + QWidget *view_widget = lay::widget_from_view (view ()); + if (! view_widget) { + return; + } +#endif + + if (! view ()->canvas ()->mouse_in_window ()) { + return; + } + + edt::Service *es = dynamic_cast (view ()->canvas ()->active_service ()); + if (es) { + es->via (); + } else { + +#if 0 // @@@ + db::ShapeIterator::flags_type (db::ShapeIterator::All - db::ShapeIterator::Texts), // do not consider texts - their bounding box may be too large + lay::ShapeFinder finder (true, view ()->is_editable () && m_top_level_sel, m_flags, &m_previous_selection); + + // go through all visible layers of all cellviews + finder.find (view (), search_box); + + // collect the founds from the finder + lay::ShapeFinder::iterator r = finder.begin (); + if (r != finder.end ()) { +#endif + + } +} + +void MainService::cm_change_layer () { tl_assert (view ()->is_editable ()); diff --git a/src/edt/edt/edtMainService.h b/src/edt/edt/edtMainService.h index 5a134d56f..698ede7f4 100644 --- a/src/edt/edt/edtMainService.h +++ b/src/edt/edt/edtMainService.h @@ -200,7 +200,12 @@ public: */ void cm_tap (); - /** + /** + * @brief Via operation + */ + void cm_via (); + + /** * @brief "paste" operation */ virtual void paste (); diff --git a/src/edt/edt/edtPlugin.cc b/src/edt/edt/edtPlugin.cc index 422fa7b4a..c404ffffa 100644 --- a/src/edt/edt/edtPlugin.cc +++ b/src/edt/edt/edtPlugin.cc @@ -379,6 +379,9 @@ public: menu_entries.push_back (lay::menu_item ("edt::sel_area_perimeter", "area_perimeter", "edit_menu.selection_menu.end", tl::to_string (tr ("Area and Perimeter")))); menu_entries.push_back (lay::menu_item ("edt::combine_mode", "combine_mode:edit_mode", "@toolbar.end_modes", tl::to_string (tr ("Combine{Select background combination mode}")))); + + // Key binding only + menu_entries.push_back (lay::menu_item ("edt::via", "via:edit_mode", "@secrets.end", tl::to_string (tr ("Via")) + "(V)")); } bool configure (const std::string &name, const std::string &value) diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index e17f5ee71..b7c584d78 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -1717,6 +1717,12 @@ Service::tap (const db::DPoint & /*initial*/) // .. nothing here .. } +void +Service::via () +{ + // .. nothing here .. +} + void Service::geometry_changing () { diff --git a/src/edt/edt/edtService.h b/src/edt/edt/edtService.h index e782bbfb5..226994a6d 100644 --- a/src/edt/edt/edtService.h +++ b/src/edt/edt/edtService.h @@ -377,6 +377,11 @@ public: */ virtual void tap (const db::DPoint &initial); + /** + * @brief Implements the via feature + */ + virtual void via (); + /** * @brief Delete the selected rulers * diff --git a/src/edt/edt/edtServiceImpl.cc b/src/edt/edt/edtServiceImpl.cc index 634a70a86..6abd7568f 100644 --- a/src/edt/edt/edtServiceImpl.cc +++ b/src/edt/edt/edtServiceImpl.cc @@ -1443,6 +1443,93 @@ PathService::selection_applies (const lay::ObjectInstPath &sel) const return !sel.is_cell_inst () && sel.shape ().is_path (); } +void +PathService::via () +{ +#if ! defined(HAVE_QT) + tl_assert (false); // see TODO +#endif + + // @@@ + db::LayerProperties lp = layout ().get_properties (layer ()); + + // definitions of vias found + struct SelectedViaDefinition + { + SelectedViaDefinition () + : lib (0), pcell (0) + { } + + SelectedViaDefinition (const db::Library *_lib, const db::PCellDeclaration *_pcell, const db::ViaType &_via_type) + : lib (_lib), pcell (_pcell), via_type (_via_type) + { } + + const db::Library *lib; + const db::PCellDeclaration *pcell; + db::ViaType via_type; + }; + + std::vector via_defs; + + // Find vias with corresponding top an bottom layers + // @@@ TODO: move elsewhere + for (auto l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) { + const db::Library *lib = db::LibraryManager::instance ().lib (l->second); + for (auto pc = lib->layout ().begin_pcells (); pc != lib->layout ().end_pcells (); ++pc) { + const db::PCellDeclaration *pcell = lib->layout ().pcell_declaration (pc->second); + auto via_types = pcell->via_types (); + for (auto vt = via_types.begin (); vt != via_types.end (); ++vt) { + if ((vt->bottom.log_equal (lp) && vt->bottom_wired) || (vt->top.log_equal (lp) && vt->top_wired)) { + via_defs.push_back (SelectedViaDefinition (lib, pcell, *vt)); + } + } + } + } + + SelectedViaDefinition via_def; + + if (via_defs.size () == 0) { + + return; + + } else if (via_defs.size () == 1) { + + via_def = via_defs.front (); + + } else if (via_defs.size () > 1) { + +#if defined(HAVE_QT) + // TODO: what to do here in Qt-less case? Store results in configuration so they can be retrieved externally? + + QWidget *view_widget = lay::widget_from_view (view ()); + if (! view_widget) { + return; + } + + std::unique_ptr menu (new QMenu (view_widget)); + menu->show (); + + db::DPoint mp_local = view ()->canvas ()->mouse_position (); + QPoint mp = view ()->canvas ()->widget ()->mapToGlobal (QPoint (mp_local.x (), mp_local.y ())); + + for (auto i = via_defs.begin (); i != via_defs.end (); ++i) { + QAction *a = menu->addAction (tl::to_qstring (i->via_type.description.empty () ? i->via_type.name : i->via_type.description)); + a->setData (int (i - via_defs.begin ())); + } + + QAction *action = menu->exec (mp); + if (! action) { + return; + } + + via_def = via_defs [action->data ().toInt ()]; +#endif + + } + + tl::warn << "@@@1 " << via_def.via_type.name; +} + bool PathService::configure (const std::string &name, const std::string &value) { diff --git a/src/edt/edt/edtServiceImpl.h b/src/edt/edt/edtServiceImpl.h index 99259bac6..92468dfb4 100644 --- a/src/edt/edt/edtServiceImpl.h +++ b/src/edt/edt/edtServiceImpl.h @@ -236,6 +236,7 @@ public: virtual void do_finish_edit (); virtual void do_cancel_edit (); virtual bool do_activated (); + virtual void via (); virtual bool selection_applies (const lay::ObjectInstPath &sel) const; protected: