Some debugging, tests added

This commit is contained in:
Matthias Koefferlein 2025-08-30 00:34:35 +02:00
parent 3eff75433c
commit 7d2113ffe1
6 changed files with 215 additions and 19 deletions

View File

@ -29,6 +29,8 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "edtCommon.h"
#include "layObjectInstPath.h" #include "layObjectInstPath.h"
#include "laySnap.h" #include "laySnap.h"
@ -54,17 +56,17 @@ class Service;
* This implements the standard modifiers for angle constraints - i.e. * This implements the standard modifiers for angle constraints - i.e.
* ortho for "Shift". * ortho for "Shift".
*/ */
extern lay::angle_constraint_type ac_from_buttons (unsigned int buttons); EDT_PUBLIC lay::angle_constraint_type ac_from_buttons (unsigned int buttons);
/** /**
* @brief Serializes PCell parameters to a string * @brief Serializes PCell parameters to a string
*/ */
std::string pcell_parameters_to_string (const std::map<std::string, tl::Variant> &parameters); EDT_PUBLIC std::string pcell_parameters_to_string (const std::map<std::string, tl::Variant> &parameters);
/** /**
* @brief Deserializes PCell parameters from a string * @brief Deserializes PCell parameters from a string
*/ */
std::map<std::string, tl::Variant> pcell_parameters_from_string (const std::string &s); EDT_PUBLIC std::map<std::string, tl::Variant> pcell_parameters_from_string (const std::string &s);
/** /**
* @brief Fetch PCell parameters from a cell and merge the guiding shapes into them * @brief Fetch PCell parameters from a cell and merge the guiding shapes into them
@ -74,13 +76,13 @@ std::map<std::string, tl::Variant> pcell_parameters_from_string (const std::stri
* @param parameters_for_pcell Will receive the parameters * @param parameters_for_pcell Will receive the parameters
* @return true, if the cell is a PCell and parameters have been fetched * @return true, if the cell is a PCell and parameters have been fetched
*/ */
bool EDT_PUBLIC bool
get_parameters_from_pcell_and_guiding_shapes (db::Layout *layout, db::cell_index_type cell_index, db::pcell_parameters_type &parameters_for_pcell); get_parameters_from_pcell_and_guiding_shapes (db::Layout *layout, db::cell_index_type cell_index, db::pcell_parameters_type &parameters_for_pcell);
/** /**
* @brief A helper class that identifies clipboard data for edt:: * @brief A helper class that identifies clipboard data for edt::
*/ */
class ClipboardData class EDT_PUBLIC ClipboardData
: public db::ClipboardData : public db::ClipboardData
{ {
public: public:
@ -90,7 +92,7 @@ public:
/** /**
* @brief A cache for the transformation variants for a certain layer and cell view index for a lay::LayoutView * @brief A cache for the transformation variants for a certain layer and cell view index for a lay::LayoutView
*/ */
class TransformationVariants class EDT_PUBLIC TransformationVariants
{ {
public: public:
TransformationVariants (const lay::LayoutViewBase *view, bool per_cv_and_layer = true, bool per_cv = true); TransformationVariants (const lay::LayoutViewBase *view, bool per_cv_and_layer = true, bool per_cv = true);

View File

@ -404,6 +404,12 @@ public:
return f_configure.can_issue () ? f_configure.issue<PluginBase, bool, const std::string &, const std::string &> (&PluginBase::configure, name, value) : lay::Plugin::configure (name, value); return f_configure.can_issue () ? f_configure.issue<PluginBase, bool, const std::string &, const std::string &> (&PluginBase::configure, name, value) : lay::Plugin::configure (name, value);
} }
// for testing
void configure_test (const std::string &name, const std::string &value)
{
configure_edt (name, value);
}
virtual bool configure (const std::string &name, const std::string &value) virtual bool configure (const std::string &name, const std::string &value)
{ {
configure_edt (name, value); configure_edt (name, value);
@ -633,21 +639,43 @@ public:
lay::EditorServiceBase::add_edge_marker (p, cv_index, cv.context_trans (), *tv_list, emphasize); lay::EditorServiceBase::add_edge_marker (p, cv_index, cv.context_trans (), *tv_list, emphasize);
} }
// for testing
bool has_tracking_position_test () const
{
return has_tracking_position ();
}
bool has_tracking_position_base () const
{
return lay::EditorServiceBase::has_tracking_position ();
}
virtual bool has_tracking_position () const virtual bool has_tracking_position () const
{ {
if (f_has_tracking_position.can_issue ()) { if (f_has_tracking_position.can_issue ()) {
return f_has_tracking_position.issue<lay::EditorServiceBase, bool> (&lay::EditorServiceBase::has_tracking_position); return f_has_tracking_position.issue<lay::EditorServiceBase, bool> (&lay::EditorServiceBase::has_tracking_position);
} else { } else {
return lay::EditorServiceBase::has_tracking_position (); return has_tracking_position_base ();
} }
} }
// for testing
db::DPoint tracking_position_test () const
{
return tracking_position ();
}
db::DPoint tracking_position_base () const
{
return lay::EditorServiceBase::tracking_position ();
}
virtual db::DPoint tracking_position () const virtual db::DPoint tracking_position () const
{ {
if (f_tracking_position.can_issue ()) { if (f_tracking_position.can_issue ()) {
return f_tracking_position.issue<lay::EditorServiceBase, db::DPoint> (&lay::EditorServiceBase::tracking_position); return f_tracking_position.issue<lay::EditorServiceBase, db::DPoint> (&lay::EditorServiceBase::tracking_position);
} else { } else {
return lay::EditorServiceBase::tracking_position (); return tracking_position_base ();
} }
} }
@ -662,13 +690,17 @@ public:
} }
#if defined(HAVE_QTBINDINGS) #if defined(HAVE_QTBINDINGS)
std::vector<lay::EditorOptionsPage *> editor_options_pages () std::vector<QWidget *> editor_options_pages ()
{ {
lay::EditorOptionsPages *eo_pages = view ()->editor_options_pages (); lay::EditorOptionsPages *eo_pages = view ()->editor_options_pages ();
if (!eo_pages) { if (!eo_pages) {
return std::vector<lay::EditorOptionsPage *> (); return std::vector<QWidget *> ();
} else { } else {
return eo_pages->pages (); std::vector<QWidget *> pages;
for (auto p = eo_pages->pages ().begin (); p != eo_pages->pages ().end (); ++p) {
pages.push_back (*p);
}
return pages;
} }
} }
#endif #endif
@ -1281,6 +1313,7 @@ Class<gsi::PluginBase> decl_Plugin ("lay", "Plugin",
"When a menu item is clicked which was registered with the plugin factory, the plugin's 'menu_activated' method is " "When a menu item is clicked which was registered with the plugin factory, the plugin's 'menu_activated' method is "
"called for the current view. The symbol registered for the menu item is passed in the 'symbol' argument." "called for the current view. The symbol registered for the menu item is passed in the 'symbol' argument."
) + ) +
method ("configure_test", &gsi::PluginBase::configure_test, gsi::arg ("name"), gsi::arg ("value"), "@hide") +
callback ("configure", &gsi::PluginBase::configure_impl, &gsi::PluginBase::f_configure, gsi::arg ("name"), gsi::arg ("value"), callback ("configure", &gsi::PluginBase::configure_impl, &gsi::PluginBase::f_configure, gsi::arg ("name"), gsi::arg ("value"),
"@brief Sends configuration requests to the plugin\n" "@brief Sends configuration requests to the plugin\n"
"@param name The name of the configuration variable as registered in the plugin factory\n" "@param name The name of the configuration variable as registered in the plugin factory\n"
@ -1384,6 +1417,8 @@ Class<gsi::PluginBase> decl_Plugin ("lay", "Plugin",
"\n" "\n"
"The cursor type is one of the cursor constants in the \\Cursor class, i.e. 'CursorArrow' for the normal cursor." "The cursor type is one of the cursor constants in the \\Cursor class, i.e. 'CursorArrow' for the normal cursor."
) + ) +
method ("has_tracking_position_test", &gsi::PluginBase::has_tracking_position_test, "@hide") +
method ("has_tracking_position", &gsi::PluginBase::has_tracking_position_base, "@hide") +
callback ("has_tracking_position", &gsi::PluginBase::has_tracking_position, &gsi::PluginBase::f_has_tracking_position, callback ("has_tracking_position", &gsi::PluginBase::has_tracking_position, &gsi::PluginBase::f_has_tracking_position,
"@brief Gets a value indicating whether the plugin provides a tracking position\n" "@brief Gets a value indicating whether the plugin provides a tracking position\n"
"The tracking position is shown in the lower-left corner of the layout window to indicate the current position.\n" "The tracking position is shown in the lower-left corner of the layout window to indicate the current position.\n"
@ -1392,6 +1427,8 @@ Class<gsi::PluginBase> decl_Plugin ("lay", "Plugin",
"\n" "\n"
"This method has been added in version 0.27.6." "This method has been added in version 0.27.6."
) + ) +
method ("tracking_position_test", &gsi::PluginBase::tracking_position_test, "@hide") +
method ("tracking_position", &gsi::PluginBase::tracking_position_base, "@hide") +
callback ("tracking_position", &gsi::PluginBase::tracking_position, &gsi::PluginBase::f_tracking_position, callback ("tracking_position", &gsi::PluginBase::tracking_position, &gsi::PluginBase::f_tracking_position,
"@brief Gets the tracking position\n" "@brief Gets the tracking position\n"
"See \\has_tracking_position for details.\n" "See \\has_tracking_position for details.\n"

View File

@ -141,8 +141,14 @@ public:
*/ */
void show_error (tl::Exception &ex); void show_error (tl::Exception &ex);
protected: /**
* @brief Sets a configuration option
*/
virtual bool configure (const std::string &name, const std::string &value); virtual bool configure (const std::string &name, const std::string &value);
/**
* @brief Called when the plugin is deactivated
*/
virtual void deactivated (); virtual void deactivated ();
private: private:

View File

@ -602,20 +602,25 @@ void LayoutViewBase::create_plugins (const lay::PluginDeclaration *except_this)
clear_plugins (); clear_plugins ();
// create the plugins // create the plugins
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) { for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ) {
if (&*cls != except_this) { // NOTE: during "create_plugin" a plugin may be unregistered, so don't increment the iterator after
auto current = cls.operator-> ();
std::string current_name = cls.current_name ();
++cls;
if (current != except_this) {
// TODO: clean solution. The following is a HACK: // TODO: clean solution. The following is a HACK:
if (cls.current_name () == "ant::Plugin" || cls.current_name () == "img::Plugin") { if (current_name == "ant::Plugin" || current_name == "img::Plugin") {
// ant and img are created always // ant and img are created always
create_plugin (&*cls); create_plugin (current);
} else if ((options () & LV_NoPlugins) == 0) { } else if ((options () & LV_NoPlugins) == 0) {
// others: only create unless LV_NoPlugins is set // others: only create unless LV_NoPlugins is set
create_plugin (&*cls); create_plugin (current);
} else if ((options () & LV_NoGrid) == 0 && cls.current_name () == "GridNetPlugin") { } else if ((options () & LV_NoGrid) == 0 && current_name == "GridNetPlugin") {
// except grid net plugin which is created on request // except grid net plugin which is created on request
create_plugin (&*cls); create_plugin (current);
} }
} }

View File

@ -152,6 +152,7 @@ RUBYTEST (layMainWindow, "layMainWindow.rb")
RUBYTEST (layMarkers, "layMarkers.rb") RUBYTEST (layMarkers, "layMarkers.rb")
RUBYTEST (layMacro, "layMacro.rb") RUBYTEST (layMacro, "layMacro.rb")
RUBYTEST (layMenuTest, "layMenuTest.rb") RUBYTEST (layMenuTest, "layMenuTest.rb")
RUBYTEST (layPluginTests, "layPluginTests.rb")
RUBYTEST (layPixelBuffer, "layPixelBuffer.rb") RUBYTEST (layPixelBuffer, "layPixelBuffer.rb")
RUBYTEST (laySession, "laySession.rb") RUBYTEST (laySession, "laySession.rb")
RUBYTEST (laySaveLayoutOptions, "laySaveLayoutOptions.rb") RUBYTEST (laySaveLayoutOptions, "laySaveLayoutOptions.rb")

145
testdata/ruby/layPluginTests.rb vendored Normal file
View File

@ -0,0 +1,145 @@
# encoding: UTF-8
# KLayout Layout Viewer
# Copyright (C) 2006-2025 Matthias Koefferlein
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
if !$:.member?(File::dirname($0))
$:.push(File::dirname($0))
end
load("test_prologue.rb")
class PluginFactory < RBA::PluginFactory
def initialize()
register(1000, "plugin_for_test", "Plugin")
@pi = nil
end
def create_plugin(manager, unused, view)
@pi = RBA::Plugin::new
@pi
end
def pi
@pi
end
end
class Plugin2 < RBA::Plugin
def set_tp(tp)
@tp = tp
end
def has_tracking_position
!!@tp
end
def tracking_position
@tp || RBA::DPoint::new
end
end
class PluginFactory2 < RBA::PluginFactory
def initialize()
register(1001, "plugin_for_test2", "Plugin2")
@pi = nil
end
def create_plugin(manager, unused, view)
@pi = Plugin2::new
@pi
end
def pi
@pi
end
end
class LayPlugin_TestClass < TestBase
def test_1
assert_equal(RBA::Plugin::AC_Global.to_s, "AC_Global")
assert_equal(RBA::Plugin::AC_Any.to_s, "AC_Any")
assert_equal(RBA::Plugin::AC_Diagonal.to_s, "AC_Diagonal")
assert_equal(RBA::Plugin::AC_Horizontal.to_s, "AC_Horizontal")
assert_equal(RBA::Plugin::AC_Vertical.to_s, "AC_Vertical")
assert_equal(RBA::Plugin::ac_from_buttons(0), RBA::Plugin::AC_Global)
assert_equal(RBA::Plugin::ac_from_buttons(1), RBA::Plugin::AC_Ortho)
assert_equal(RBA::Plugin::ac_from_buttons(2), RBA::Plugin::AC_Diagonal)
begin
dpi = PluginFactory::new
dpi2 = PluginFactory2::new
# Create a new layout
main_window = RBA::MainWindow.instance()
main_window.close_all
main_window.create_layout(2)
pi = dpi.pi
pi2 = dpi2.pi
# smoke test
pi.grab_mouse
pi.ungrab_mouse
pi.set_cursor(RBA::Cursor::Wait)
pi.add_edge_marker(RBA::DEdge::new)
pi.add_mouse_cursor(RBA::DPoint::new)
pi.clear_mouse_cursors
# virtual methods
assert_equal(pi.has_tracking_position_test, false)
pi.clear_mouse_cursors
pi.add_mouse_cursor(RBA::DPoint::new(1, 2))
assert_equal(pi.has_tracking_position_test, true)
assert_equal(pi.tracking_position_test.to_s, "1,2")
pi.clear_mouse_cursors
assert_equal(pi.has_tracking_position_test, false)
assert_equal(pi2.has_tracking_position_test, false)
pi2.set_tp(RBA::DPoint::new(2, 3))
assert_equal(pi2.has_tracking_position_test, true)
assert_equal(pi2.tracking_position_test.to_s, "2,3")
pi2.set_tp(nil)
assert_equal(pi2.has_tracking_position_test, false)
pi.configure_test("edit-grid", "0.0")
assert_equal(pi.snap(RBA::DPoint::new(0.01, 0.02)).to_s, "0.01,0.02")
assert_equal(pi.snap(RBA::DVector::new(0.01, 0.02)).to_s, "0.01,0.02")
pi.configure_test("edit-grid", "0.1")
assert_equal(pi.snap(RBA::DPoint::new(0.11, 0.18)).to_s, "0.1,0.2")
assert_equal(pi.snap(RBA::DVector::new(0.11, 0.18)).to_s, "0.1,0.2")
pi.configure_test("edit-connect-angle-mode", "ortho")
assert_equal(pi.snap(RBA::DPoint::new(1.5, 2.1), RBA::DPoint::new(1, 2), true).to_s, "1.5,2")
assert_equal(pi.snap(RBA::DPoint::new(1.5, 2.1), RBA::DPoint::new(1, 2), false).to_s, "1.5,2.1")
assert_equal(pi.snap(RBA::DPoint::new(1.5, 2.1), RBA::DPoint::new(1, 2), false, RBA::Plugin::AC_Ortho).to_s, "1.5,2")
pi.configure_test("edit-connect-angle-mode", "ortho")
assert_equal(pi.snap(RBA::DVector::new(0.5, 2.1), true).to_s, "0,2.1")
assert_equal(pi.snap(RBA::DVector::new(0.5, 2.1), false).to_s, "0.5,2.1")
assert_equal(pi.snap(RBA::DVector::new(0.5, 2.1), false, RBA::Plugin::AC_Ortho).to_s, "0,2.1")
ensure
main_window.close_all
dpi._destroy
dpi2._destroy
end
end
end
load("test_epilogue.rb")