From ac5c66400d7b99cbdf3bbd35db2fda3e0d40aa19 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 6 Jun 2022 23:04:31 +0200 Subject: [PATCH] Added ability to query modes and issue menu commands to LayoutView in non-Qt case. --- .../laybasic/gsiDeclLayLayoutViewBase.cc | 36 ++++++ src/laybasic/laybasic/layLayoutViewBase.cc | 104 ++++++++++++++++++ src/laybasic/laybasic/layLayoutViewBase.h | 17 +++ testdata/ruby/layLayoutView.rb | 37 +++++-- 4 files changed, 184 insertions(+), 10 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc index d142c2a4c..1827f509f 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc @@ -952,6 +952,42 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase (QT_EXTERNAL_BASE "\n" "@param props The layer properties object to initialize." ) + + gsi::method ("switch_mode", static_cast (&lay::LayoutViewBase::switch_mode), + "@brief Switches the mode.\n" + "\n" + "See \\mode_name about a method to get the name of the current mode and \\mode_names for a method " + "to retrieve all available mode names.\n" + "\n" + "This method has been introduced in version 0.28." + ) + + gsi::method ("mode_name", &lay::LayoutViewBase::mode_name, + "@brief Gets the name of the current mode.\n" + "\n" + "See \\switch_mode about a method to change the mode and \\mode_names for a method " + "to retrieve all available mode names.\n" + "\n" + "This method has been introduced in version 0.28." + ) + + gsi::method ("mode_names", &lay::LayoutViewBase::mode_names, + "@brief Gets the names of the available modes.\n" + "\n" + "This method allows asking the view for the available mode names for \\switch_mode and " + "for the value returned by \\mode.\n" + "\n" + "This method has been introduced in version 0.28." + ) + + gsi::method ("call_menu", &lay::LayoutViewBase::menu_activated, gsi::arg ("symbol"), + "@brief Calls the menu item with the provided symbol.\n" + "To obtain all symbols, use \\menu_symbols.\n" + "\n" + "This method has been introduced in version 0.28." + ) + + gsi::method ("menu_symbols", &lay::LayoutViewBase::menu_symbols, + "@brief Gets all available menu symbols.\n" + "NOTE: currently this method delivers a superset of all available symbols. Depending on the context, no all symbols may trigger actual functionality.\n" + "\n" + "This method has been introduced in version 0.28." + ) + gsi::method ("cancel", &lay::LayoutViewBase::cancel, "@brief Cancels all edit operations\n" "\n" diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index 9a31ad0ba..9d26f4cce 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -5369,6 +5369,110 @@ LayoutViewBase::default_mode () return 0; // TODO: any generic scheme? is select, should be ruler.. } +static std::string +name_from_title (const std::string &title) +{ + std::string s = title; + std::string::size_type tab = s.find ('\t'); + if (tab != std::string::npos) { + s = std::string (s, 0, tab); + } + std::string::size_type colon = s.find (':'); + if (colon != std::string::npos) { + s = std::string (s, 0, colon); + } + return s; +} + +static bool +edit_mode_from_title (const std::string &title) +{ + std::string s = title; + std::string::size_type tab = s.find ('\t'); + if (tab != std::string::npos) { + s = std::string (s, 0, tab); + } + std::vector parts = tl::split (s, ":"); + for (auto i = parts.begin (); i != parts.end (); ++i) { + if (*i == "edit_mode") { + return true; + } + } + return false; +} + +std::vector +LayoutViewBase::mode_names () const +{ + std::vector names; + + std::vector intrinsic_modes; + intrinsic_mouse_modes (&intrinsic_modes); + for (auto i = intrinsic_modes.begin (); i != intrinsic_modes.end (); ++i) { + names.push_back (name_from_title (*i)); + } + + for (auto i = mp_plugins.begin (); i != mp_plugins.end (); ++i) { + std::string title; + if ((*i) && (*i)->plugin_declaration () && (*i)->plugin_declaration ()->implements_mouse_mode (title)) { + if (is_editable () || !edit_mode_from_title (title)) { + names.push_back (name_from_title (title)); + } + } + } + + return names; +} + +std::string +LayoutViewBase::mode_name () const +{ + if (m_mode <= 0) { + + std::vector intrinsic_modes; + intrinsic_mouse_modes (&intrinsic_modes); + + if (int (intrinsic_modes.size ()) > -m_mode) { + return name_from_title (intrinsic_modes [-m_mode]); + } + + } else { + + for (auto i = mp_plugins.begin (); i != mp_plugins.end (); ++i) { + std::string title; + if ((*i) && (*i)->plugin_declaration () && (*i)->plugin_declaration ()->id () == m_mode && (*i)->plugin_declaration ()->implements_mouse_mode (title)) { + return name_from_title (title); + } + } + + } + + return std::string (); +} + +void +LayoutViewBase::switch_mode (const std::string &name) +{ + std::vector intrinsic_modes; + intrinsic_mouse_modes (&intrinsic_modes); + for (auto i = intrinsic_modes.begin (); i != intrinsic_modes.end (); ++i) { + if (name_from_title (*i) == name) { + switch_mode (int (0 - int (i - intrinsic_modes.begin ()))); + return; + } + } + + for (auto i = mp_plugins.begin (); i != mp_plugins.end (); ++i) { + std::string title; + if ((*i) && (*i)->plugin_declaration () && (*i)->plugin_declaration ()->implements_mouse_mode (title)) { + if (name_from_title (title) == name) { + switch_mode ((*i)->plugin_declaration ()->id ()); + return; + } + } + } +} + std::vector LayoutViewBase::menu_symbols () { diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index 53d20dd93..149000372 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -220,6 +220,23 @@ public: */ virtual void switch_mode (int m); + /** + * @brief Gets the name of the active mode + */ + std::string mode_name () const; + + /** + * @brief Switches the mode according to the given name + * + * The name must be one of the names provided by "mode_names". + */ + void switch_mode (const std::string &name); + + /** + * @brief Gets the names of the available modes + */ + std::vector mode_names () const; + /** * @brief Determine if there is something to copy * diff --git a/testdata/ruby/layLayoutView.rb b/testdata/ruby/layLayoutView.rb index 456480a0d..deaaab413 100644 --- a/testdata/ruby/layLayoutView.rb +++ b/testdata/ruby/layLayoutView.rb @@ -466,18 +466,35 @@ class LAYLayoutView_TestClass < TestBase def test_5 - lv = RBA::LayoutView::new - lv.load_layout(File.join($ut_testsrc, "testdata/gds/t10.gds"), true) + [true, false].each do |editable| - lv.resize(42, 117) - img = lv.get_screenshot_pixels - assert_equal(img.width, 42) - assert_equal(img.height, 117) + lv = RBA::LayoutView::new(editable) + lv.load_layout(File.join($ut_testsrc, "testdata/gds/t10.gds"), true) - lv.resize(142, 217) - img = lv.get_screenshot_pixels - assert_equal(img.width, 142) - assert_equal(img.height, 217) + lv.resize(42, 117) + img = lv.get_screenshot_pixels + assert_equal(img.width, 42) + assert_equal(img.height, 117) + + lv.resize(142, 217) + img = lv.get_screenshot_pixels + assert_equal(img.width, 142) + assert_equal(img.height, 217) + + if editable + assert_equal(lv.mode_names, ["select", "move", "ruler", "polygon", "box", "text", "path", "instance", "partial"]) + else + assert_equal(lv.mode_names, ["select", "move", "ruler"]) + end + assert_equal(lv.mode_name, "select") + lv.switch_mode("ruler") + assert_equal(lv.mode_name, "ruler") + lv.switch_mode("move") + assert_equal(lv.mode_name, "move") + lv.switch_mode("select") + assert_equal(lv.mode_name, "select") + + end end