From 7a7ee8492bbcf622417cd81b55e74d46a938407c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 10 Aug 2024 14:58:02 +0200 Subject: [PATCH] Some enhancements to "Descend" and "Ascend" - Ascend now ascends further up if a child cell is selected as top level cell - Descend now looks into transiently selected shapes or instances too (mouse hover mode) - New feature "Descend into" which combines "Descend" with "make new top". - Fixed a compiler warning in layLayoutViewBase.cc --- src/edt/edt/edtMainService.cc | 64 +++++++++++++++++++--- src/edt/edt/edtMainService.h | 6 ++ src/edt/edt/edtPlugin.cc | 1 + src/laybasic/laybasic/layLayoutViewBase.cc | 29 +++++++++- 4 files changed, 90 insertions(+), 10 deletions(-) diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index f08334d7c..bbd50ee10 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -169,6 +169,8 @@ MainService::menu_activated (const std::string &symbol) { if (symbol == "edt::descend") { cm_descend (); + } else if (symbol == "edt::descend_into") { + cm_descend_into (); } else if (symbol == "edt::ascend") { cm_ascend (); } else if (symbol == "edt::sel_align") { @@ -303,8 +305,20 @@ private: }; -void +void MainService::cm_descend () +{ + descend (false); +} + +void +MainService::cm_descend_into () +{ + descend (true); +} + +void +MainService::descend (bool into) { CommonInsts common_inst; @@ -315,6 +329,15 @@ MainService::cm_descend () } } + if (! common_inst.anything ()) { + // try transient selection + for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end () && common_inst.valid (); ++es) { + for (EditableSelectionIterator sel = (*es)->begin_transient_selection (); ! sel.at_end () && common_inst.valid (); ++sel) { + common_inst.add (*sel, 1); + } + } + } + // cannot descend - we are at the lowest level already if (common_inst.empty ()) { return; @@ -354,6 +377,9 @@ MainService::cm_descend () // this will clear the selection: view ()->descend (common_inst.common_path (), common_inst.cv_index ()); + if (into) { + view ()->select_cell_dispatch (view ()->cellview (common_inst.cv_index ()).combined_unspecific_path (), common_inst.cv_index ()); + } view ()->set_current_cell_path (common_inst.cv_index (), view ()->cellview (common_inst.cv_index ()).combined_unspecific_path ()); // set the new selections @@ -371,6 +397,7 @@ MainService::cm_ascend () std::vector edt_services = view ()->get_plugins (); + bool any_selected = false; std::vector< std::vector > new_selections; new_selections.reserve (edt_services.size ()); for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) { @@ -382,6 +409,7 @@ MainService::cm_ascend () new_selections.back ().reserve (n); for (EditableSelectionIterator i = (*es)->begin_selection (); ! i.at_end (); ++i) { new_selections.back ().push_back (*i); + any_selected = true; } } @@ -394,14 +422,36 @@ MainService::cm_ascend () db::cell_index_type new_top = view ()->cellview (cv_index).cell_index (); view ()->set_current_cell_path (cv_index, view ()->cellview (cv_index).combined_unspecific_path ()); - // create and the new selections - unsigned int index = 0; - for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es, ++index) { - for (std::vector::iterator sel = new_selections [index].begin (); sel != new_selections [index].end (); ++sel) { - if (int (sel->cv_index ()) == cv_index) { - sel->insert_front (new_top, removed); + if (! any_selected) { + +#if 0 + // make the instance we just left the selected one + // (Note: this is a nice idea, but it kind of pins the path to the current cell. + // Specifically after enabling the transient selection for "descend", this is more + // annoying than useful) + edt::InstService *inst_service = view ()->get_plugin (); + unsigned int index = 0; + for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es, ++index) { + if (*es == inst_service) { + new_selections [index].push_back (lay::ObjectInstPath ()); + new_selections [index].back ().add_path (removed); + break; } } +#endif + + } else { + + // modify the selections by adding the new path element + unsigned int index = 0; + for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es, ++index) { + for (std::vector::iterator sel = new_selections [index].begin (); sel != new_selections [index].end (); ++sel) { + if (int (sel->cv_index ()) == cv_index) { + sel->insert_front (new_top, removed); + } + } + } + } } diff --git a/src/edt/edt/edtMainService.h b/src/edt/edt/edtMainService.h index 3afc3aabb..ee69f6f6a 100644 --- a/src/edt/edt/edtMainService.h +++ b/src/edt/edt/edtMainService.h @@ -90,6 +90,11 @@ public: */ void cm_descend (); + /** + * @brief Descend to selection and make cell current top + */ + void cm_descend_into (); + /** * @brief Ascend one level */ @@ -239,6 +244,7 @@ private: void boolean_op (int mode); void check_no_guiding_shapes (); + void descend (bool make_new_top); #if defined(HAVE_QT) edt::RoundCornerOptionsDialog *round_corners_dialog (); edt::AreaAndPerimeterDialog *area_and_perimeter_dialog (); diff --git a/src/edt/edt/edtPlugin.cc b/src/edt/edt/edtPlugin.cc index fe0e239c9..cde82a890 100644 --- a/src/edt/edt/edtPlugin.cc +++ b/src/edt/edt/edtPlugin.cc @@ -351,6 +351,7 @@ public: menu_entries.push_back (lay::separator ("edt::hier_group", "zoom_menu.end")); menu_entries.push_back (lay::menu_item ("edt::descend", "descend", "zoom_menu.end", tl::to_string (tr ("Descend")) + "(Ctrl+D)")); + menu_entries.push_back (lay::menu_item ("edt::descend_into", "descend_into", "zoom_menu.end", tl::to_string (tr ("Descend Into")) + "(D)")); menu_entries.push_back (lay::menu_item ("edt::ascend", "ascend", "zoom_menu.end", tl::to_string (tr ("Ascend")) + "(Ctrl+A)")); menu_entries.push_back (lay::menu_item ("edt::sel_make_array", "make_array:edit_mode", "edit_menu.selection_menu.end", tl::to_string (tr ("Make Array")))); diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index 30e855a41..9a2272106 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -780,7 +780,7 @@ LayoutViewBase::configure (const std::string &name, const std::string &value) int os = 1; tl::from_string (value, os); - if (os != mp_canvas->oversampling ()) { + if (os != int (mp_canvas->oversampling ())) { mp_canvas->set_oversampling (os); resolution_changed_event (); } @@ -5899,17 +5899,40 @@ LayoutViewBase::ascend (int index) { tl_assert (int (m_cellviews.size ()) > index && cellview_iter (index)->is_valid ()); + lay::CellView &cv = *cellview_iter (index); + cellview_about_to_change_event (index); - lay::CellView::specific_cell_path_type spath (cellview_iter (index)->specific_path ()); + lay::CellView::specific_cell_path_type spath (cv.specific_path ()); if (spath.empty ()) { + + lay::CellView::unspecific_cell_path_type upath (cv.unspecific_path ()); + if (upath.size () >= 2) { + + db::cell_index_type last = upath.back (); + upath.pop_back (); + const db::Cell &new_cell = cv->layout ().cell (upath.back ()); + + auto i = new_cell.begin (); + while (! i.at_end () && i->cell_index () != last) { + ++i; + } + + if (! i.at_end ()) { + select_cell_dispatch (upath, index); + return db::InstElement (*i); + } + + } + return db::InstElement (); + } else { cancel (); db::InstElement ret = spath.back (); spath.pop_back (); - cellview_iter (index)->set_specific_path (spath); + cv.set_specific_path (spath); store_state (); redraw ();