From f9899efea3d1621e21c6eb3237aebfdb353f6d22 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 29 Jun 2024 23:02:29 +0200 Subject: [PATCH 1/4] First implementation --- .../laybasic/gsiDeclLayLayoutViewBase.cc | 40 +++++++- src/laybasic/laybasic/gsiDeclLayMarker.cc | 95 +++++++++++++------ src/laybasic/laybasic/layMarker.cc | 2 +- src/laybasic/laybasic/layViewObject.cc | 34 ++++++- src/laybasic/laybasic/layViewObject.h | 18 ++++ 5 files changed, 154 insertions(+), 35 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc index 6674eb17c..bad7a7831 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc @@ -469,6 +469,20 @@ static LayerPropertiesConstIteratorWrapper each_layer2 (lay::LayoutViewBase *vie return LayerPropertiesConstIteratorWrapper (view->begin_layers (list_index)); } +static void add_object (lay::LayoutViewBase *view, lay::ViewObject *object) +{ + if (view->canvas ()) { + view->canvas ()->add_object (object); + } +} + +static void clear_objects (lay::LayoutViewBase *view) +{ + if (view->canvas ()) { + view->canvas ()->clear_objects (); + } +} + static lay::AbstractMenu *menu (lay::LayoutViewBase *view) { return view->menu (); @@ -679,6 +693,30 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi "\n" "In 0.25, this method has been moved from MainWindow to LayoutView.\n" ) + + gsi::method_ext ("add_marker", &add_object, gsi::arg ("marker"), + "@brief Adds a persistent marker to the view (transferring ownership)\n" + "\n" + "This method allows creating markers and transferring ownership to the view, hence making them persistent. " + "This means, when the variable with the marker object goes out of scope, the marker will still exists in the view.\n" + "\n" + "To create a persistent marker, use the following code:\n" + "\n" + "@code\n" + "marker = RBA::Marker::new\n" + "# ... configure marker ...\n" + "view.add_marker(marker)\n" + "@/code\n" + "\n" + "To remove all persistent markers owned by the view, use \\clear_markers.\n" + "\n" + "Persistent markers have been introduced in version 0.29.3\n" + ) + + gsi::method_ext ("clear_markers", &clear_objects, + "@brief Clears all persistent markers from the view\n" + "See \\add_marker for details about persistent markers.\n" + "\n" + "Persistent markers have been introduced in version 0.29.3\n" + ) + gsi::method ("is_editable?", static_cast (&lay::LayoutViewBase::is_editable), "@brief Returns true if the view is in editable mode\n" "\n" @@ -836,7 +874,7 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi gsi::method ("active_cellview_index", static_cast (&lay::LayoutViewBase::active_cellview_index), "@brief Gets the index of the active cellview (shown in hierarchy browser)\n" ) + - gsi::method ("active_setview_index=|#set_active_cellview_index", &lay::LayoutViewBase::set_active_cellview_index, gsi::arg ("index"), + gsi::method ("active_cellview_index=|#active_setview_index=|#set_active_cellview_index", &lay::LayoutViewBase::set_active_cellview_index, gsi::arg ("index"), "@brief Makes the cellview with the given index the active one (shown in hierarchy browser)\n" "See \\active_cellview_index.\n" "\n" diff --git a/src/laybasic/laybasic/gsiDeclLayMarker.cc b/src/laybasic/laybasic/gsiDeclLayMarker.cc index d79580349..d47a1e950 100644 --- a/src/laybasic/laybasic/gsiDeclLayMarker.cc +++ b/src/laybasic/laybasic/gsiDeclLayMarker.cc @@ -28,44 +28,56 @@ namespace gsi { +/** + * @brief A managed version of the marker class + */ +class ManagedDMarker + : public lay::DMarker, public gsi::ObjectBase +{ +public: + ManagedDMarker (lay::LayoutViewBase *view) + : lay::DMarker (view) + { } +}; + static lay::DMarker *create_marker (lay::LayoutViewBase *view) { - return new lay::DMarker (view); + return new ManagedDMarker (view); } static -void reset_frame_color (lay::DMarker *marker) +void reset_frame_color (ManagedDMarker *marker) { marker->set_frame_color (tl::Color ()); } static -void set_frame_color (lay::DMarker *marker, unsigned int color) +void set_frame_color (ManagedDMarker *marker, unsigned int color) { marker->set_frame_color (tl::Color (color)); } static -unsigned int get_frame_color (const lay::DMarker *marker) +unsigned int get_frame_color (const ManagedDMarker *marker) { return marker->get_frame_color ().rgb (); } static -bool has_frame_color (const lay::DMarker *marker) +bool has_frame_color (const ManagedDMarker *marker) { return marker->get_frame_color ().is_valid (); } static -void reset_color (lay::DMarker *marker) +void reset_color (ManagedDMarker *marker) { marker->set_color (tl::Color ()); } static -void set_color (lay::DMarker *marker, unsigned int color) +void set_color (ManagedDMarker *marker, unsigned int color) { marker->set_color (tl::Color (color)); } @@ -77,44 +89,48 @@ unsigned int get_color (const lay::DMarker *marker) } static -bool has_color (const lay::DMarker *marker) +bool has_color (const ManagedDMarker *marker) { return marker->get_color ().is_valid (); } -Class decl_Marker ("lay", "Marker", - gsi::constructor ("new", &create_marker, gsi::arg ("view"), +Class decl_Marker ("lay", "Marker", + gsi::constructor ("new", &create_marker, gsi::arg ("view", (lay::LayoutViewBase *) 0, "nil"), "@brief Creates a marker\n" "\n" "A marker is always associated with a view, in which it is shown. The " - "view this marker is associated with must be passed to the constructor." + "view this marker is associated with must be passed to the constructor.\n" + "\n" + "See the class description about the options for attaching markers to a view.\n" + "\n" + "The 'view' argument is optional since version 0.29.3." ) + - gsi::method ("set|set_box", (void (lay::DMarker::*) (const db::DBox &)) &lay::DMarker::set, gsi::arg ("box"), + gsi::method ("set|set_box", (void (ManagedDMarker::*) (const db::DBox &)) &ManagedDMarker::set, gsi::arg ("box"), "@brief Sets the box the marker is to display\n" "\n" "Makes the marker show a box. The box must be given in micron units.\n" "If the box is empty, no marker is drawn.\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("set|set_text", (void (lay::DMarker::*) (const db::DText &)) &lay::DMarker::set, gsi::arg ("text"), + gsi::method ("set|set_text", (void (ManagedDMarker::*) (const db::DText &)) &ManagedDMarker::set, gsi::arg ("text"), "@brief Sets the text the marker is to display\n" "\n" "Makes the marker show a text. The text must be given in micron units.\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("set|set_edge", (void (lay::DMarker::*) (const db::DEdge &)) &lay::DMarker::set, gsi::arg ("edge"), + gsi::method ("set|set_edge", (void (ManagedDMarker::*) (const db::DEdge &)) &ManagedDMarker::set, gsi::arg ("edge"), "@brief Sets the edge the marker is to display\n" "\n" "Makes the marker show a edge. The edge must be given in micron units.\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("set|set_path", (void (lay::DMarker::*) (const db::DPath &)) &lay::DMarker::set, gsi::arg ("path"), + gsi::method ("set|set_path", (void (ManagedDMarker::*) (const db::DPath &)) &ManagedDMarker::set, gsi::arg ("path"), "@brief Sets the path the marker is to display\n" "\n" "Makes the marker show a path. The path must be given in micron units.\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("set|set_polygon", (void (lay::DMarker::*) (const db::DPolygon &)) &lay::DMarker::set, gsi::arg ("polygon"), + gsi::method ("set|set_polygon", (void (ManagedDMarker::*) (const db::DPolygon &)) &ManagedDMarker::set, gsi::arg ("polygon"), "@brief Sets the polygon the marker is to display\n" "\n" "Makes the marker show a polygon. The polygon must be given in micron units.\n" @@ -156,59 +172,59 @@ Class decl_Marker ("lay", "Marker", "@brief Returns a value indicating whether the marker has a specific frame color\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("dismissable=", &lay::DMarker::set_dismissable, gsi::arg ("flag"), + gsi::method ("dismissable=", (void (ManagedDMarker::*) (bool)) &ManagedDMarker::set_dismissable, gsi::arg ("flag"), "@brief Sets a value indicating whether the marker can be hidden\n" "Dismissable markers can be hidden setting \"View/Show Markers\" to \"off\". " "The default setting is \"false\" meaning the marker can't be hidden.\n" "\n" "This attribute has been introduced in version 0.25.4." ) + - gsi::method ("dismissable?", &lay::DMarker::get_dismissable, + gsi::method ("dismissable?", (bool (ManagedDMarker::*) () const) &ManagedDMarker::get_dismissable, "@brief Gets a value indicating whether the marker can be hidden\n" "See \\dismissable= for a description of this predicate." ) + - gsi::method ("line_width=", &lay::DMarker::set_line_width, gsi::arg ("width"), + gsi::method ("line_width=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_line_width, gsi::arg ("width"), "@brief Sets the line width of the marker\n" "This is the width of the line drawn for the outline of the marker." ) + - gsi::method ("line_width", &lay::DMarker::get_line_width, + gsi::method ("line_width", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_line_width, "@brief Gets the line width of the marker\n" "See \\line_width= for a description of the line width." ) + - gsi::method ("vertex_size=", &lay::DMarker::set_vertex_size, gsi::arg ("size"), + gsi::method ("vertex_size=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_vertex_size, gsi::arg ("size"), "@brief Sets the vertex size of the marker\n" "This is the size of the rectangles drawn for the vertices object." ) + - gsi::method ("vertex_size", &lay::DMarker::get_vertex_size, + gsi::method ("vertex_size", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_vertex_size, "@brief Gets the vertex size of the marker\n" "See \\vertex_size= for a description." ) + - gsi::method ("halo=", &lay::DMarker::set_halo, gsi::arg ("halo"), + gsi::method ("halo=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_halo, gsi::arg ("halo"), "@brief Sets the halo flag\n" "The halo flag is either -1 (for taking the default), 0 to disable the halo or 1 to enable it. " "If the halo is enabled, a pixel border with the background color is drawn around the marker, the " "vertices and texts." ) + - gsi::method ("halo", &lay::DMarker::get_halo, + gsi::method ("halo", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_halo, "@brief Gets the halo flag\n" "See \\halo= for a description of the halo flag." ) + - gsi::method ("dither_pattern=", &lay::DMarker::set_dither_pattern, gsi::arg ("index"), + gsi::method ("dither_pattern=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_dither_pattern, gsi::arg ("index"), "@brief Sets the stipple pattern index\n" "A value of -1 or less than zero indicates that the marker is not filled. Otherwise, the " "value indicates which pattern to use for filling the marker." ) + - gsi::method ("dither_pattern", &lay::DMarker::get_dither_pattern, + gsi::method ("dither_pattern", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_dither_pattern, "@brief Gets the stipple pattern index\n" "See \\dither_pattern= for a description of the stipple pattern index." ) + - gsi::method ("line_style=", &lay::DMarker::set_line_style, gsi::arg ("index"), + gsi::method ("line_style=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_line_style, gsi::arg ("index"), "@brief Sets the line style\n" "The line style is given by an index. 0 is solid, 1 is dashed and so forth.\n" "\n" "This method has been introduced in version 0.25." ) + - gsi::method ("line_style", &lay::DMarker::get_line_style, + gsi::method ("line_style", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_line_style, "@brief Get the line style\n" "See \\line_style= for a description of the line style index." "\n" @@ -219,6 +235,29 @@ Class decl_Marker ("lay", "Marker", "The marker is a visual object that \"marks\" (highlights) a \n" "certain area of the layout, given by a database object. " "This object accepts database objects with floating-point coordinates in micron values.\n" + "\n" + "Since version 0.29.3, markers can be attached to views in two ways: self-managed or persistent.\n" + "\n" + "Self-managed markers are created with a view argument. When the variable goes out of scope, the " + "and the Marker object is released, the marker vanishes. This was the concept before 0.29.3:\n" + "\n" + "@code\n" + "view = ... # some LayoutView\n" + "marker = RBA::Marker::new(view)\n" + "@/code\n" + "\n" + "Persistent markers are attached to the view and stay within the view. To remove persistent markers, " + "use \\LayoutView#clear_markers or use \\_destroy on the marker:\n" + "\n" + "@code\n" + "view = ... # some LayoutView\n" + "marker = RBA::Marker::new\n" + "view.add_marker(marker)\n" + "...\n" + "view.clear_markers\n" + "@/code\n" + "\n" + "Persistent markers do not need to be held in separate variables to keep them visible." ); } diff --git a/src/laybasic/laybasic/layMarker.cc b/src/laybasic/laybasic/layMarker.cc index ec05152c5..dabea8f11 100644 --- a/src/laybasic/laybasic/layMarker.cc +++ b/src/laybasic/laybasic/layMarker.cc @@ -197,7 +197,7 @@ void render_cell_inst (const db::Layout &layout, const db::CellInstArray &inst, // ------------------------------------------------------------------------ MarkerBase::MarkerBase (lay::LayoutViewBase *view) - : lay::ViewObject (view->canvas ()), + : lay::ViewObject (view ? view->canvas () : 0), m_line_width (-1), m_vertex_size (-1), m_halo (-1), m_text_enabled (true), m_vertex_shape (lay::ViewOp::Rect), m_line_style (-1), m_dither_pattern (-1), m_frame_pattern (0), mp_view (view) { // .. nothing yet .. diff --git a/src/laybasic/laybasic/layViewObject.cc b/src/laybasic/laybasic/layViewObject.cc index d794fe87f..3b9e5013b 100644 --- a/src/laybasic/laybasic/layViewObject.cc +++ b/src/laybasic/laybasic/layViewObject.cc @@ -118,12 +118,9 @@ BackgroundViewObject::z_order (int z) // ViewObject implementation ViewObject::ViewObject (ViewObjectUI *widget, bool _static) - : mp_widget (widget), m_static (_static), m_visible (true), m_dismissable (false) + : mp_widget (0), m_static (_static), m_visible (true), m_dismissable (false) { - if (widget) { - widget->m_objects.push_back (this); - redraw (); - } + set_widget (widget); } ViewObject::~ViewObject () @@ -131,6 +128,19 @@ ViewObject::~ViewObject () redraw (); } +void +ViewObject::set_widget (ViewObjectUI *widget) +{ + if (mp_widget) { + mp_widget->m_objects.erase (this); + } + mp_widget = widget; + if (widget) { + widget->m_objects.push_back (this); + redraw (); + } +} + void ViewObject::set_dismissable (bool dismissable) { @@ -535,6 +545,20 @@ ViewObjectUI::init_ui (QWidget *parent) } #endif +void +ViewObjectUI::add_object (lay::ViewObject *object) +{ + object->set_widget (this); + m_owned_objects.push_back (object); + m_objects.push_back (object); +} + +void +ViewObjectUI::clear_objects () +{ + m_owned_objects.clear (); +} + void ViewObjectUI::register_service (lay::ViewService *svc) { diff --git a/src/laybasic/laybasic/layViewObject.h b/src/laybasic/laybasic/layViewObject.h index 8ba1bebb9..3c5ee7199 100644 --- a/src/laybasic/laybasic/layViewObject.h +++ b/src/laybasic/laybasic/layViewObject.h @@ -439,6 +439,13 @@ public: */ virtual ~ViewObject (); + /** + * @brief Attaches a view object to a widget + * + * This will register the object at the widget, but not transfer ownership. + */ + void set_widget (ViewObjectUI *widget); + /** * @brief Render the object on the planes provided by the canvas. * @@ -785,6 +792,16 @@ public: return m_objects.end (); } + /** + * @brief Adds an object, transferring ownership to the view + */ + void add_object (lay::ViewObject *object); + + /** + * @brief Clears all objects owned by the view + */ + void clear_objects (); + /** * @brief Remaining leave event handler * @@ -1073,6 +1090,7 @@ private: QWidget *mp_widget; #endif tl::weak_collection m_objects; + tl::shared_collection m_owned_objects; tl::weak_collection m_background_objects; std::list m_services; std::list m_grabbed; From b92c7bf225bebb0d7fc41fd9e2a7057476789326 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 29 Jun 2024 23:22:32 +0200 Subject: [PATCH 2/4] Refined solution --- .../laybasic/gsiDeclLayLayoutViewBase.cc | 10 +-- src/laybasic/laybasic/gsiDeclLayMarker.cc | 66 ++++++++----------- src/laybasic/laybasic/layMarker.h | 16 +++++ testdata/ruby/layMarkers.rb | 23 +++++++ 4 files changed, 72 insertions(+), 43 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc index bad7a7831..9dce193e2 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc @@ -28,6 +28,7 @@ #include "layLayoutViewBase.h" #include "layDitherPattern.h" #include "layLineStyles.h" +#include "layMarker.h" #include "dbSaveLayoutOptions.h" #include "dbLayoutToNetlist.h" #include "dbLayoutVsSchematic.h" @@ -469,15 +470,16 @@ static LayerPropertiesConstIteratorWrapper each_layer2 (lay::LayoutViewBase *vie return LayerPropertiesConstIteratorWrapper (view->begin_layers (list_index)); } -static void add_object (lay::LayoutViewBase *view, lay::ViewObject *object) +static void add_marker (lay::LayoutViewBase *view, lay::ManagedDMarker *object) { if (view->canvas ()) { view->canvas ()->add_object (object); } } -static void clear_objects (lay::LayoutViewBase *view) +static void clear_markers (lay::LayoutViewBase *view) { + // NOTE: this will clear *all* persistent objects, not just our markers if (view->canvas ()) { view->canvas ()->clear_objects (); } @@ -693,7 +695,7 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi "\n" "In 0.25, this method has been moved from MainWindow to LayoutView.\n" ) + - gsi::method_ext ("add_marker", &add_object, gsi::arg ("marker"), + gsi::method_ext ("add_marker", &add_marker, gsi::arg ("marker"), "@brief Adds a persistent marker to the view (transferring ownership)\n" "\n" "This method allows creating markers and transferring ownership to the view, hence making them persistent. " @@ -711,7 +713,7 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi "\n" "Persistent markers have been introduced in version 0.29.3\n" ) + - gsi::method_ext ("clear_markers", &clear_objects, + gsi::method_ext ("clear_markers", &clear_markers, "@brief Clears all persistent markers from the view\n" "See \\add_marker for details about persistent markers.\n" "\n" diff --git a/src/laybasic/laybasic/gsiDeclLayMarker.cc b/src/laybasic/laybasic/gsiDeclLayMarker.cc index d47a1e950..5c0f5f4b3 100644 --- a/src/laybasic/laybasic/gsiDeclLayMarker.cc +++ b/src/laybasic/laybasic/gsiDeclLayMarker.cc @@ -28,56 +28,44 @@ namespace gsi { -/** - * @brief A managed version of the marker class - */ -class ManagedDMarker - : public lay::DMarker, public gsi::ObjectBase -{ -public: - ManagedDMarker (lay::LayoutViewBase *view) - : lay::DMarker (view) - { } -}; - static -lay::DMarker *create_marker (lay::LayoutViewBase *view) +lay::ManagedDMarker *create_marker (lay::LayoutViewBase *view) { - return new ManagedDMarker (view); + return new lay::ManagedDMarker (view); } static -void reset_frame_color (ManagedDMarker *marker) +void reset_frame_color (lay::ManagedDMarker *marker) { marker->set_frame_color (tl::Color ()); } static -void set_frame_color (ManagedDMarker *marker, unsigned int color) +void set_frame_color (lay::ManagedDMarker *marker, unsigned int color) { marker->set_frame_color (tl::Color (color)); } static -unsigned int get_frame_color (const ManagedDMarker *marker) +unsigned int get_frame_color (const lay::ManagedDMarker *marker) { return marker->get_frame_color ().rgb (); } static -bool has_frame_color (const ManagedDMarker *marker) +bool has_frame_color (const lay::ManagedDMarker *marker) { return marker->get_frame_color ().is_valid (); } static -void reset_color (ManagedDMarker *marker) +void reset_color (lay::ManagedDMarker *marker) { marker->set_color (tl::Color ()); } static -void set_color (ManagedDMarker *marker, unsigned int color) +void set_color (lay::ManagedDMarker *marker, unsigned int color) { marker->set_color (tl::Color (color)); } @@ -89,12 +77,12 @@ unsigned int get_color (const lay::DMarker *marker) } static -bool has_color (const ManagedDMarker *marker) +bool has_color (const lay::ManagedDMarker *marker) { return marker->get_color ().is_valid (); } -Class decl_Marker ("lay", "Marker", +Class decl_Marker ("lay", "Marker", gsi::constructor ("new", &create_marker, gsi::arg ("view", (lay::LayoutViewBase *) 0, "nil"), "@brief Creates a marker\n" "\n" @@ -105,32 +93,32 @@ Class decl_Marker ("lay", "Marker", "\n" "The 'view' argument is optional since version 0.29.3." ) + - gsi::method ("set|set_box", (void (ManagedDMarker::*) (const db::DBox &)) &ManagedDMarker::set, gsi::arg ("box"), + gsi::method ("set|set_box", (void (lay::ManagedDMarker::*) (const db::DBox &)) &lay::ManagedDMarker::set, gsi::arg ("box"), "@brief Sets the box the marker is to display\n" "\n" "Makes the marker show a box. The box must be given in micron units.\n" "If the box is empty, no marker is drawn.\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("set|set_text", (void (ManagedDMarker::*) (const db::DText &)) &ManagedDMarker::set, gsi::arg ("text"), + gsi::method ("set|set_text", (void (lay::ManagedDMarker::*) (const db::DText &)) &lay::ManagedDMarker::set, gsi::arg ("text"), "@brief Sets the text the marker is to display\n" "\n" "Makes the marker show a text. The text must be given in micron units.\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("set|set_edge", (void (ManagedDMarker::*) (const db::DEdge &)) &ManagedDMarker::set, gsi::arg ("edge"), + gsi::method ("set|set_edge", (void (lay::ManagedDMarker::*) (const db::DEdge &)) &lay::ManagedDMarker::set, gsi::arg ("edge"), "@brief Sets the edge the marker is to display\n" "\n" "Makes the marker show a edge. The edge must be given in micron units.\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("set|set_path", (void (ManagedDMarker::*) (const db::DPath &)) &ManagedDMarker::set, gsi::arg ("path"), + gsi::method ("set|set_path", (void (lay::ManagedDMarker::*) (const db::DPath &)) &lay::ManagedDMarker::set, gsi::arg ("path"), "@brief Sets the path the marker is to display\n" "\n" "Makes the marker show a path. The path must be given in micron units.\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("set|set_polygon", (void (ManagedDMarker::*) (const db::DPolygon &)) &ManagedDMarker::set, gsi::arg ("polygon"), + gsi::method ("set|set_polygon", (void (lay::ManagedDMarker::*) (const db::DPolygon &)) &lay::ManagedDMarker::set, gsi::arg ("polygon"), "@brief Sets the polygon the marker is to display\n" "\n" "Makes the marker show a polygon. The polygon must be given in micron units.\n" @@ -172,59 +160,59 @@ Class decl_Marker ("lay", "Marker", "@brief Returns a value indicating whether the marker has a specific frame color\n" "The set method has been added in version 0.20.\n" ) + - gsi::method ("dismissable=", (void (ManagedDMarker::*) (bool)) &ManagedDMarker::set_dismissable, gsi::arg ("flag"), + gsi::method ("dismissable=", (void (lay::ManagedDMarker::*) (bool)) &lay::ManagedDMarker::set_dismissable, gsi::arg ("flag"), "@brief Sets a value indicating whether the marker can be hidden\n" "Dismissable markers can be hidden setting \"View/Show Markers\" to \"off\". " "The default setting is \"false\" meaning the marker can't be hidden.\n" "\n" "This attribute has been introduced in version 0.25.4." ) + - gsi::method ("dismissable?", (bool (ManagedDMarker::*) () const) &ManagedDMarker::get_dismissable, + gsi::method ("dismissable?", (bool (lay::ManagedDMarker::*) () const) &lay::ManagedDMarker::get_dismissable, "@brief Gets a value indicating whether the marker can be hidden\n" "See \\dismissable= for a description of this predicate." ) + - gsi::method ("line_width=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_line_width, gsi::arg ("width"), + gsi::method ("line_width=", (void (lay::ManagedDMarker::*) (int)) &lay::ManagedDMarker::set_line_width, gsi::arg ("width"), "@brief Sets the line width of the marker\n" "This is the width of the line drawn for the outline of the marker." ) + - gsi::method ("line_width", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_line_width, + gsi::method ("line_width", (int (lay::ManagedDMarker::*) () const) &lay::ManagedDMarker::get_line_width, "@brief Gets the line width of the marker\n" "See \\line_width= for a description of the line width." ) + - gsi::method ("vertex_size=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_vertex_size, gsi::arg ("size"), + gsi::method ("vertex_size=", (void (lay::ManagedDMarker::*) (int)) &lay::ManagedDMarker::set_vertex_size, gsi::arg ("size"), "@brief Sets the vertex size of the marker\n" "This is the size of the rectangles drawn for the vertices object." ) + - gsi::method ("vertex_size", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_vertex_size, + gsi::method ("vertex_size", (int (lay::ManagedDMarker::*) () const) &lay::ManagedDMarker::get_vertex_size, "@brief Gets the vertex size of the marker\n" "See \\vertex_size= for a description." ) + - gsi::method ("halo=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_halo, gsi::arg ("halo"), + gsi::method ("halo=", (void (lay::ManagedDMarker::*) (int)) &lay::ManagedDMarker::set_halo, gsi::arg ("halo"), "@brief Sets the halo flag\n" "The halo flag is either -1 (for taking the default), 0 to disable the halo or 1 to enable it. " "If the halo is enabled, a pixel border with the background color is drawn around the marker, the " "vertices and texts." ) + - gsi::method ("halo", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_halo, + gsi::method ("halo", (int (lay::ManagedDMarker::*) () const) &lay::ManagedDMarker::get_halo, "@brief Gets the halo flag\n" "See \\halo= for a description of the halo flag." ) + - gsi::method ("dither_pattern=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_dither_pattern, gsi::arg ("index"), + gsi::method ("dither_pattern=", (void (lay::ManagedDMarker::*) (int)) &lay::ManagedDMarker::set_dither_pattern, gsi::arg ("index"), "@brief Sets the stipple pattern index\n" "A value of -1 or less than zero indicates that the marker is not filled. Otherwise, the " "value indicates which pattern to use for filling the marker." ) + - gsi::method ("dither_pattern", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_dither_pattern, + gsi::method ("dither_pattern", (int (lay::ManagedDMarker::*) () const) &lay::ManagedDMarker::get_dither_pattern, "@brief Gets the stipple pattern index\n" "See \\dither_pattern= for a description of the stipple pattern index." ) + - gsi::method ("line_style=", (void (ManagedDMarker::*) (int)) &ManagedDMarker::set_line_style, gsi::arg ("index"), + gsi::method ("line_style=", (void (lay::ManagedDMarker::*) (int)) &lay::ManagedDMarker::set_line_style, gsi::arg ("index"), "@brief Sets the line style\n" "The line style is given by an index. 0 is solid, 1 is dashed and so forth.\n" "\n" "This method has been introduced in version 0.25." ) + - gsi::method ("line_style", (int (ManagedDMarker::*) () const) &ManagedDMarker::get_line_style, + gsi::method ("line_style", (int (lay::ManagedDMarker::*) () const) &lay::ManagedDMarker::get_line_style, "@brief Get the line style\n" "See \\line_style= for a description of the line style index." "\n" diff --git a/src/laybasic/laybasic/layMarker.h b/src/laybasic/laybasic/layMarker.h index 4dc705215..14312380e 100644 --- a/src/laybasic/laybasic/layMarker.h +++ b/src/laybasic/laybasic/layMarker.h @@ -40,6 +40,7 @@ #include "dbEdgePair.h" #include "dbArray.h" #include "gsi.h" +#include "gsiObject.h" namespace lay { @@ -831,6 +832,21 @@ private: lay::LayoutViewBase *mp_view; }; +/** + * @brief A managed version of the marker class + * + * It uses gsi::ObjectBase as a base class and serves as + * proxy for GSI binding. + */ +class ManagedDMarker + : public lay::DMarker, public gsi::ObjectBase +{ +public: + ManagedDMarker (lay::LayoutViewBase *view) + : lay::DMarker (view) + { } +}; + } #endif diff --git a/testdata/ruby/layMarkers.rb b/testdata/ruby/layMarkers.rb index 0947994a7..3d624cb83 100644 --- a/testdata/ruby/layMarkers.rb +++ b/testdata/ruby/layMarkers.rb @@ -77,6 +77,29 @@ class LAYMarkers_TestClass < TestBase end + # persistent markers + def test_2 + + if !RBA.constants.member?(:Application) + return + end + + app = RBA::Application.instance + mw = app.main_window + mw.create_layout(0) + cv = mw.current_view + + m = RBA::Marker.new + m.set(RBA::DBox.new(1, 2, 3, 4)) + m.vertex_size = 3 + cv.add_marker(m) + + cv.clear_markers + + assert_equal(m.destroyed?, true) + + end + end load("test_epilogue.rb") From 7eadac527bc181ee06e7eee32d044bba57188b56 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 29 Jun 2024 23:55:02 +0200 Subject: [PATCH 3/4] Debugging and finalization --- .../laybasic/gsiDeclLayLayoutViewBase.cc | 2 ++ src/laybasic/laybasic/layMarker.cc | 27 ++++++++++++------- src/laybasic/laybasic/layMarker.h | 21 +++++++-------- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc index 9dce193e2..22e12cc9c 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc @@ -474,6 +474,8 @@ static void add_marker (lay::LayoutViewBase *view, lay::ManagedDMarker *object) { if (view->canvas ()) { view->canvas ()->add_object (object); + object->keep (); + object->set_view (view); } } diff --git a/src/laybasic/laybasic/layMarker.cc b/src/laybasic/laybasic/layMarker.cc index dabea8f11..42b8d2d61 100644 --- a/src/laybasic/laybasic/layMarker.cc +++ b/src/laybasic/laybasic/layMarker.cc @@ -203,7 +203,16 @@ MarkerBase::MarkerBase (lay::LayoutViewBase *view) // .. nothing yet .. } -void +void +MarkerBase::set_view (LayoutViewBase *view) +{ + if (mp_view != view) { + mp_view = view; + redraw (); + } +} + +void MarkerBase::set_frame_color (tl::Color color) { if (color != m_frame_color) { @@ -381,7 +390,7 @@ MarkerBase::get_bitmaps (const Viewport & /*vp*/, ViewObjectCanvas &canvas, lay: // ------------------------------------------------------------------------ GenericMarkerBase::GenericMarkerBase (lay::LayoutViewBase *view, unsigned int cv_index) - : MarkerBase (view), mp_trans_vector (0), mp_view (view), m_cv_index (cv_index) + : MarkerBase (view), mp_trans_vector (0), m_cv_index (cv_index) { // .. nothing yet .. } @@ -463,7 +472,7 @@ GenericMarkerBase::set (const db::DCplxTrans &t1, const std::vectorcellview (m_cv_index); + const lay::CellView &cv = view ()->cellview (m_cv_index); if (! cv.is_valid ()) { return db::DBox (); } @@ -483,11 +492,11 @@ GenericMarkerBase::bbox () const const db::Layout * GenericMarkerBase::layout () const { - if (m_cv_index >= (unsigned int) (mp_view->cellviews ())) { + if (m_cv_index >= (unsigned int) (view ()->cellviews ())) { return 0; } - const lay::CellView &cv = mp_view->cellview (m_cv_index); + const lay::CellView &cv = view ()->cellview (m_cv_index); if (! cv.is_valid ()) { return 0; } else { @@ -1175,7 +1184,7 @@ Marker::render (const Viewport &vp, ViewObjectCanvas &canvas) // ------------------------------------------------------------------------ DMarker::DMarker (LayoutViewBase *view) - : MarkerBase (view), mp_view (view) + : MarkerBase (view) { m_type = None; m_object.any = 0; @@ -1304,9 +1313,9 @@ DMarker::render (const Viewport &vp, ViewObjectCanvas &canvas) lay::Renderer &r = canvas.renderer (); - r.set_font (db::Font (mp_view->text_font ())); - r.apply_text_trans (mp_view->apply_text_trans ()); - r.default_text_size (mp_view->default_text_size ()); + r.set_font (db::Font (view ()->text_font ())); + r.apply_text_trans (view ()->apply_text_trans ()); + r.default_text_size (view ()->default_text_size ()); r.set_precise (true); db::DCplxTrans t = vp.trans (); diff --git a/src/laybasic/laybasic/layMarker.h b/src/laybasic/laybasic/layMarker.h index 14312380e..1b0dd9629 100644 --- a/src/laybasic/laybasic/layMarker.h +++ b/src/laybasic/laybasic/layMarker.h @@ -62,6 +62,11 @@ public: */ MarkerBase (lay::LayoutViewBase *view); + /** + * @brief Attaches to a new view + */ + void set_view (lay::LayoutViewBase *view); + /** * @brief Get the color by which the marker is drawn * @@ -232,6 +237,11 @@ protected: return mp_view; } + const lay::LayoutViewBase *view () const + { + return mp_view; + } + private: tl::Color m_color; tl::Color m_frame_color; @@ -325,14 +335,6 @@ public: return m_cv_index; } - /** - * @brief Gets the view object - */ - lay::LayoutViewBase *view () const - { - return mp_view; - } - /** * @brief Gets the bounding box */ @@ -351,7 +353,6 @@ public: private: db::CplxTrans m_trans; std::vector *mp_trans_vector; - lay::LayoutViewBase *mp_view; unsigned int m_cv_index; /** @@ -828,8 +829,6 @@ private: db::DText *text; void *any; } m_object; - - lay::LayoutViewBase *mp_view; }; /** From a49f907cfa8bb1ab11c9386c461fde02ba64924e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 30 Jun 2024 00:07:52 +0200 Subject: [PATCH 4/4] Doc fixes --- src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc | 3 +-- src/laybasic/laybasic/gsiDeclLayMarker.cc | 11 +++++++---- src/laybasic/laybasic/layMarker.cc | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc index 22e12cc9c..a36fd0468 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc @@ -473,7 +473,6 @@ static LayerPropertiesConstIteratorWrapper each_layer2 (lay::LayoutViewBase *vie static void add_marker (lay::LayoutViewBase *view, lay::ManagedDMarker *object) { if (view->canvas ()) { - view->canvas ()->add_object (object); object->keep (); object->set_view (view); } @@ -701,7 +700,7 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi "@brief Adds a persistent marker to the view (transferring ownership)\n" "\n" "This method allows creating markers and transferring ownership to the view, hence making them persistent. " - "This means, when the variable with the marker object goes out of scope, the marker will still exists in the view.\n" + "This means, when the variable with the marker object goes out of scope, the marker will still exist in the view.\n" "\n" "To create a persistent marker, use the following code:\n" "\n" diff --git a/src/laybasic/laybasic/gsiDeclLayMarker.cc b/src/laybasic/laybasic/gsiDeclLayMarker.cc index 5c0f5f4b3..b6d423640 100644 --- a/src/laybasic/laybasic/gsiDeclLayMarker.cc +++ b/src/laybasic/laybasic/gsiDeclLayMarker.cc @@ -227,15 +227,17 @@ Class decl_Marker ("lay", "Marker", "Since version 0.29.3, markers can be attached to views in two ways: self-managed or persistent.\n" "\n" "Self-managed markers are created with a view argument. When the variable goes out of scope, the " - "and the Marker object is released, the marker vanishes. This was the concept before 0.29.3:\n" + "and the Marker object is released, the marker vanishes. This was the only concept before 0.29.3:\n" "\n" "@code\n" "view = ... # some LayoutView\n" "marker = RBA::Marker::new(view)\n" "@/code\n" "\n" - "Persistent markers are attached to the view and stay within the view. To remove persistent markers, " - "use \\LayoutView#clear_markers or use \\_destroy on the marker:\n" + "Persistent markers on the other hand are attached to the view and stay within the view. To create a " + "persistent marker, do not use a view argument to the constructor. Instead add them to the view using " + "\\LayoutView#add_marker. To remove persistent markers, " + "use \\LayoutView#clear_markers (removes all) or call \\_destroy on a specific marker:\n" "\n" "@code\n" "view = ... # some LayoutView\n" @@ -245,7 +247,8 @@ Class decl_Marker ("lay", "Marker", "view.clear_markers\n" "@/code\n" "\n" - "Persistent markers do not need to be held in separate variables to keep them visible." + "Persistent markers do not need to be held in separate variables to keep them visible. In some applications " + "this may be useful." ); } diff --git a/src/laybasic/laybasic/layMarker.cc b/src/laybasic/laybasic/layMarker.cc index 42b8d2d61..017b22f74 100644 --- a/src/laybasic/laybasic/layMarker.cc +++ b/src/laybasic/laybasic/layMarker.cc @@ -208,6 +208,7 @@ MarkerBase::set_view (LayoutViewBase *view) { if (mp_view != view) { mp_view = view; + mp_view->canvas ()->add_object (this); redraw (); } }