diff --git a/src/db/db/dbVia.cc b/src/db/db/dbVia.cc index 78844b3f6..6d9da1e2a 100644 --- a/src/db/db/dbVia.cc +++ b/src/db/db/dbVia.cc @@ -46,8 +46,8 @@ ViaType::init () // --------------------------------------------------------------------------------------- -std::vector -find_via_definitions_for (const std::string &technology, const db::LayerProperties &layer, int dir) +static std::vector +find_via_definitions_impl (const std::string &technology, const db::LayerProperties &layer, int dir, bool all) { std::vector via_defs; @@ -65,7 +65,8 @@ find_via_definitions_for (const std::string &technology, const db::LayerProperti auto via_types = pcell->via_types (); for (auto vt = via_types.begin (); vt != via_types.end (); ++vt) { - if ((dir >= 0 && vt->bottom.log_equal (layer) && vt->bottom_wired) || + if (all || + (dir >= 0 && vt->bottom.log_equal (layer) && vt->bottom_wired) || (dir <= 0 && vt->top.log_equal (layer) && vt->top_wired)) { via_defs.push_back (SelectedViaDefinition (lib, pc->second, *vt)); } @@ -78,4 +79,16 @@ find_via_definitions_for (const std::string &technology, const db::LayerProperti return via_defs; } +std::vector +get_via_definitions (const std::string &technology) +{ + return find_via_definitions_impl (technology, db::LayerProperties (), 0, true); +} + +std::vector +find_via_definitions_for (const std::string &technology, const db::LayerProperties &layer, int dir) +{ + return find_via_definitions_impl (technology, layer, dir, false); +} + } diff --git a/src/db/db/dbVia.h b/src/db/db/dbVia.h index 492e1333e..d02378df9 100644 --- a/src/db/db/dbVia.h +++ b/src/db/db/dbVia.h @@ -210,6 +210,9 @@ struct SelectedViaDefinition DB_PUBLIC std::vector find_via_definitions_for (const std::string &technology, const db::LayerProperties &layer, int dir); +DB_PUBLIC std::vector +get_via_definitions (const std::string &technology); + } #endif diff --git a/src/edt/edt/edtDialogs.cc b/src/edt/edt/edtDialogs.cc index 120a7495f..cd1553a0f 100644 --- a/src/edt/edt/edtDialogs.cc +++ b/src/edt/edt/edtDialogs.cc @@ -29,8 +29,9 @@ #include "layEditorUtils.h" #include "layObjectInstPath.h" #include "layCellView.h" -#include "layLayoutViewBase.h" #include "layMarker.h" +#include "layFinder.h" +#include "layLayerTreeModel.h" #include "tlException.h" #include "tlExceptions.h" @@ -725,6 +726,93 @@ AreaAndPerimeterDialog::exec_dialog (double area, double perimeter) return exec () != 0; } +// -------------------------------------------------------------------------------- +// popup_tap_layer_menu implementation + +lay::LayerPropertiesConstIterator +popup_tap_layer_menu (lay::LayoutViewBase *view, const std::set *filter, int cv_index) +{ + QWidget *view_widget = lay::widget_from_view (view); + if (! view_widget) { + return lay::LayerPropertiesConstIterator (); + } + + if (! view->canvas ()->mouse_in_window ()) { + return lay::LayerPropertiesConstIterator (); + } + + lay::ShapeFinder finder (true, // point mode + false, // all hierarchy levels + db::ShapeIterator::flags_type (db::ShapeIterator::All - db::ShapeIterator::Texts), // do not consider texts - their bounding box may be too large + 0, // no excludes + true // capture all shapes + ); + + // capture all objects in point mode (default: capture one only) + finder.set_catch_all (true); + + // go through all visible layers of all cellviews + db::DPoint pt = view->canvas ()->mouse_position_um (); + finder.find (view, db::DBox (pt, pt)); + + std::set > layers_in_selection; + + for (lay::ShapeFinder::iterator f = finder.begin (); f != finder.end (); ++f) { + if (cv_index < 0 || f->cv_index () == cv_index) { + const db::Layout &ly = view->cellview (f->cv_index ())->layout (); + // ignore guiding shapes and only provide layers from the filter + if (f->layer () != ly.guiding_shape_layer () + && (! filter || filter->find (ly.get_properties (f->layer ())) != filter->end ())) { + layers_in_selection.insert (std::make_pair (f->cv_index (), f->layer ())); + } + } + } + + std::vector tapped_layers; + for (lay::LayerPropertiesConstIterator lp = view->begin_layers (view->current_layer_list ()); ! lp.at_end (); ++lp) { + const lay::LayerPropertiesNode *ln = lp.operator-> (); + if (layers_in_selection.find (std::make_pair ((unsigned int) ln->cellview_index (), (unsigned int) ln->layer_index ())) != layers_in_selection.end ()) { + tapped_layers.push_back (lp); + } + } + + if (tapped_layers.empty ()) { + return lay::LayerPropertiesConstIterator (); + } else if (tapped_layers.size () == 1) { + return tapped_layers.front (); + } + + // List the layers under the cursor as pop up a menu + +#if QT_VERSION >= 0x050000 + double dpr = view_widget->devicePixelRatio (); +#else + double dpr = 1.0; +#endif + + std::unique_ptr menu (new QMenu (view_widget)); + menu->show (); + + int icon_size = menu->style ()->pixelMetric (QStyle::PM_ButtonIconSize); + + db::DPoint mp_local = view->canvas ()->mouse_position (); + QPoint mp = view->canvas ()->widget ()->mapToGlobal (QPoint (mp_local.x (), mp_local.y ())); + + for (std::vector::const_iterator l = tapped_layers.begin (); l != tapped_layers.end (); ++l) { + QAction *a = menu->addAction (lay::LayerTreeModel::icon_for_layer (*l, view, icon_size, icon_size, dpr, 0, true), tl::to_qstring ((*l)->display_string (view, true, true /*with source*/))); + a->setData (int (l - tapped_layers.begin ())); + } + + QAction *action = menu->exec (mp); + if (action) { + int index = action->data ().toInt (); + return tapped_layers [index]; + } else { + return lay::LayerPropertiesConstIterator (); + } + +} + } #endif diff --git a/src/edt/edt/edtDialogs.h b/src/edt/edt/edtDialogs.h index e844491ff..fa8947a06 100644 --- a/src/edt/edt/edtDialogs.h +++ b/src/edt/edt/edtDialogs.h @@ -34,6 +34,9 @@ #include "dbLayout.h" #include "dbPoint.h" +#include "dbLayerProperties.h" + +#include "layLayoutView.h" #include "ui_InstantiationForm.h" #include "ui_ChangeLayerOptionsDialog.h" @@ -47,7 +50,6 @@ namespace lay { - class LayoutViewBase; class Marker; class ObjectInstPath; } @@ -222,6 +224,17 @@ public: bool exec_dialog (double area, double perimeter); }; +/** + * @brief Obtains an layer iterator for one of the layers present under the mouse cursor + * + * This is not really a dialog, but a popup menu. + * + * @param view The LayoutView object + * @param filter An optional set of layers to show. Only layers from this set are shown. + * @return A layer iterator which is at_end if no specific layer was selected + */ +lay::LayerPropertiesConstIterator popup_tap_layer_menu (lay::LayoutViewBase *view, const std::set *filter = 0, int cv_index = -1); + } // namespace edt #endif diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index 69dd64163..d395d8309 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -47,7 +47,6 @@ #if defined(HAVE_QT) # include "layDialogs.h" -# include "layLayerTreeModel.h" # include "layCellSelectionForm.h" # include "edtDialogs.h" # include "edtEditorOptionsPages.h" @@ -2361,88 +2360,16 @@ void MainService::cm_tap () { #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; - } - - lay::ShapeFinder finder (true, // point mode - false, // all hierarchy levels - db::ShapeIterator::flags_type (db::ShapeIterator::All - db::ShapeIterator::Texts), // do not consider texts - their bounding box may be too large - 0, // no excludes - true // capture all shapes - ); - - // capture all objects in point mode (default: capture one only) - finder.set_catch_all (true); - - // go through all visible layers of all cellviews - db::DPoint pt = view ()->canvas ()->mouse_position_um (); - finder.find (view (), db::DBox (pt, pt)); - - std::set > layers_in_selection; - - for (lay::ShapeFinder::iterator f = finder.begin (); f != finder.end (); ++f) { - // ignore guiding shapes - if (f->layer () != view ()->cellview (f->cv_index ())->layout ().guiding_shape_layer ()) { - layers_in_selection.insert (std::make_pair (f->cv_index (), f->layer ())); - } - } - - std::vector tapped_layers; - for (lay::LayerPropertiesConstIterator lp = view ()->begin_layers (view ()->current_layer_list ()); ! lp.at_end (); ++lp) { - const lay::LayerPropertiesNode *ln = lp.operator-> (); - if (layers_in_selection.find (std::make_pair ((unsigned int) ln->cellview_index (), (unsigned int) ln->layer_index ())) != layers_in_selection.end ()) { - tapped_layers.push_back (lp); - } - } - - if (tapped_layers.empty ()) { - return; - } - - // List the layers under the cursor as pop up a menu - -#if defined(HAVE_QT) - // TODO: what to do here in Qt-less case? Store results in configuration so they can be retrieved externally? - -#if QT_VERSION >= 0x050000 - double dpr = view_widget->devicePixelRatio (); + tl_assert (false); // TODO #else - double dpr = 1.0; -#endif + lay::LayerPropertiesConstIterator iter = edt::popup_tap_layer_menu (view ()); + if (! iter.at_end ()) { - std::unique_ptr menu (new QMenu (view_widget)); - menu->show (); - - int icon_size = menu->style ()->pixelMetric (QStyle::PM_ButtonIconSize); - - db::DPoint mp_local = view ()->canvas ()->mouse_position (); - QPoint mp = view ()->canvas ()->widget ()->mapToGlobal (QPoint (mp_local.x (), mp_local.y ())); - - for (std::vector::const_iterator l = tapped_layers.begin (); l != tapped_layers.end (); ++l) { - QAction *a = menu->addAction (lay::LayerTreeModel::icon_for_layer (*l, view (), icon_size, icon_size, dpr, 0, true), tl::to_qstring ((*l)->display_string (view (), true, true /*with source*/))); - a->setData (int (l - tapped_layers.begin ())); - } - - QAction *action = menu->exec (mp); - if (action) { - - int index = action->data ().toInt (); - lay::LayerPropertiesConstIterator iter = tapped_layers [index]; view ()->set_current_layer (iter); edt::Service *es = dynamic_cast (view ()->canvas ()->active_service ()); if (es) { + db::DPoint pt = view ()->canvas ()->mouse_position_um (); es->tap (pt); } @@ -2486,9 +2413,11 @@ MainService::via_impl (int dir) return; } - edt::Service *es = dynamic_cast (view ()->canvas ()->active_service ()); - if (es) { - es->via (dir); + // via generation is delegated to the path service always + edt::PathService *ps = view ()->get_plugin (); + if (ps) { + view ()->switch_mode (ps->plugin_declaration ()->id ()); + ps->via (dir); } } diff --git a/src/edt/edt/edtPathService.cc b/src/edt/edt/edtPathService.cc index 6879dec56..65863b591 100644 --- a/src/edt/edt/edtPathService.cc +++ b/src/edt/edt/edtPathService.cc @@ -22,15 +22,12 @@ #include "edtPathService.h" +#include "edtDialogs.h" +#include "edtPropertiesPages.h" #include "layLayoutViewBase.h" #include "layFinder.h" -#if defined(HAVE_QT) -# include "edtPropertiesPages.h" -# include "layLayoutView.h" -#endif - namespace edt { @@ -268,6 +265,35 @@ PathService::via (int dir) #endif } +db::LayerProperties +PathService::get_layer_for_via (unsigned int cv_index) +{ +#if defined(HAVE_QT) + const lay::CellView &cv = view ()->cellview (cv_index); + if (! cv.is_valid ()) { + return db::LayerProperties (); + } + + std::vector via_defs = db::get_via_definitions (cv->layout ().technology_name ()); + + std::set lp_filter; + for (auto vd = via_defs.begin (); vd != via_defs.end (); ++vd) { + lp_filter.insert (vd->via_type.bottom); + lp_filter.insert (vd->via_type.top); + } + + lay::LayerPropertiesConstIterator iter; + iter = edt::popup_tap_layer_menu (view (), &lp_filter, cv_index); + if (iter.at_end ()) { + return db::LayerProperties (); + } + + return cv->layout ().get_properties (iter->layer_index ()); +#else + return db::LayerProperties (); +#endif +} + bool PathService::get_via_for (const db::LayerProperties &lp, unsigned int cv_index, int dir, db::SelectedViaDefinition &via_def) { @@ -364,19 +390,20 @@ PathService::via_initial (int dir) return; } - const lay::CellView &cv = view ()->cellview (r->cv_index ()); - if (! cv.is_valid ()) { + // the first found provides the cellview index + int cv_index = r->cv_index (); + + db::LayerProperties lp = get_layer_for_via (cv_index); + if (lp.is_null ()) { return; } - db::LayerProperties lp = cv->layout ().get_properties (r->layer ()); - db::SelectedViaDefinition via_def; - if (! get_via_for (lp, r->cv_index (), dir, via_def)) { + if (! get_via_for (lp, cv_index, dir, via_def)) { return; } - set_layer (lp, r->cv_index ()); + set_layer (lp, cv_index); bool is_bottom = via_def.via_type.bottom.log_equal (lp); db::LayerProperties lp_new = is_bottom ? via_def.via_type.top : via_def.via_type.bottom; diff --git a/src/edt/edt/edtPathService.h b/src/edt/edt/edtPathService.h index c926101b4..b7321fa53 100644 --- a/src/edt/edt/edtPathService.h +++ b/src/edt/edt/edtPathService.h @@ -89,6 +89,7 @@ private: void via_initial (int dir); void via_editing (int dir); bool get_via_for (const db::LayerProperties &lp, unsigned int cv_index, int dir, db::SelectedViaDefinition &via_def); + db::LayerProperties get_layer_for_via (unsigned int cv_index); void push_segment (const db::Shape &shape, const db::Instance &instance, const db::ViaType &via_type, db::Manager::transaction_id_t transaction_id); void pop_segment (); }; diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index ceab2f786..758f5ecc1 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -26,17 +26,13 @@ #include "dbLibrary.h" #include "edtPlugin.h" #include "edtService.h" -#if defined(HAVE_QT) -# include "edtEditorOptionsPages.h" -# include "edtDialogs.h" -#endif +#include "edtEditorOptionsPages.h" +#include "edtDialogs.h" #include "layFinder.h" #include "layLayoutView.h" #include "laySnap.h" #include "layConverters.h" -#if defined(HAVE_QT) -# include "layEditorOptionsPages.h" -#endif +#include "layEditorOptionsPages.h" #include "tlProgress.h" #include "tlTimer.h" @@ -1709,13 +1705,13 @@ Service::begin_edit (const db::DPoint &p) } void -Service::tap (const db::DPoint & /*initial*/) +Service::tap (const db::DPoint & /*pt*/) { // .. nothing here .. } void -Service::via (int) +Service::via (int /*dir*/) { // .. nothing here .. } diff --git a/src/edt/edt/edtShapeService.cc b/src/edt/edt/edtShapeService.cc index 4664f777b..da8b7590c 100644 --- a/src/edt/edt/edtShapeService.cc +++ b/src/edt/edt/edtShapeService.cc @@ -22,15 +22,14 @@ #include "edtShapeService.h" #include "edtMainService.h" +#include "edtPathService.h" +#include "edtPropertiesPages.h" #include "layLayoutView.h" #include "dbEdgeProcessor.h" #include "dbPolygonTools.h" -#if defined(HAVE_QT) -# include "edtPropertiesPages.h" -# include "layTipDialog.h" -# include "layEditorOptionsPages.h" -#endif +#include "layTipDialog.h" +#include "layEditorOptionsPages.h" namespace edt {