From 58417d5700bf19d0a15f69864ebde7a0492a767c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 23 Jul 2023 18:35:36 +0200 Subject: [PATCH 01/22] pya: adding hint about disambiuation of methods/properties to Python specific doc. --- src/pya/pya/pyaModule.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/pya/pya/pyaModule.cc b/src/pya/pya/pyaModule.cc index 7a1e83c1d..690bbf594 100644 --- a/src/pya/pya/pyaModule.cc +++ b/src/pya/pya/pyaModule.cc @@ -456,24 +456,27 @@ public: std::string name = mt->name (mid); - // does this method hide a property? -> append "_" in that case - std::pair t = mt->find_property (mt->is_static (mid), name); - if (t.first) { - name += "_"; - } - // needs static/non-static disambiguation? - t = mt->find_method (! mt->is_static (mid), name); + std::pair t = mt->find_method (! mt->is_static (mid), name); if (t.first) { disambiguated_names.push_back (name); if (mt->is_static (mid)) { name = "_class_" + name; + mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This class method is available as '%s' in Python")), name)); } else { name = "_inst_" + name; + mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This instance method is available as '%s' in Python")), name)); } - mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This attribute is available as '%s' in Python")), name)); + } else { + + // does this method hide a property? -> append "_" in that case + t = mt->find_property (mt->is_static (mid), name); + if (t.first) { + name += "_"; + mp_module->add_python_doc (*cls, mt, int (mid), tl::sprintf (tl::to_string (tr ("This method is available as '%s' in Python to distiguish it from the property with the same name")), name)); + } } From 8b44a3ba134ae2f6fcf2f9878340b2abaf98841f Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 28 Jul 2023 21:26:05 +0200 Subject: [PATCH 02/22] Fixing PCellDeclaration helper (correct use of 'raise' --- src/db/db/built-in-pymacros/pcell_declaration_helper.lym | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/db/db/built-in-pymacros/pcell_declaration_helper.lym b/src/db/db/built-in-pymacros/pcell_declaration_helper.lym index 1df6dcb53..7e0b3f8fe 100644 --- a/src/db/db/built-in-pymacros/pcell_declaration_helper.lym +++ b/src/db/db/built-in-pymacros/pcell_declaration_helper.lym @@ -358,10 +358,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration): pdecl.unit = unit if not (choices is None): if not isinstance(choices, list) and not isinstance(choices, tuple): - raise "choices value must be an list/tuple of two-element arrays (description, value)" + raise TypeError("choices value must be an list/tuple of two-element arrays (description, value)") for c in choices: if (not isinstance(choices, list) and not isinstance(choices, tuple)) or len(c) != 2: - raise "choices value must be an list/tuple of two-element arrays (description, value)" + raise TypeError("choices value must be an list/tuple of two-element arrays (description, value)") pdecl.add_choice(c[0],c[1]) # return the declaration object for further operations From a7e648c82bfd4e84faf4049dd4fbc68a779f849e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 28 Jul 2023 21:27:16 +0200 Subject: [PATCH 03/22] Fixed a doc typo --- src/lay/lay/macro_templates/pcell_python.lym | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lay/lay/macro_templates/pcell_python.lym b/src/lay/lay/macro_templates/pcell_python.lym index 2d7e3c334..1f36444ff 100644 --- a/src/lay/lay/macro_templates/pcell_python.lym +++ b/src/lay/lay/macro_templates/pcell_python.lym @@ -38,7 +38,7 @@ class PCell(pya.PCellDeclarationHelper): def produce_impl(self): # TODO: produce the cell content - # i.e. self.cell().shapes(self.l_layer).insert(pya.Polygon(...)) + # i.e. self.cell.shapes(self.l_layer).insert(pya.Polygon(...)) # optional: # def can_create_from_shape_impl(self): From 7ac51337cad9be8002e3673491657bcf8d698893 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 28 Jul 2023 21:28:09 +0200 Subject: [PATCH 04/22] Script errors now include the class for better readability in Python, normalizing errors in Python --- src/lay/lay/layApplication.cc | 4 ++-- src/pya/pya/pyaUtils.cc | 20 +++++++++++--------- src/tl/tl/tlScriptError.cc | 24 ++++++++++++++++++++---- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index aef4d5042..6a825293d 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -124,9 +124,9 @@ static void ui_exception_handler_tl (const tl::Exception &ex, QWidget *parent) if (gsi_excpt->line () > 0) { tl::error << gsi_excpt->sourcefile () << ":" << gsi_excpt->line () << ": " - << gsi_excpt->msg () << tl::to_string (QObject::tr (" (class ")) << gsi_excpt->cls () << ")"; + << gsi_excpt->msg (); } else { - tl::error << gsi_excpt->msg () << tl::to_string (QObject::tr (" (class ")) << gsi_excpt->cls () << ")"; + tl::error << gsi_excpt->msg (); } lay::RuntimeErrorForm error_dialog (parent, "ruby_error_form", gsi_excpt); diff --git a/src/pya/pya/pyaUtils.cc b/src/pya/pya/pyaUtils.cc index 939718d7b..a279bac18 100644 --- a/src/pya/pya/pyaUtils.cc +++ b/src/pya/pya/pyaUtils.cc @@ -44,17 +44,19 @@ void check_error () { PyObject *py_exc_type = NULL, *py_exc_value = NULL, *py_exc_traceback = NULL; PyErr_Fetch (&py_exc_type, &py_exc_value, &py_exc_traceback); - PythonRef exc_type (py_exc_type); - PythonRef exc_value (py_exc_value); - PythonRef exc_traceback (py_exc_traceback); + if (py_exc_type != NULL) { - std::string exc_cls ("unknown"); - const char *c = ((PyTypeObject *) exc_type.get ())->tp_name; - if (c) { - exc_cls = c; - } + PyErr_NormalizeException (&py_exc_type, &py_exc_value, &py_exc_traceback); - if (exc_type) { + PythonRef exc_type (py_exc_type); + PythonRef exc_value (py_exc_value); + PythonRef exc_traceback (py_exc_traceback); + + std::string exc_cls ("unknown"); + const char *c = ((PyTypeObject *) exc_type.get ())->tp_name; + if (c) { + exc_cls = c; + } // fetch traceback // TODO: really decref the stack trace? how about the other objects in the stack trace? diff --git a/src/tl/tl/tlScriptError.cc b/src/tl/tl/tlScriptError.cc index 67065fc74..aae4e56f9 100644 --- a/src/tl/tl/tlScriptError.cc +++ b/src/tl/tl/tlScriptError.cc @@ -79,14 +79,30 @@ BacktraceElement::to_string() const // ------------------------------------------------------------------- // ScriptError implementation +static std::string make_basic_msg (const char *text, const char *cls) +{ + std::string msg; + if (*cls) { + msg = cls; + } + if (*cls && *text) { + msg += ": "; + } + if (*text) { + msg += text; + } + return msg; +} + + ScriptError::ScriptError (const char *msg, const char *cls, const std::vector &backtrace) - : tl::Exception (msg), m_line (-1), m_cls (cls), m_backtrace (backtrace) + : tl::Exception (make_basic_msg (msg, cls)), m_line (-1), m_cls (cls), m_backtrace (backtrace) { // .. nothing yet .. } ScriptError::ScriptError (const char *msg, const char *sourcefile, int line, const char *cls, const std::vector &backtrace) - : tl::Exception (msg), m_sourcefile (sourcefile), m_line (line), m_cls (cls), m_backtrace (backtrace) + : tl::Exception (make_basic_msg (msg, cls)), m_sourcefile (sourcefile), m_line (line), m_cls (cls), m_backtrace (backtrace) { translate_includes (); } @@ -103,8 +119,8 @@ ScriptError::msg () const std::string m = basic_msg (); if (! m_context.empty ()) { - m += tl::to_string (tr (" in ")) + m_context; - } + m += tl::to_string (tr (" in ")) + m_context; + } for (std::vector::const_iterator bt = backtrace ().begin (); bt != backtrace ().end (); ++bt) { m += "\n "; From e766b12c3e03b67f5c8a54dd9c93927e792a0b6f Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 28 Jul 2023 21:52:51 +0200 Subject: [PATCH 05/22] Allowing PCell layer parameters without default (-> empty) --- src/db/db/built-in-macros/pcell_declaration_helper.lym | 2 +- src/db/db/built-in-pymacros/pcell_declaration_helper.lym | 5 ++++- src/db/db/gsiDeclDbLibrary.cc | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/db/db/built-in-macros/pcell_declaration_helper.lym b/src/db/db/built-in-macros/pcell_declaration_helper.lym index 30023a97a..43754b65d 100644 --- a/src/db/db/built-in-macros/pcell_declaration_helper.lym +++ b/src/db/db/built-in-macros/pcell_declaration_helper.lym @@ -408,7 +408,7 @@ module RBA # get the layer definitions def get_layers(parameters) - @layer_param_index.collect { |i| parameters[i] } + @layer_param_index.collect { |i| parameters[i] || RBA::LayerInfo::new } end # coerce parameters (make consistent) diff --git a/src/db/db/built-in-pymacros/pcell_declaration_helper.lym b/src/db/db/built-in-pymacros/pcell_declaration_helper.lym index 7e0b3f8fe..81ea44c44 100644 --- a/src/db/db/built-in-pymacros/pcell_declaration_helper.lym +++ b/src/db/db/built-in-pymacros/pcell_declaration_helper.lym @@ -430,7 +430,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration): """ layers = [] for i in self._layer_param_index: - layers.append(parameters[i]) + if parameters[i] is not None: + layers.append(parameters[i]) + else: + layers.append(pya.LayerInfo()) return layers def callback(self, layout, name, states): diff --git a/src/db/db/gsiDeclDbLibrary.cc b/src/db/db/gsiDeclDbLibrary.cc index dc8c6ed45..6dc75a636 100644 --- a/src/db/db/gsiDeclDbLibrary.cc +++ b/src/db/db/gsiDeclDbLibrary.cc @@ -263,7 +263,7 @@ static std::vector get_layer_declarations_native (const db: std::vector lp = pd->db::PCellDeclaration::get_layer_declarations (parameters); std::vector ret; for (std::vector::const_iterator l = lp.begin (); l != lp.end (); ++l) { - ret.push_back (db::LayerProperties(*l)); + ret.push_back (db::LayerProperties (*l)); } return ret; } From 6e4ac714421dc45902ff795572c8c42f415e6a0e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 28 Jul 2023 23:48:34 +0200 Subject: [PATCH 06/22] WIP --- src/db/db/dbPCellVariant.cc | 20 +- src/edt/edt/PointPropertiesPage.ui | 282 ++++++++++++++++++ src/edt/edt/edt.pro | 3 + src/edt/edt/edtMainService.cc | 2 + src/edt/edt/edtPartialService.cc | 3 + src/edt/edt/edtPlugin.cc | 14 +- src/edt/edt/edtPlugin.h | 1 + src/edt/edt/edtPropertiesPageUtils.cc | 36 +++ src/edt/edt/edtPropertiesPageUtils.h | 16 + src/edt/edt/edtPropertiesPages.cc | 118 ++++++++ src/edt/edt/edtPropertiesPages.h | 29 ++ src/edt/edt/edtServiceImpl.cc | 111 +++++++ src/edt/edt/edtServiceImpl.h | 28 ++ src/edt/edt/edtUtils.cc | 18 +- src/laybasic/laybasic/layBitmapRenderer.cc | 4 +- .../laybasic/layRedrawThreadWorker.cc | 4 +- src/laybasic/laybasic/layRenderer.cc | 2 + 17 files changed, 666 insertions(+), 25 deletions(-) create mode 100644 src/edt/edt/PointPropertiesPage.ui diff --git a/src/db/db/dbPCellVariant.cc b/src/db/db/dbPCellVariant.cc index 8f46f2199..e5660daf0 100644 --- a/src/db/db/dbPCellVariant.cc +++ b/src/db/db/dbPCellVariant.cc @@ -199,51 +199,51 @@ PCellVariant::update (ImportLayerMapping *layer_mapping) if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties (db::Box (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties (m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(db::Edge (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties (db::Edge (m_parameters[i].to_user () * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::EdgeWithProperties (m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::DPoint p = m_parameters[i].to_user (); - shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (db::DBox (p, p) * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PointWithProperties (db::Point (p * (1.0 / layout ()->dbu ())), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::Point p = m_parameters[i].to_user (); - shapes (layout ()->guiding_shape_layer ()).insert (db::BoxWithProperties(db::Box (p, p), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PointWithProperties (p, layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::complex_trans dbu_trans (1.0 / layout ()->dbu ()); db::Polygon poly = m_parameters[i].to_user ().transformed (dbu_trans, false); // Hint: we don't compress the polygon since we don't want to loose information - shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties (poly, layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::Polygon poly = m_parameters[i].to_user (); // Hint: we don't compress the polygon since we don't want to loose information - shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties(poly, layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PolygonWithProperties (poly, layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { db::complex_trans dbu_trans (1.0 / layout ()->dbu ()); - shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(dbu_trans * m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties (dbu_trans * m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); } else if (m_parameters[i].is_user ()) { - shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties(m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); + shapes (layout ()->guiding_shape_layer ()).insert (db::PathWithProperties (m_parameters[i].to_user (), layout ()->properties_repository ().properties_id (props))); } diff --git a/src/edt/edt/PointPropertiesPage.ui b/src/edt/edt/PointPropertiesPage.ui new file mode 100644 index 000000000..325d018b9 --- /dev/null +++ b/src/edt/edt/PointPropertiesPage.ui @@ -0,0 +1,282 @@ + + + PointPropertiesPage + + + + 0 + 0 + 531 + 370 + + + + Form + + + + 6 + + + 9 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 0 + + + + + + Sans Serif + 12 + false + true + false + false + + + + Point Properties + + + + + + + + 0 + 0 + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + Point position + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 6 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + x = + + + + + + + + 1 + 0 + + + + + + + + y = + + + + + + + + 1 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 478 + 10 + + + + + + + + Coordinates in database units + + + + + + + Absolute (accumulated) transformations + + + + + + + Qt::Vertical + + + + 478 + 16 + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 211 + 20 + + + + + + + + User Properties + + + + + + + Instantiation + + + + + + + + + + dbu_cb + abs_cb + prop_pb + inst_pb + + + + diff --git a/src/edt/edt/edt.pro b/src/edt/edt/edt.pro index 7680a9946..477e14ff4 100644 --- a/src/edt/edt/edt.pro +++ b/src/edt/edt/edt.pro @@ -92,3 +92,6 @@ LIBS += -L$$DESTDIR -lklayout_tl -lklayout_gsi -lklayout_laybasic -lklayout_layv } +FORMS += \ + PointPropertiesPage.ui + diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc index b1f4b2df5..6f9be9888 100644 --- a/src/edt/edt/edtMainService.cc +++ b/src/edt/edt/edtMainService.cc @@ -2537,6 +2537,7 @@ public: { mp_polygon_service = view->get_plugin (); mp_box_service = view->get_plugin (); + mp_point_service = view->get_plugin (); mp_text_service = view->get_plugin (); mp_path_service = view->get_plugin (); mp_inst_service = view->get_plugin (); @@ -2587,6 +2588,7 @@ public: private: edt::PolygonService *mp_polygon_service; edt::BoxService *mp_box_service; + edt::PointService *mp_point_service; edt::TextService *mp_text_service; edt::PathService *mp_path_service; edt::InstService *mp_inst_service; diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index 765c6d2a7..669bfe2f5 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -2795,6 +2795,9 @@ PartialService::partial_select (const db::DBox &box, lay::Editable::SelectionMod if (edt::boxes_enabled ()) { shape_flags |= db::ShapeIterator::Boxes; } + if (edt::points_enabled ()) { + shape_flags |= db::ShapeIterator::Points; + } if (edt::texts_enabled ()) { shape_flags |= db::ShapeIterator::Texts; } diff --git a/src/edt/edt/edtPlugin.cc b/src/edt/edt/edtPlugin.cc index 51eea026b..d9e374902 100644 --- a/src/edt/edt/edtPlugin.cc +++ b/src/edt/edt/edtPlugin.cc @@ -245,8 +245,12 @@ public: virtual bool implements_mouse_mode (std::string &title) const { - title = m_mouse_mode; - return true; + if (! m_mouse_mode.empty ()) { + title = m_mouse_mode; + return true; + } else { + return false; + } } private: @@ -282,6 +286,11 @@ static tl::RegisteredClass config_decl4 ( "edt::Service(Paths)" ); static tl::RegisteredClass config_decl5 ( + new edt::PluginDeclaration (tl::to_string (tr ("Points")), std::string (), 0, &get_shape_editor_options_pages), + 4014, + "edt::Service(Points)" +); +static tl::RegisteredClass config_decl6 ( new edt::PluginDeclaration (tl::to_string (tr ("Instances")), "instance:edit_mode\t" + tl::to_string (tr ("Instance")) + "\t<:instance_24px.png>" + tl::to_string (tr ("{Create a cell instance}")), &get_inst_options, &get_inst_editor_options_pages), 4020, "edt::Service(CellInstances)" @@ -302,6 +311,7 @@ bool is_enabled () bool polygons_enabled () { return is_enabled (); } bool paths_enabled () { return is_enabled (); } bool boxes_enabled () { return is_enabled (); } +bool points_enabled () { return is_enabled (); } bool texts_enabled () { return is_enabled (); } bool instances_enabled () { return is_enabled (); } diff --git a/src/edt/edt/edtPlugin.h b/src/edt/edt/edtPlugin.h index dc9bef133..a1fb66e63 100644 --- a/src/edt/edt/edtPlugin.h +++ b/src/edt/edt/edtPlugin.h @@ -54,6 +54,7 @@ namespace edt // other types ... bool paths_enabled (); bool boxes_enabled (); + bool points_enabled (); bool texts_enabled (); bool instances_enabled (); diff --git a/src/edt/edt/edtPropertiesPageUtils.cc b/src/edt/edt/edtPropertiesPageUtils.cc index 79363efe2..cd96f632a 100644 --- a/src/edt/edt/edtPropertiesPageUtils.cc +++ b/src/edt/edt/edtPropertiesPageUtils.cc @@ -197,6 +197,42 @@ db::Shape BoxDimensionsChangeApplicator::do_apply (db::Shapes &shapes, const db: } } +// ------------------------------------------------------------------------- +// PointDimensionsChangeApplicator implementation + +PointDimensionsChangeApplicator::PointDimensionsChangeApplicator (const db::Point &point, const db::Point &org_point) + : m_point (point), m_org_point (org_point) +{ + // .. nothing yet .. +} + +db::Shape PointDimensionsChangeApplicator::do_apply (db::Shapes &shapes, const db::Shape &shape, double /*dbu*/, bool relative) const +{ + db::Point org_point; + shape.point (org_point); + + db::Point new_point; + if (relative) { + new_point = org_point + (m_point - m_org_point); + } else if (m_point != m_org_point) { + new_point = org_point; + if (m_point.x () != m_org_point.x ()) { + new_point.set_x (m_point.x ()); + } + if (m_point.y () != m_org_point.y ()) { + new_point.set_y (m_point.y ()); + } + } + + if (new_point != org_point) { + // shape changed - replace the old by the new one + return shapes.replace (shape, new_point); + } else { + // shape did not change + return shape; + } +} + // ------------------------------------------------------------------------- // PolygonChangeApplicator implementation diff --git a/src/edt/edt/edtPropertiesPageUtils.h b/src/edt/edt/edtPropertiesPageUtils.h index 3c9dcc4f9..fb9550cdb 100644 --- a/src/edt/edt/edtPropertiesPageUtils.h +++ b/src/edt/edt/edtPropertiesPageUtils.h @@ -131,6 +131,22 @@ private: db::Coord m_l, m_b, m_r, m_t; }; +/** + * @brief A point change applicator + */ +class PointDimensionsChangeApplicator + : public ChangeApplicator +{ +public: + PointDimensionsChangeApplicator (const db::Point &point, const db::Point &org_point); + + bool supports_relative_mode () const { return true; } + db::Shape do_apply (db::Shapes &shapes, const db::Shape &shape, double dbu, bool relative) const; + +private: + db::Point m_point, m_org_point; +}; + /** * @brief A polygon change applicator */ diff --git a/src/edt/edt/edtPropertiesPages.cc b/src/edt/edt/edtPropertiesPages.cc index 74e7f0d2b..fb524c205 100644 --- a/src/edt/edt/edtPropertiesPages.cc +++ b/src/edt/edt/edtPropertiesPages.cc @@ -853,6 +853,124 @@ BoxPropertiesPage::changed () emit edited (); } +// ------------------------------------------------------------------------- +// PointPropertiesPage implementation + +PointPropertiesPage::PointPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent) + : ShapePropertiesPage (tl::to_string (tr ("Points")), service, manager, parent), + m_dbu (1.0) +{ + setupUi (this); + setup (); + + if (! readonly ()) { + + connect (x_le, SIGNAL (editingFinished ()), this, SLOT (changed ())); + connect (y_le, SIGNAL (editingFinished ()), this, SLOT (changed ())); + + } else { + + x_le->setReadOnly (true); + y_le->setReadOnly (true); + + } + + connect (inst_pb, SIGNAL (clicked ()), this, SLOT (show_inst ())); + connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ())); +} + +std::string +PointPropertiesPage::description (size_t entry) const +{ + const db::Shape &sh = shape (entry); + db::CplxTrans dbu_trans (dbu (entry)); + return ShapePropertiesPage::description (entry) + " - " + tl::sprintf (tl::to_string (tr ("Point%s")), (dbu_trans * sh.point ()).to_string ()); +} + +void +PointPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname) +{ + m_dbu = dbu; + + layer_lbl->setText (tl::to_qstring (lname)); + + db::Point point; + shape.point (point); + set_point (point); +} + +ChangeApplicator * +PointPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape &shape, double dbu) +{ + m_dbu = dbu; + + db::Point point = get_point (); + + db::Point org_point; + shape.point (org_point); + + if (point != org_point) { + return new PointDimensionsChangeApplicator (point, org_point); + } else { + return 0; + } +} + +db::Point +PointPropertiesPage::get_point () const +{ + bool has_error = false; + double x = 0.0, y = 0.0; + + try { + tl::from_string_ext (tl::to_string (x_le->text ()), x); + lay::indicate_error (x_le, (tl::Exception *) 0); + } catch (tl::Exception &ex) { + lay::indicate_error (x_le, &ex); + has_error = true; + } + + try { + tl::from_string_ext (tl::to_string (y_le->text ()), y); + lay::indicate_error (y_le, (tl::Exception *) 0); + } catch (tl::Exception &ex) { + lay::indicate_error (y_le, &ex); + has_error = true; + } + + if (has_error) { + throw tl::Exception (tl::to_string (tr ("Invalid values - see highlighted entry boxes"))); + } + + db::VCplxTrans t = db::VCplxTrans (trans ().inverted ()); + bool du = dbu_units (); + + return point_from_dpoint (db::DPoint (x, y), m_dbu, du, t); +} + +void +PointPropertiesPage::set_point (const db::Point &point) +{ + db::CplxTrans t = db::CplxTrans (trans ()); + db::DPoint pt = db::DPoint (t (point)); + + bool du = dbu_units (); + + x_le->setText (tl::to_qstring (coord_to_string (pt.x (), m_dbu, du))); + y_le->setText (tl::to_qstring (coord_to_string (pt.y (), m_dbu, du))); +} + +void +PointPropertiesPage::changed () +{ + try { + set_point (get_point ()); + } catch (...) { + } + + emit edited (); +} + // ------------------------------------------------------------------------- // TextPropertiesPage implementation diff --git a/src/edt/edt/edtPropertiesPages.h b/src/edt/edt/edtPropertiesPages.h index c95ce5432..534f44020 100644 --- a/src/edt/edt/edtPropertiesPages.h +++ b/src/edt/edt/edtPropertiesPages.h @@ -31,6 +31,7 @@ #include "edtService.h" #include "ui_PolygonPropertiesPage.h" #include "ui_BoxPropertiesPage.h" +#include "ui_PointPropertiesPage.h" #include "ui_PathPropertiesPage.h" #include "ui_EditablePathPropertiesPage.h" #include "ui_TextPropertiesPage.h" @@ -152,6 +153,34 @@ private: void set_box (const db::Box &box); }; +class PointPropertiesPage + : public ShapePropertiesPage, + public Ui::PointPropertiesPage +{ +Q_OBJECT + +public: + PointPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent); + + virtual std::string description (size_t entry) const; + virtual std::string description () const { return ShapePropertiesPage::description (); } + virtual void do_update (const db::Shape &shape, double dbu, const std::string &lname); + virtual ChangeApplicator *create_applicator (db::Shapes &shapes, const db::Shape &shape, double dbu); + +public slots: + void changed (); + +protected: + virtual QCheckBox *dbu_checkbox () const { return dbu_cb; } + virtual QCheckBox *abs_checkbox () const { return abs_cb; } + +private: + double m_dbu; + + db::Point get_point () const; + void set_point (const db::Point &point); +}; + class TextPropertiesPage : public ShapePropertiesPage, public Ui::TextPropertiesPage diff --git a/src/edt/edt/edtServiceImpl.cc b/src/edt/edt/edtServiceImpl.cc index a219d38bb..642605718 100644 --- a/src/edt/edt/edtServiceImpl.cc +++ b/src/edt/edt/edtServiceImpl.cc @@ -386,6 +386,20 @@ ShapeEditService::deliver_shape (const db::Box &box) } } +void +ShapeEditService::deliver_shape (const db::Point &point) +{ + if (m_combine_mode == CM_Add) { + if (manager ()) { + manager ()->transaction (tl::to_string (tr ("Create point"))); + } + cell ().shapes (layer ()).insert (point); + if (manager ()) { + manager ()->commit (); + } + } +} + // ----------------------------------------------------------------------------- // PolygonService implementation @@ -816,6 +830,103 @@ BoxService::selection_applies (const lay::ObjectInstPath &sel) const return !sel.is_cell_inst () && sel.shape ().is_box (); } +// ----------------------------------------------------------------------------- +// PointService implementation + +PointService::PointService (db::Manager *manager, lay::LayoutViewBase *view) + : ShapeEditService (manager, view, db::ShapeIterator::Points) +{ + // .. nothing yet .. +} + +#if defined(HAVE_QT) +std::vector +PointService::properties_pages (db::Manager *manager, QWidget *parent) +{ + std::vector pages; + pages.push_back (new edt::PointPropertiesPage (this, manager, parent)); + return pages; +} +#endif + +void +PointService::do_begin_edit (const db::DPoint &p) +{ + get_edit_layer (); + + db::DPoint pp = snap2 (p); + m_p = pp; + + set_edit_marker (new lay::Marker (view (), cv_index ())); + update_marker (); +} + +db::Point +PointService::get_point () const +{ + return db::Point (trans () * m_p); +} + +void +PointService::update_marker () +{ + lay::Marker *marker = dynamic_cast (edit_marker ()); + if (marker) { + + db::Point pt = get_point (); + marker->set (db::Box (pt, pt), db::VCplxTrans (1.0 / layout ().dbu ()) * trans ().inverted ()); + + view ()->message (std::string ("x: ") + + tl::micron_to_string (m_p.x ()) + + std::string (" y: ") + + tl::micron_to_string (m_p.y ())); + + } +} + +void +PointService::do_mouse_move_inactive (const db::DPoint &p) +{ + lay::PointSnapToObjectResult snap_details = snap2_details (p); + mouse_cursor_from_snap_details (snap_details); +} + +void +PointService::do_mouse_move (const db::DPoint &p) +{ + do_mouse_move_inactive (p); + + set_cursor (lay::Cursor::cross); + m_p = snap2 (p); + update_marker (); +} + +bool +PointService::do_mouse_click (const db::DPoint &p) +{ + do_mouse_move (p); + return true; +} + +void +PointService::do_finish_edit () +{ + deliver_shape (get_point ()); + commit_recent (view ()); +} + +void +PointService::do_cancel_edit () +{ + // .. nothing yet .. +} + +bool +PointService::selection_applies (const lay::ObjectInstPath &sel) const +{ + return !sel.is_cell_inst () && sel.shape ().is_point (); +} + // ----------------------------------------------------------------------------- // TextService implementation diff --git a/src/edt/edt/edtServiceImpl.h b/src/edt/edt/edtServiceImpl.h index ecb9e4200..8fe8399b7 100644 --- a/src/edt/edt/edtServiceImpl.h +++ b/src/edt/edt/edtServiceImpl.h @@ -67,6 +67,7 @@ protected: void deliver_shape (const db::Polygon &poly); void deliver_shape (const db::Path &path); void deliver_shape (const db::Box &box); + void deliver_shape (const db::Point &point); virtual void current_layer_changed () { } private: @@ -140,6 +141,33 @@ private: db::Box get_box () const; }; +/** + * @brief Implementation of edt::Service for point editing + */ +class PointService + : public ShapeEditService +{ +public: + PointService (db::Manager *manager, lay::LayoutViewBase *view); + +#if defined(HAVE_QT) + virtual std::vector properties_pages (db::Manager *manager, QWidget *parent); +#endif + virtual void do_begin_edit (const db::DPoint &p); + virtual void do_mouse_move (const db::DPoint &p); + virtual void do_mouse_move_inactive (const db::DPoint &p); + virtual bool do_mouse_click (const db::DPoint &p); + virtual void do_finish_edit (); + virtual void do_cancel_edit (); + virtual bool selection_applies (const lay::ObjectInstPath &sel) const; + +private: + db::DPoint m_p; + + void update_marker (); + db::Point get_point () const; +}; + /** * @brief Implementation of edt::Service for text editing */ diff --git a/src/edt/edt/edtUtils.cc b/src/edt/edt/edtUtils.cc index 72375fee9..f8259ffef 100644 --- a/src/edt/edt/edtUtils.cc +++ b/src/edt/edt/edtUtils.cc @@ -260,19 +260,19 @@ get_parameters_from_pcell_and_guiding_shapes (db::Layout *layout, db::cell_index std::map ::const_iterator pnm = pname_map.find (pv->second.to_string ()); if (pnm != pname_map.end ()) { + db::CplxTrans dbu_trans (layout->dbu ()); + if (sh->is_box ()) { - if (sh->box ().width () == 0 && sh->box ().height () == 0) { - parameters_for_pcell [pnm->second] = tl::Variant (sh->box ().lower_left () * layout->dbu ()); - } else { - parameters_for_pcell [pnm->second] = tl::Variant (sh->box () * layout->dbu ()); - } + parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->box ()); } else if (sh->is_edge ()) { - parameters_for_pcell [pnm->second] = tl::Variant (sh->edge () * layout->dbu ()); + parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->edge ()); + } else if (sh->is_point ()) { + parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->point ()); } else if (sh->is_polygon ()) { // Hint: we don't compress since we don't want to loose information - parameters_for_pcell [pnm->second] = tl::Variant (sh->polygon ().transformed (db::CplxTrans (layout->dbu ()), false)); + parameters_for_pcell [pnm->second] = tl::Variant (sh->polygon ().transformed (dbu_trans, false)); } else if (sh->is_path ()) { - parameters_for_pcell [pnm->second] = tl::Variant (db::CplxTrans (layout->dbu ()) * sh->path ()); + parameters_for_pcell [pnm->second] = tl::Variant (dbu_trans * sh->path ()); } } @@ -315,7 +315,7 @@ get_parameters_from_pcell_and_guiding_shapes (db::Layout *layout, db::cell_index } else if (org_parameters[i].is_user ()) { db::DPoint p = org_parameters[i].to_user (); - guiding_shapes.insert (db::BoxWithProperties(db::Box (db::DBox (p, p) * (1.0 / layout->dbu ())), layout->properties_repository ().properties_id (props))); + guiding_shapes.insert (db::PointWithProperties(db::Point (p * (1.0 / layout->dbu ())), layout->properties_repository ().properties_id (props))); } else if (org_parameters[i].is_user ()) { diff --git a/src/laybasic/laybasic/layBitmapRenderer.cc b/src/laybasic/laybasic/layBitmapRenderer.cc index c218cc6bc..e5d67ccb6 100644 --- a/src/laybasic/laybasic/layBitmapRenderer.cc +++ b/src/laybasic/laybasic/layBitmapRenderer.cc @@ -427,7 +427,7 @@ BitmapRenderer::draw (const db::Shape &shape, const db::CplxTrans &trans, db::Box bbox = shape.bbox (); double threshold = 1.0 / trans.mag (); - if (bbox.width () <= threshold && bbox.height () <= threshold) { + if (bbox.width () <= threshold && bbox.height () <= threshold && !shape.is_point ()) { db::DPoint dc = trans * bbox.center (); if (fill && ! shape.is_edge ()) { @@ -440,7 +440,7 @@ BitmapRenderer::draw (const db::Shape &shape, const db::CplxTrans &trans, render_dot (dc.x (), dc.y (), vertices); } - } else if (shape.is_box ()) { + } else if (shape.is_box () || shape.is_point ()) { draw (bbox, trans, fill, frame, vertices, text); diff --git a/src/laybasic/laybasic/layRedrawThreadWorker.cc b/src/laybasic/laybasic/layRedrawThreadWorker.cc index 6cf2c9e4f..8e868a5bc 100644 --- a/src/laybasic/laybasic/layRedrawThreadWorker.cc +++ b/src/laybasic/laybasic/layRedrawThreadWorker.cc @@ -1059,7 +1059,7 @@ RedrawThreadWorker::any_shapes (db::cell_index_type cell_index, unsigned int lev int ret = false; const db::Cell &cell = mp_layout->cell (cell_index); - if (! cell.shapes (m_layer).begin (db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Boxes, mp_prop_sel, m_inv_prop_sel).at_end ()) { + if (! cell.shapes (m_layer).begin (db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Boxes | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel).at_end ()) { ret = true; } else if (levels > 1) { for (db::Cell::child_cell_iterator cc = cell.begin_child_cells (); !cc.at_end () && !ret; ++cc) { @@ -1624,7 +1624,7 @@ RedrawThreadWorker::draw_layer_wo_cache (int from_level, int to_level, db::cell_ size_t current_quad_id = 0; size_t current_array_quad_id = 0; - db::ShapeIterator shape (shapes.begin_touching (*v, db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths, mp_prop_sel, m_inv_prop_sel)); + db::ShapeIterator shape (shapes.begin_touching (*v, db::ShapeIterator::Boxes | db::ShapeIterator::Polygons | db::ShapeIterator::Edges | db::ShapeIterator::Paths | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel)); while (! shape.at_end ()) { test_snapshot (update_snapshot); diff --git a/src/laybasic/laybasic/layRenderer.cc b/src/laybasic/laybasic/layRenderer.cc index aecdc4a37..8ad78895d 100644 --- a/src/laybasic/laybasic/layRenderer.cc +++ b/src/laybasic/laybasic/layRenderer.cc @@ -65,6 +65,8 @@ Renderer::draw_propstring (const db::Shape &shape, const db::PropertiesRepositor dp = trans * (db::Point () + shape.text_trans ().disp ()); } else if (shape.is_box ()) { dp = trans (shape.box ().p1 ()); + } else if (shape.is_point ()) { + dp = trans (shape.point ()); } else if (shape.is_polygon ()) { db::Shape::polygon_edge_iterator e = shape.begin_edge (); dp = trans ((*e).p1 ()); From e53d432117c66090a844bfc7e5955aa854f3873d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 29 Jul 2023 01:01:50 +0200 Subject: [PATCH 07/22] Better support for point-like handles PCells have been featuring point-like handles but they suffered some issues because they have been mapped to degenerated boxes: - hardly visible - could be destroyed using partial editing Now, the database offers points, hence it is possible to store points explicitly, so no tricks need to be played to make them visible. Editing has been implemented to some extent, so it is possible for example to configure handles in the properties dialogs. --- src/edt/edt/edtPartialService.cc | 42 +++++++++++++++++++++++++++++- src/edt/edt/edtService.cc | 25 ++++++++++++++++-- src/laybasic/laybasic/layFinder.cc | 2 +- src/laybasic/laybasic/laySnap.cc | 8 +++++- 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/edt/edt/edtPartialService.cc b/src/edt/edt/edtPartialService.cc index 669bfe2f5..0d9fd63b7 100644 --- a/src/edt/edt/edtPartialService.cc +++ b/src/edt/edt/edtPartialService.cc @@ -849,6 +849,14 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co } + } else if (shape->is_point ()) { + + db::Point tp (shape->point ()); + + if (hit_box.contains (tp)) { + edges.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0)); + } + } else if (shape->is_text ()) { db::Point tp (shape->text_trans () * db::Point ()); @@ -1000,6 +1008,17 @@ PartialShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, co } + } else if (shape->is_point ()) { + + db::Point tp (shape->point ()); + + if (hit_box.contains (tp)) { + d = tp.distance (hit_box.center ()); + edge_sel.clear (); + edge_sel.push_back (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0)); + match = true; + } + } else if (shape->is_text ()) { db::Point tp (shape->text_trans () * db::Point ()); @@ -1258,6 +1277,11 @@ PartialService::timeout () db::Point tp (r->first.shape ().text_trans () * db::Point ()); enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, true); + } else if (r->first.shape ().is_point ()) { + + db::Point tp (r->first.shape ().point ()); + enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, true); + } } @@ -1479,6 +1503,17 @@ PartialService::transform_selection (const db::DTrans &move_trans) shape = shapes.replace (shape, t); } + } else if (shape.is_point ()) { + + db::Point p; + shape.point (p); + + std::map ::const_iterator np = new_points.find (PointWithIndex (p, 0, 0)); + + if (np != new_points.end ()) { + shape = shapes.replace (shape, np->second); + } + } // transform the selection @@ -2204,7 +2239,7 @@ PartialService::del () shapes_to_delete_by_cell.insert (std::make_pair (std::make_pair (r->first.cell_index (), std::make_pair (r->first.cv_index (), r->first.layer ())), std::vector ())).first->second.push_back (r); } - } else if (shape.is_text ()) { + } else if (shape.is_text () || shape.is_point ()) { shapes_to_delete_by_cell.insert (std::make_pair (std::make_pair (r->first.cell_index (), std::make_pair (r->first.cv_index (), r->first.layer ())), std::vector ())).first->second.push_back (r); @@ -2684,6 +2719,11 @@ PartialService::do_selection_to_view () db::Point tp (r->first.shape ().text_trans () * db::Point ()); enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, false); + } else if (r->first.shape ().is_point ()) { + + db::Point tp (r->first.shape ().point ()); + enter_edge (EdgeWithIndex (db::Edge (tp, tp), 0, 0, 0), n_marker, r, new_points, new_edges, gt, *tv_list, false); + } } diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index aefcf86dd..8afdf95e3 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -1108,7 +1108,20 @@ Service::transient_select (const db::DPoint &pos) lay::ShapeMarker *marker = new lay::ShapeMarker (view (), r->cv_index ()); marker->set (r->shape (), gt, mp_view->cv_transform_variants (r->cv_index (), r->layer ())); - marker->set_vertex_size (0); + + bool is_point = false; + if (r->shape ().is_edge () || r->shape ().is_box ()) { + is_point = r->shape ().bbox ().is_point (); + } else if (r->shape ().is_point ()) { + is_point = true; + } + + if (is_point) { + marker->set_vertex_shape (lay::ViewOp::Cross); + marker->set_vertex_size (9 /*cross vertex size*/); + } else { + marker->set_vertex_size (0); + } marker->set_line_width (1); marker->set_halo (0); @@ -1602,7 +1615,15 @@ Service::do_selection_to_view () } marker->set (r->shape (), gt, *tv_list); - if (r->shape ().is_text ()) { + + bool is_point = false; + if (r->shape ().is_text () || r->shape ().is_point ()) { + is_point = true; + } else if (r->shape ().is_edge () || r->shape ().is_box ()) { + is_point = r->shape ().bbox ().is_point (); + } + + if (is_point) { // show the origins as crosses for texts marker->set_vertex_shape (lay::ViewOp::Cross); marker->set_vertex_size (9 /*cross vertex size*/); diff --git a/src/laybasic/laybasic/layFinder.cc b/src/laybasic/laybasic/layFinder.cc index df2cdcc36..d227d7ae6 100644 --- a/src/laybasic/laybasic/layFinder.cc +++ b/src/laybasic/laybasic/layFinder.cc @@ -606,7 +606,7 @@ ShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, const db: match = true; } - } else if (shape->is_box () || shape->is_text ()) { + } else if (shape->is_box () || shape->is_point () || shape->is_text ()) { db::Box box = shape->bbox (); if (text_info () && shape->is_text ()) { diff --git a/src/laybasic/laybasic/laySnap.cc b/src/laybasic/laybasic/laySnap.cc index 4606eb868..b6d268b32 100644 --- a/src/laybasic/laybasic/laySnap.cc +++ b/src/laybasic/laybasic/laySnap.cc @@ -598,7 +598,7 @@ private: const db::Shapes &shapes = cell.shapes (l); - db::ShapeIterator shape = shapes.begin_touching (touch_box, db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes, mp_prop_sel, m_inv_prop_sel); + db::ShapeIterator shape = shapes.begin_touching (touch_box, db::ShapeIterator::Polygons | db::ShapeIterator::Paths | db::ShapeIterator::Boxes | db::ShapeIterator::Points, mp_prop_sel, m_inv_prop_sel); while (! shape.at_end () && m_tests > 0) { --m_tests; @@ -653,6 +653,12 @@ private: test_edge (t * db::Edge (box.p2 (), db::Point (box.right (), box.bottom ()))); test_edge (t * db::Edge (db::Point (box.right (), box.bottom ()), box.p1 ())); + } else if (shape->is_point ()) { + + const db::Point &p = shape->point (); + + test_edge (t * db::Edge (p, p)); + } ++shape; From ad114f6137ed989e2994ed89cd82e13202fba117 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 29 Jul 2023 01:13:25 +0200 Subject: [PATCH 08/22] Fixed unit tests (error messages now have the message class attached) --- src/pya/unit_tests/pyaTests.cc | 4 ++-- src/rba/unit_tests/rbaTests.cc | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pya/unit_tests/pyaTests.cc b/src/pya/unit_tests/pyaTests.cc index c10a6d817..4e907c18f 100644 --- a/src/pya/unit_tests/pyaTests.cc +++ b/src/pya/unit_tests/pyaTests.cc @@ -45,7 +45,7 @@ TEST (basic) try { pya::PythonInterpreter::instance ()->eval_string ("raise Exception(\"an error\")"); } catch (tl::ScriptError &ex) { - EXPECT_EQ (ex.basic_msg (), std::string ("an error")); + EXPECT_EQ (ex.basic_msg (), std::string ("Exception: an error")); EXPECT_EQ (ex.cls () == std::string ("exceptions.Exception") || ex.cls () == std::string ("Exception"), true); err = true; } @@ -56,7 +56,7 @@ TEST (basic) try { pya::PythonInterpreter::instance ()->eval_string ("Quatsch"); } catch (tl::ScriptError &ex) { - EXPECT_EQ (ex.basic_msg (), std::string ("name 'Quatsch' is not defined")); + EXPECT_EQ (ex.basic_msg (), std::string ("NameError: name 'Quatsch' is not defined")); EXPECT_EQ (ex.cls () == std::string ("exceptions.NameError") || ex.cls () == std::string ("NameError"), true); err = true; } diff --git a/src/rba/unit_tests/rbaTests.cc b/src/rba/unit_tests/rbaTests.cc index 3051abe23..7bea46066 100644 --- a/src/rba/unit_tests/rbaTests.cc +++ b/src/rba/unit_tests/rbaTests.cc @@ -45,7 +45,7 @@ TEST (basic) try { rba::RubyInterpreter::instance ()->eval_string ("raise \"an error\""); } catch (tl::Exception &ex) { - EXPECT_EQ (std::string (ex.msg (), 0, 8), std::string ("an error")); + EXPECT_EQ (std::string (ex.msg (), 0, 22), std::string ("RuntimeError: an error")); err = true; } @@ -56,8 +56,8 @@ TEST (basic) try { rba::RubyInterpreter::instance ()->eval_string ("Quatsch"); } catch (tl::Exception &ex) { - EXPECT_EQ (std::string (ex.msg (), 0, 30) == std::string ("uninitialized constant Quatsch") || - std::string (ex.msg (), 0, 38) == std::string ("uninitialized constant Object::Quatsch"), + EXPECT_EQ (std::string (ex.msg (), 0, 41) == std::string ("NameError: uninitialized constant Quatsch") || + std::string (ex.msg (), 0, 49) == std::string ("NameError: uninitialized constant Object::Quatsch"), true); err = true; } From 2ae01a3e91931a939dea24d968b4be6c7d41b9db Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 30 Jul 2023 13:50:49 +0200 Subject: [PATCH 09/22] Do not duplicate cells+layers on "Duplicate" See https://www.klayout.de/forum/discussion/2335 for the rationale --- src/laybasic/laybasic/layLayoutViewBase.cc | 12 +++++++----- src/laybasic/laybasic/layLayoutViewBase.h | 7 +++++++ src/layui/layui/layLayoutViewFunctions.cc | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index fb4ffd020..7823967e3 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -5297,11 +5297,7 @@ LayoutViewBase::paste_interactive () std::unique_ptr trans (new db::Transaction (manager (), tl::to_string (tr ("Paste and move")))); - { - // let the receivers sort out who is pasting what .. - do_paste (); - lay::Editables::paste (); - } + lay::Editables::paste (); // temporarily close the transaction and pass to the move service for appending it's own // operations. @@ -5314,6 +5310,12 @@ LayoutViewBase::paste_interactive () void LayoutViewBase::copy () +{ + copy_view_objects (); +} + +void +LayoutViewBase::copy_view_objects () { cancel_edits (); if (! lay::Editables::has_selection ()) { diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index f22e4cc34..eb6370bab 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -264,6 +264,13 @@ public: */ virtual void copy (); + /** + * @brief Copies to clipboard (view objects only) + * + * This version does not look for copy sources in the tree views. + */ + void copy_view_objects (); + /** * @brief Cuts to clipboard * diff --git a/src/layui/layui/layLayoutViewFunctions.cc b/src/layui/layui/layLayoutViewFunctions.cc index 36bc3d6ad..157b978ba 100644 --- a/src/layui/layui/layLayoutViewFunctions.cc +++ b/src/layui/layui/layLayoutViewFunctions.cc @@ -1177,7 +1177,7 @@ LayoutViewFunctions::do_cm_duplicate (bool interactive) db::Clipboard::instance ().swap (saved_clipboard); try { - view ()->copy (); + view ()->copy_view_objects (); view ()->clear_selection (); view ()->cancel (); if (interactive) { From 3736b591566e86f258aaeff931e219c1a9a87dad Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 30 Jul 2023 14:46:58 +0200 Subject: [PATCH 10/22] it's -> its --- src/buddies/src/bd/bdWriterOptions.cc | 4 ++-- src/db/db/dbHierarchyBuilder.cc | 2 +- src/db/db/dbLayout.cc | 14 +++++++------- src/db/db/dbPath.cc | 4 ++-- src/db/db/dbPolygon.cc | 4 ++-- src/db/db/dbVariableWidthPath.cc | 4 ++-- src/db/db/gsiDeclDbCell.cc | 10 +++++----- src/db/db/gsiDeclDbCellMapping.cc | 2 +- src/db/db/gsiDeclDbCompoundOperation.cc | 2 +- src/db/db/gsiDeclDbLayout.cc | 8 ++++---- src/db/db/gsiDeclDbLayoutToNetlist.cc | 8 ++++---- src/db/db/gsiDeclDbNetlist.cc | 4 ++-- src/db/db/gsiDeclDbNetlistCompare.cc | 2 +- src/db/db/gsiDeclDbNetlistDeviceExtractor.cc | 4 ++-- src/db/db/gsiDeclDbPolygon.cc | 4 ++-- src/db/db/gsiDeclDbTechnologies.cc | 2 +- src/db/db/gsiDeclDbTilingProcessor.cc | 2 +- src/db/db/gsiDeclDbTrans.cc | 2 +- src/db/db/gsiDeclDbUtils.cc | 2 +- src/db/unit_tests/dbNetlistCompareTests.cc | 4 ++-- .../drc/built-in-macros/_drc_cop_integration.rb | 4 ++-- src/drc/drc/built-in-macros/_drc_layer.rb | 4 ++-- src/gsi/gsi/gsiExpression.cc | 4 ++-- src/gsi/gsi/gsiIterators.h | 2 +- src/gsiqt/qtbasic/gsiQtHelper.cc | 4 ++-- src/lay/lay/built_in_macros/qobject_helper.lym | 2 +- src/lay/lay/layMainWindow.cc | 4 ++-- src/lay/lay/laySaltController.cc | 4 ++-- src/lay/lay/laySaltGrainPropertiesDialog.cc | 2 +- src/lay/lay/macro_templates/pcell.lym | 2 +- src/lay/lay/macro_templates/pcell_python.lym | 2 +- .../salt_templates/pcell_lib/macros/pcell.lym | 2 +- src/laybasic/laybasic/gsiDeclLayLayers.cc | 4 ++-- .../laybasic/gsiDeclLayLayoutViewBase.cc | 12 ++++++------ src/laybasic/laybasic/gsiDeclLayPlugin.cc | 4 ++-- src/laybasic/laybasic/gtf.cc | 2 +- src/laybasic/laybasic/layAbstractMenu.cc | 2 +- src/laybasic/laybasic/layBitmapRenderer.cc | 2 +- src/layui/layui/NetExportDialog.ui | 2 +- src/layui/layui/gsiDeclLayDialogs.cc | 16 ++++++++-------- src/layui/layui/layHierarchyControlPanel.cc | 2 +- src/layui/layui/layLayoutViewFunctions.cc | 6 +++--- src/layview/layview/layLayoutView_qt.cc | 2 +- .../streamers/dxf/db_plugin/gsiDeclDbDXF.cc | 4 ++-- .../dxf/lay_plugin/DXFReaderOptionPage.ui | 2 +- src/rdb/rdb/gsiDeclRdb.cc | 6 +++--- 46 files changed, 95 insertions(+), 95 deletions(-) diff --git a/src/buddies/src/bd/bdWriterOptions.cc b/src/buddies/src/bd/bdWriterOptions.cc index 07fa96f92..93c559a86 100644 --- a/src/buddies/src/bd/bdWriterOptions.cc +++ b/src/buddies/src/bd/bdWriterOptions.cc @@ -136,11 +136,11 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin "\n" "Multiple operations can be specified by combining them with a comma. " "Positive and negative selection happens in the order given. Hence it's possible " - "to select a cell with it's children and then unselect some children of this cell.\n" + "to select a cell with its children and then unselect some children of this cell.\n" "\n" "Examples:\n\n" "* \"TOP1,TOP2\" - Select cells TOP1 and TOP2 with all of their children\n" - "* \"(TOP)\" - Select only cell TOP, but none of it's child cells\n" + "* \"(TOP)\" - Select only cell TOP, but none of its child cells\n" "* \"TOP,-A\" - Select cell TOP (plus children), then remove A (with children)" ); diff --git a/src/db/db/dbHierarchyBuilder.cc b/src/db/db/dbHierarchyBuilder.cc index d8698a83e..c83e5acc4 100644 --- a/src/db/db/dbHierarchyBuilder.cc +++ b/src/db/db/dbHierarchyBuilder.cc @@ -191,7 +191,7 @@ HierarchyBuilder::reset () void HierarchyBuilder::register_variant (db::cell_index_type non_var, db::cell_index_type var) { - // non_var (despite it's name) may be a variant created previously. + // non_var (despite its name) may be a variant created previously. variant_to_original_target_map_type::const_iterator v = m_variants_to_original_target_map.find (non_var); if (v != m_variants_to_original_target_map.end ()) { non_var = v->second; diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index 46f3bae47..1790caadc 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -1358,7 +1358,7 @@ Layout::add_cell (const char *name) m_cells.push_back_ptr (new_cell); m_cell_ptrs [new_index] = new_cell; - // enter it's index and cell_name + // enter its index and cell_name register_cell_name (name, new_index); if (manager () && manager ()->transacting ()) { @@ -1380,7 +1380,7 @@ Layout::add_anonymous_cell () m_cells.push_back_ptr (new_cell); m_cell_ptrs [new_index] = new_cell; - // enter it's index and cell_name + // enter its index and cell_name register_cell_name (0, new_index); if (manager () && manager ()->transacting ()) { @@ -1393,7 +1393,7 @@ Layout::add_anonymous_cell () void Layout::register_cell_name (const char *name, cell_index_type ci) { - // enter it's index and cell_name + // enter its index and cell_name char *cp; if (name == 0) { @@ -2254,7 +2254,7 @@ Layout::get_pcell_variant_dict (pcell_id_type pcell_id, const std::maptransacting ()) { @@ -2293,7 +2293,7 @@ Layout::get_pcell_variant (pcell_id_type pcell_id, const std::vectortransacting ()) { @@ -2932,7 +2932,7 @@ Layout::get_lib_proxy (Library *lib, cell_index_type cell_index) m_cells.push_back_ptr (proxy); m_cell_ptrs [new_index] = proxy; - // enter it's index and cell_name + // enter its index and cell_name register_cell_name (b.c_str (), new_index); if (manager () && manager ()->transacting ()) { @@ -2968,7 +2968,7 @@ Layout::create_cold_proxy (const db::LayoutOrCellContextInfo &info) m_cells.push_back_ptr (proxy); m_cell_ptrs [new_index] = proxy; - // enter it's index and cell_name + // enter its index and cell_name register_cell_name (b.c_str (), new_index); if (manager () && manager ()->transacting ()) { diff --git a/src/db/db/dbPath.cc b/src/db/db/dbPath.cc index d41509af1..f1d5be16e 100644 --- a/src/db/db/dbPath.cc +++ b/src/db/db/dbPath.cc @@ -277,7 +277,7 @@ void path::create_shifted_points (C start, C end, C width, bool forward, Iter Iter ppp = pp; ++ppp; - // Compute the unit vector of the line and it's normal (times width) + // Compute the unit vector of the line and its normal (times width) db::DVector ed (*pp - *p); ed *= 1.0 / ed.double_length (); @@ -383,7 +383,7 @@ void path::create_shifted_points (C start, C end, C width, bool forward, Iter // Segments are too short - the won't intersect: In this case we create a loop of three // points which define the area in self-overlapping way but confined to the path within - // the limits of it's width. + // the limits of its width. // HINT: the execution of this code is a pretty strong evidence for the existence to loops // in the contour delivered. A proof however is missing .. *pts++ = *pp + vector (nd); diff --git a/src/db/db/dbPolygon.cc b/src/db/db/dbPolygon.cc index 070024fa8..e1b8edbc8 100644 --- a/src/db/db/dbPolygon.cc +++ b/src/db/db/dbPolygon.cc @@ -32,7 +32,7 @@ db::DEdge compute_shifted (const db::edge &e, C dx, C dy, double ext, int nsi { tl_assert (! e.is_degenerate ()); // no coincident points allowed - // Compute the unit vector of the line and it's normal (times width) + // Compute the unit vector of the line and its normal (times width) db::DVector ec (e.d ()); ec *= 1.0 / ec.double_length (); db::DVector nc (-ec.y (), ec.x ()); @@ -47,7 +47,7 @@ db::DEdge compute_shifted (const db::edge &e, C dx, C dy, double ext, int nsi /** * @brief Smart multiplication of a vector with a distance - * This function tries to keep the length of the vector on grid if it's + * This function tries to keep the length of the vector on grid if its * a 45 degree or horizontal/vertical one. */ template diff --git a/src/db/db/dbVariableWidthPath.cc b/src/db/db/dbVariableWidthPath.cc index d017546bc..6910e05d2 100644 --- a/src/db/db/dbVariableWidthPath.cc +++ b/src/db/db/dbVariableWidthPath.cc @@ -151,7 +151,7 @@ void create_shifted_points (C /*c*/, bool forward, Iter from, Iter to, WIter wfr WIter www = ww; ++www; - // Compute the unit vector of the line and it's normal (times width) + // Compute the unit vector of the line and its normal (times width) db::DVector ed (*pp - *p); ed *= 1.0 / ed.double_length (); @@ -258,7 +258,7 @@ void create_shifted_points (C /*c*/, bool forward, Iter from, Iter to, WIter wfr // Segments are too short - the won't intersect: In this case we create a loop of three // points which define the area in self-overlapping way but confined to the path within - // the limits of it's width. + // the limits of its width. // HINT: the execution of this code is a pretty strong evidence for the existence to loops // in the contour delivered. A proof however is missing .. *pts++ = *pp + vector (nd2); diff --git a/src/db/db/gsiDeclDbCell.cc b/src/db/db/gsiDeclDbCell.cc index 9fc3c76a2..861020f98 100644 --- a/src/db/db/gsiDeclDbCell.cc +++ b/src/db/db/gsiDeclDbCell.cc @@ -1875,14 +1875,14 @@ Class decl_Cell ("db", "Cell", gsi::method_ext ("write", &write_simple, gsi::arg ("file_name"), "@brief Writes the cell to a layout file\n" "The format of the file will be determined from the file name. Only the cell and " - "it's subtree below will be saved.\n" + "its subtree below will be saved.\n" "\n" "This method has been introduced in version 0.23.\n" ) + gsi::method_ext ("write", &write_options, gsi::arg ("file_name"), gsi::arg ("options"), "@brief Writes the cell to a layout file\n" "The format of the file will be determined from the file name. Only the cell and " - "it's subtree below will be saved.\n" + "its subtree below will be saved.\n" "In contrast to the other 'write' method, this version allows one to specify save options, i.e. " "scaling etc.\n" "\n" @@ -2576,7 +2576,7 @@ Class decl_Cell ("db", "Cell", "\n" "In contrast to the \\transform method, this method allows propagation of the transformation into child cells. " "More precisely: it applies just a part of the given transformation to the instance, such that when transforming " - "the cell instantiated and it's shapes with the same transformation, the result will reflect the desired transformation. Mathematically spoken, the " + "the cell instantiated and its shapes with the same transformation, the result will reflect the desired transformation. Mathematically spoken, the " "transformation of the instance (A) is transformed with the given transformation T using \"A' = T * A * Tinv\" where " "Tinv is the inverse of T. In effect, the transformation T commutes with the new instance transformation A' and can be " "applied to child cells as well. This method is therefore useful to transform a hierarchy of cells.\n" @@ -3221,7 +3221,7 @@ Class decl_Cell ("db", "Cell", "\n" "The parameters are given in the order the parameters are declared. Use \\pcell_declaration " "on the instance to get the PCell declaration object of the cell. That PCellDeclaration object " - "delivers the parameter declaration with it's 'get_parameters' method.\n" + "delivers the parameter declaration with its 'get_parameters' method.\n" "Each parameter in the variant list passed to the second list of values corresponds to " "one parameter declaration.\n" "\n" @@ -4013,7 +4013,7 @@ Class decl_Instance ("db", "Instance", "@param layer_index The index of the layer the bounding box will be computed for.\n" "The bounding box incorporates all instances that the array represents. " "It gives the overall extension of the child cell as seen in the calling cell (or all array members if the instance forms an array) " - "for the given layer. If the layer is empty in this cell and all it's children', an empty bounding box will be returned. " + "for the given layer. If the layer is empty in this cell and all its children', an empty bounding box will be returned. " "\n" "This method has been introduced in version 0.25. 'bbox' is the preferred synonym for it since version 0.28." ) + diff --git a/src/db/db/gsiDeclDbCellMapping.cc b/src/db/db/gsiDeclDbCellMapping.cc index 62e19f1a3..a35e6ae55 100644 --- a/src/db/db/gsiDeclDbCellMapping.cc +++ b/src/db/db/gsiDeclDbCellMapping.cc @@ -132,7 +132,7 @@ Class decl_CellMapping ("db", "CellMapping", "If used as a pseudo-target for the cell mapping, this index indicates " "that the cell shall be dropped rather than created on the target side " "or skipped by flattening. Instead, all shapes of this cell are discarded " - "and it's children are not translated unless explicitly requested or " + "and its children are not translated unless explicitly requested or " "if required are children for other cells.\n" "\n" "This constant has been introduced in version 0.25." diff --git a/src/db/db/gsiDeclDbCompoundOperation.cc b/src/db/db/gsiDeclDbCompoundOperation.cc index 1abfd4515..9271ba64f 100644 --- a/src/db/db/gsiDeclDbCompoundOperation.cc +++ b/src/db/db/gsiDeclDbCompoundOperation.cc @@ -727,7 +727,7 @@ Class decl_CompoundRegionOperationNode ("db", " "If 'is_square' is true, only squares will be selected. If 'inverse' is true, the non-rectangle/non-square shapes are returned.\n" ) + gsi::constructor ("new_edges", &new_edges, gsi::arg ("input"), - "@brief Creates a node converting polygons into it's edges.\n" + "@brief Creates a node converting polygons into its edges.\n" ) + gsi::constructor ("new_edge_length_filter", &new_edge_length_filter, gsi::arg ("input"), gsi::arg ("inverse", false), gsi::arg ("lmin", 0), gsi::arg ("lmax", std::numeric_limits::max (), "max"), "@brief Creates a node filtering edges by their length.\n" diff --git a/src/db/db/gsiDeclDbLayout.cc b/src/db/db/gsiDeclDbLayout.cc index 9da66889d..5402af6db 100644 --- a/src/db/db/gsiDeclDbLayout.cc +++ b/src/db/db/gsiDeclDbLayout.cc @@ -1374,7 +1374,7 @@ Class decl_Layout ("db", "Layout", "If the region is (conceptionally) a flat region, it will be inserted into the cell's shapes " "list as a flat sequence of polygons.\n" "If the region is a deep (hierarchical) region, it will create a subhierarchy below the given " - "cell and it's shapes will be put into the respective cells. Suitable subcells will be picked " + "cell and its shapes will be put into the respective cells. Suitable subcells will be picked " "for inserting the shapes. If a hierarchy already exists below the given cell, the algorithm will " "try to reuse this hierarchy.\n" "\n" @@ -1386,7 +1386,7 @@ Class decl_Layout ("db", "Layout", "If the edge collection is (conceptionally) flat, it will be inserted into the cell's shapes " "list as a flat sequence of edges.\n" "If the edge collection is deep (hierarchical), it will create a subhierarchy below the given " - "cell and it's edges will be put into the respective cells. Suitable subcells will be picked " + "cell and its edges will be put into the respective cells. Suitable subcells will be picked " "for inserting the edges. If a hierarchy already exists below the given cell, the algorithm will " "try to reuse this hierarchy.\n" "\n" @@ -1398,7 +1398,7 @@ Class decl_Layout ("db", "Layout", "If the edge pair collection is (conceptionally) flat, it will be inserted into the cell's shapes " "list as a flat sequence of edge pairs.\n" "If the edge pair collection is deep (hierarchical), it will create a subhierarchy below the given " - "cell and it's edge pairs will be put into the respective cells. Suitable subcells will be picked " + "cell and its edge pairs will be put into the respective cells. Suitable subcells will be picked " "for inserting the edge pairs. If a hierarchy already exists below the given cell, the algorithm will " "try to reuse this hierarchy.\n" "\n" @@ -1410,7 +1410,7 @@ Class decl_Layout ("db", "Layout", "If the text collection is (conceptionally) flat, it will be inserted into the cell's shapes " "list as a flat sequence of texts.\n" "If the text collection is deep (hierarchical), it will create a subhierarchy below the given " - "cell and it's texts will be put into the respective cells. Suitable subcells will be picked " + "cell and its texts will be put into the respective cells. Suitable subcells will be picked " "for inserting the texts. If a hierarchy already exists below the given cell, the algorithm will " "try to reuse this hierarchy.\n" "\n" diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index bf80bc24e..417abd105 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -388,7 +388,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "@brief Extracts devices\n" "See the class description for more details.\n" "This method will run device extraction for the given extractor. The layer map is specific\n" - "for the extractor and uses the region objects derived with \\make_layer and it's variants.\n" + "for the extractor and uses the region objects derived with \\make_layer and its variants.\n" "\n" "In addition, derived regions can be passed too. Certain limitations apply. It's safe to use\n" "boolean operations for deriving layers. Other operations are applicable as long as they are\n" @@ -410,7 +410,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", ) + gsi::method ("connect", (void (db::LayoutToNetlist::*) (const db::Region &)) &db::LayoutToNetlist::connect, gsi::arg ("l"), "@brief Defines an intra-layer connection for the given layer.\n" - "The layer is either an original layer created with \\make_includelayer and it's variants or\n" + "The layer is either an original layer created with \\make_includelayer and its variants or\n" "a derived layer. Certain limitations apply. It's safe to use\n" "boolean operations for deriving layers. Other operations are applicable as long as they are\n" "capable of delivering hierarchical layers.\n" @@ -810,7 +810,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "@li Preparation\n" " In this step, the device recognition and extraction layers are drawn from\n" " the framework. Derived can now be computed using boolean operations.\n" - " Methods to use in this step are \\make_layer and it's variants.\n" + " Methods to use in this step are \\make_layer and its variants.\n" " Layer preparation is not necessarily required to happen before all\n" " other steps. Layers can be computed shortly before they are required.\n" "@/li\n" @@ -821,7 +821,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", " may be specified here. Layer preparation may happen between calls to \\extract_devices.\n" "@/li\n" "@li Once the devices are derived, the netlist connectivity can be defined and the\n" - " netlist extracted. The connectivity is defined with \\connect and it's\n" + " netlist extracted. The connectivity is defined with \\connect and its\n" " flavours. The actual netlist extraction happens with \\extract_netlist.\n" "@/li\n" "@li After netlist extraction, the information is ready to be retrieved.\n" diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index a898425b2..af209c40e 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -1701,7 +1701,7 @@ Class decl_dbCircuit (decl_dbNetlistObject, "db", "Circuit", ) + gsi::method ("flatten_subcircuit", &db::Circuit::flatten_subcircuit, gsi::arg ("subcircuit"), "@brief Flattens a subcircuit\n" - "This method will substitute the given subcircuit by it's contents. The subcircuit is removed " + "This method will substitute the given subcircuit by its contents. The subcircuit is removed " "after this." ) + gsi::iterator ("each_subcircuit", (db::Circuit::subcircuit_iterator (db::Circuit::*) ()) &db::Circuit::begin_subcircuits, (db::Circuit::subcircuit_iterator (db::Circuit::*) ()) &db::Circuit::end_subcircuits, @@ -1986,7 +1986,7 @@ Class decl_dbNetlist ("db", "Netlist", ) + gsi::method ("flatten_circuit", &db::Netlist::flatten_circuit, gsi::arg ("circuit"), "@brief Flattens a subcircuit\n" - "This method will substitute all instances (subcircuits) of the given circuit by it's " + "This method will substitute all instances (subcircuits) of the given circuit by its " "contents. After this, the circuit is removed." ) + gsi::method_ext ("flatten_circuit", &flatten_circuit_by_name, gsi::arg ("pattern"), diff --git a/src/db/db/gsiDeclDbNetlistCompare.cc b/src/db/db/gsiDeclDbNetlistCompare.cc index f2e193ffc..c8f1fe6a4 100644 --- a/src/db/db/gsiDeclDbNetlistCompare.cc +++ b/src/db/db/gsiDeclDbNetlistCompare.cc @@ -454,7 +454,7 @@ Class decl_GenericNetlistCompareLogger (decl_dbNetl ), "@brief An event receiver for the netlist compare feature.\n" "The \\NetlistComparer class will send compare events to a logger derived from this class. " - "Use this class to implement your own logger class. You can override on of it's methods to receive certain " + "Use this class to implement your own logger class. You can override on of its methods to receive certain " "kind of events." "\n" "This class has been introduced in version 0.26.\n" diff --git a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc index 5cdcd8605..9219c823e 100644 --- a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc +++ b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc @@ -325,7 +325,7 @@ Class decl_GenericDeviceExtractor (decl_dbNetlistDeviceE "This method is supposed to set up the device extractor. This involves three basic steps:\n" "defining the name, the device class and setting up the device layers.\n" "\n" - "Use \\name= to give the extractor and it's device class a name.\n" + "Use \\name= to give the extractor and its device class a name.\n" "Use \\register_device_class to register the device class you need.\n" "Defined the layers by calling \\define_layer once or several times.\n" ) + @@ -377,7 +377,7 @@ Class decl_GenericDeviceExtractor (decl_dbNetlistDeviceE "@return The layer descriptor object created for this layer (use 'index' to get the layer's index)\n" "As \\define_layer, this method allows specification of device extraction layer. In addition to \\define_layout, it features " "a fallback layer. If in the device extraction statement, the primary layer is not given, " - "the fallback layer will be used. Hence, this layer is optional. The fallback layer is given by it's " + "the fallback layer will be used. Hence, this layer is optional. The fallback layer is given by its " "index and must be defined before the layer using the fallback layer is defined. " "For the index, 0 is the first layer defined, 1 the second and so forth." ) + diff --git a/src/db/db/gsiDeclDbPolygon.cc b/src/db/db/gsiDeclDbPolygon.cc index eaa36e98a..0fb9a0dc1 100644 --- a/src/db/db/gsiDeclDbPolygon.cc +++ b/src/db/db/gsiDeclDbPolygon.cc @@ -372,7 +372,7 @@ struct simple_polygon_defs method ("is_box?", &C::is_box, "@brief Returns a value indicating whether the polygon is a simple box.\n" "\n" - "A polygon is a box if it is identical to it's bounding box.\n" + "A polygon is a box if it is identical to its bounding box.\n" "\n" "@return True if the polygon is a box.\n" "\n" @@ -1380,7 +1380,7 @@ struct polygon_defs method ("is_box?", &C::is_box, "@brief Returns true, if the polygon is a simple box.\n" "\n" - "A polygon is a box if it is identical to it's bounding box.\n" + "A polygon is a box if it is identical to its bounding box.\n" "\n" "@return True if the polygon is a box.\n" "\n" diff --git a/src/db/db/gsiDeclDbTechnologies.cc b/src/db/db/gsiDeclDbTechnologies.cc index 1b05e3e3f..7b442971f 100644 --- a/src/db/db/gsiDeclDbTechnologies.cc +++ b/src/db/db/gsiDeclDbTechnologies.cc @@ -120,7 +120,7 @@ gsi::Class technology_component_decl ("db", "Technology "@brief A part of a technology definition\n" "Technology components extend technology definitions (class \\Technology) by " "specialized subfeature definitions. For example, the net tracer supplies " - "it's technology-dependent specification through a technology component called " + "its technology-dependent specification through a technology component called " "\\NetTracerTechnology.\n" "\n" "Components are managed within technologies and can be accessed from a technology " diff --git a/src/db/db/gsiDeclDbTilingProcessor.cc b/src/db/db/gsiDeclDbTilingProcessor.cc index 7faa40b50..e599f00a7 100644 --- a/src/db/db/gsiDeclDbTilingProcessor.cc +++ b/src/db/db/gsiDeclDbTilingProcessor.cc @@ -174,7 +174,7 @@ gsi::Class &dbdecl_TileOutputReceiverBase () gsi::Class decl_TileOutputReceiver (decl_TileOutputReceiverBase, "db", "TileOutputReceiver", gsi::callback ("begin", &TileOutputReceiver_Impl::begin, &TileOutputReceiver_Impl::begin_cb, gsi::arg ("nx"), gsi::arg ("ny"), gsi::arg ("p0"), gsi::arg ("dx"), gsi::arg ("dy"), gsi::arg ("frame"), "@brief Initiates the delivery\n" - "This method is called before the first tile delivers it's data.\n" + "This method is called before the first tile delivers its data.\n" "\n" "@param nx The number of tiles in x direction\n" "@param ny The number of tiles in y direction\n" diff --git a/src/db/db/gsiDeclDbTrans.cc b/src/db/db/gsiDeclDbTrans.cc index 802bdb625..24e2f831c 100644 --- a/src/db/db/gsiDeclDbTrans.cc +++ b/src/db/db/gsiDeclDbTrans.cc @@ -739,7 +739,7 @@ struct cplx_trans_defs method ("invert", &C::invert, "@brief Inverts the transformation (in place)\n" "\n" - "Inverts the transformation and replaces this transformation by it's\n" + "Inverts the transformation and replaces this transformation by its\n" "inverted one.\n" "\n" "@return The inverted transformation\n" diff --git a/src/db/db/gsiDeclDbUtils.cc b/src/db/db/gsiDeclDbUtils.cc index 3e7e66463..8e571c279 100644 --- a/src/db/db/gsiDeclDbUtils.cc +++ b/src/db/db/gsiDeclDbUtils.cc @@ -62,7 +62,7 @@ namespace gsi gsi::method ("spline_interpolation", &db::UtilsDummy::spi1, gsi::arg ("control_points"), gsi::arg ("weights"), gsi::arg ("degree"), gsi::arg ("knots"), gsi::arg ("relative_accuracy"), gsi::arg ("absolute_accuracy"), "@brief This function computes the Spline curve for a given set of control points (point, weight), degree and knots.\n" "\n" - "The knot vector needs to be padded and it's size must fulfill the condition:\n" + "The knot vector needs to be padded and its size must fulfill the condition:\n" "\n" "@code\n" " knots.size == control_points.size + degree + 1\n" diff --git a/src/db/unit_tests/dbNetlistCompareTests.cc b/src/db/unit_tests/dbNetlistCompareTests.cc index 965ae0b38..0f1cc9a06 100644 --- a/src/db/unit_tests/dbNetlistCompareTests.cc +++ b/src/db/unit_tests/dbNetlistCompareTests.cc @@ -2409,7 +2409,7 @@ TEST(15_EmptySubCircuitWithoutPinNames) " subcircuit TRANS $3 ($1=OUT,$2=$5,$3=$2);\n" " subcircuit TRANS $4 ($1=OUT,$2=$4,$3=$2);\n" "end;\n" - // This circuit is an abstract and it's pins are not defined by the pin names -> + // This circuit is an abstract and its pins are not defined by the pin names -> // they are internally marked as swappable "circuit TRANS ($1=$1,$2=$2,$3=$3);\n" "end;\n"; @@ -4152,7 +4152,7 @@ TEST(23_NodesRemovedWithError) " subcircuit INV2PAIR $5 ($2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7);\n" "end;\n" "circuit INV2PAIR ($2=$I8,$3=$I5,$4=$I4,$5=$I3,$6=$I2);\n" - // NOTE: $1 pin should not be connected to different nets, although it's not functional + // NOTE: $1 pin should not be connected to different nets, although its not functional " subcircuit INV2 $1 ($1=$3,IN=$I3,$3=$I7,OUT=$I6,VSS=$I4,VDD=$I5);\n" " subcircuit INV2 $2 ($1=$6,IN=$I6,$3=$I8,OUT=$I2,VSS=$I4,VDD=$I5);\n" "end;\n" diff --git a/src/drc/drc/built-in-macros/_drc_cop_integration.rb b/src/drc/drc/built-in-macros/_drc_cop_integration.rb index 624f0d506..8eebae6fb 100644 --- a/src/drc/drc/built-in-macros/_drc_cop_integration.rb +++ b/src/drc/drc/built-in-macros/_drc_cop_integration.rb @@ -335,7 +335,7 @@ module DRC # # Some filters operate on properties of the full, local, per-primary shape set. # While the loop is executed, the DRC expressions will collect shapes, either - # from the primary, it's neighborhood (secondaries) or from deriving shape sets. + # from the primary, its neighborhood (secondaries) or from deriving shape sets. # # Obviously the primary is a simple one: it consists of a single shape, because # this is how the loop operates. Derived shape sets however can be more complex. @@ -528,7 +528,7 @@ module DRC # # This feature opens new options for processing layouts beyond the # abilities of the classical DRC concept. For classic DRC, intra-layer interactions - # are always symmetric: a polygon cannot be considered separated from it's neighbors + # are always symmetric: a polygon cannot be considered separated from its neighbors # on the same layer. # # The following example computes every part of the input which is closer than diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb index 75bb29735..ee4ef6803 100644 --- a/src/drc/drc/built-in-macros/_drc_layer.rb +++ b/src/drc/drc/built-in-macros/_drc_layer.rb @@ -630,7 +630,7 @@ CODE # @synopsis layer.with_area_ratio(min .. max) # @synopsis layer.with_area_ratio(value) # @synopsis layer.with_area_ratio(min, max) - # The area ratio is a measure how far a polygon is approximated by it's + # The area ratio is a measure how far a polygon is approximated by its # bounding box. The value is always larger or equal to 1. Boxes have a # area ratio of 1. Larger values mean more empty area inside the bounding box. # @@ -648,7 +648,7 @@ CODE # %DRC% # @name with_relative_height - # @brief Selects polygons by the ratio of the height vs. width of it's bounding box + # @brief Selects polygons by the ratio of the height vs. width of its bounding box # @synopsis layer.with_relative_height(min .. max) # @synopsis layer.with_relative_height(value) # @synopsis layer.with_relative_height(min, max) diff --git a/src/gsi/gsi/gsiExpression.cc b/src/gsi/gsi/gsiExpression.cc index a52a3ba63..9a979e9e7 100644 --- a/src/gsi/gsi/gsiExpression.cc +++ b/src/gsi/gsi/gsiExpression.cc @@ -496,7 +496,7 @@ struct writer if (atype.is_ref () || atype.is_ptr ()) { - // TODO: morph the variant to the requested type and pass it's pointer (requires a non-const reference for arg) + // TODO: morph the variant to the requested type and pass its pointer (requires a non-const reference for arg) // -> we would have a reference that can modify the argument (out parameter). R *v = new R (var2c::get (*arg)); heap->push (v); @@ -542,7 +542,7 @@ struct writer } else { - // TODO: morph the variant to the requested type and pass it's pointer (requires a non-const reference for arg) + // TODO: morph the variant to the requested type and pass its pointer (requires a non-const reference for arg) // -> we would have a reference that can modify the argument (out parameter). // NOTE: by convention we pass the ownership to the receiver for adaptors. aa->write ((void *)new StringAdaptorImpl (arg->to_string ())); diff --git a/src/gsi/gsi/gsiIterators.h b/src/gsi/gsi/gsiIterators.h index eb9561092..3a56ad830 100644 --- a/src/gsi/gsi/gsiIterators.h +++ b/src/gsi/gsi/gsiIterators.h @@ -225,7 +225,7 @@ private: }; /** - * @brief The template providing a binding of a "free iterator" (one that provides it's own at_end method) + * @brief The template providing a binding of a "free iterator" (one that provides its own at_end method) */ template class FreeIterAdaptor diff --git a/src/gsiqt/qtbasic/gsiQtHelper.cc b/src/gsiqt/qtbasic/gsiQtHelper.cc index 98775d5c6..de382d49b 100644 --- a/src/gsiqt/qtbasic/gsiQtHelper.cc +++ b/src/gsiqt/qtbasic/gsiQtHelper.cc @@ -40,10 +40,10 @@ class QtLifetimeMonitor }; /** - * @brief A helper object that is attached to a QObject to monitor it's lifetime + * @brief A helper object that is attached to a QObject to monitor its lifetime * * This object will be put into the properties table of the QObject (more precisely: a copy). - * When the QObject is destroyed, it's properties are destroyed too and through reference + * When the QObject is destroyed, its properties are destroyed too and through reference * counting the destruction of the QObject is detected. The monitoring itself is implemented * through a gsi::ObjectBase object which plugs seamlessly into the gsi type system: * diff --git a/src/lay/lay/built_in_macros/qobject_helper.lym b/src/lay/lay/built_in_macros/qobject_helper.lym index fb0c4ebc2..e89f3e33f 100644 --- a/src/lay/lay/built_in_macros/qobject_helper.lym +++ b/src/lay/lay/built_in_macros/qobject_helper.lym @@ -7,7 +7,7 @@ @args id, ... This method implements Ruby's fallback mechanism and adds some convenience to QObject: through that implementation, each child object can be accessed through -it's name. That method will deliver a reference to the child object or nil if there +its name. That method will deliver a reference to the child object or nil if there is no child element with that name. For example: diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 390263bb6..8e80edf82 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -541,7 +541,7 @@ MainWindow::init_menu () } // if not in editable mode, hide all entries from "edit_mode" group - // TODO: later do this on each change of the view - each view might get it's own editable mode + // TODO: later do this on each change of the view - each view might get its own editable mode bool view_mode = (lay::ApplicationBase::instance () && !lay::ApplicationBase::instance ()->is_editable ()); std::vector edit_mode_grp = menu ()->group ("edit_mode"); @@ -742,7 +742,7 @@ MainWindow::about_to_exec () } } - // TODO: later, each view may get it's own editable flag + // TODO: later, each view may get its own editable flag if (lay::ApplicationBase::instance () && !lay::ApplicationBase::instance ()->is_editable ()) { TipDialog td (this, tl::to_string (QObject::tr ("KLayout has been started in viewer mode. In this mode, editor functions are not available.\n\nTo enable these functions, start KLayout in editor mode by using the \"-e\" command line switch or select it as the default mode in the setup dialog. Choose \"Setup\" in the \"File\" menu and check \"Use editing mode by default\" on the \"Editing Mode\" page in the \"Application\" section.")), diff --git a/src/lay/lay/laySaltController.cc b/src/lay/lay/laySaltController.cc index d73b5b035..8dc078c4f 100644 --- a/src/lay/lay/laySaltController.cc +++ b/src/lay/lay/laySaltController.cc @@ -201,10 +201,10 @@ SaltController::install_packages (const std::vector &packages, bool } if (n.find ("http:") == 0 || n.find ("https:") == 0 || n.find ("file:") == 0 || n[0] == '/' || n[0] == '\\') { - // it's a URL + // its a URL manager.register_download (std::string (), std::string (), n, v); } else { - // it's a plain name + // its a plain name manager.register_download (n, std::string (), std::string (), v); } diff --git a/src/lay/lay/laySaltGrainPropertiesDialog.cc b/src/lay/lay/laySaltGrainPropertiesDialog.cc index 63bfa2248..7a3f098b9 100644 --- a/src/lay/lay/laySaltGrainPropertiesDialog.cc +++ b/src/lay/lay/laySaltGrainPropertiesDialog.cc @@ -580,7 +580,7 @@ SaltGrainPropertiesDialog::accept () if (d->version.empty ()) { dependencies_alert->warn () << tr ("No version specified for dependency '%1'").arg (tl::to_qstring (d->name)) << tl::endl << tr ("Please consider giving a version here. Versions help deciding whether a package needs to be updated.") << tl::endl - << tr ("If the dependency package has a version itself, the version is automatically set to it's current version."); + << tr ("If the dependency package has a version itself, the version is automatically set to its current version."); } if (!d->url.empty ()) { diff --git a/src/lay/lay/macro_templates/pcell.lym b/src/lay/lay/macro_templates/pcell.lym index 31ed9240f..eb89f8096 100644 --- a/src/lay/lay/macro_templates/pcell.lym +++ b/src/lay/lay/macro_templates/pcell.lym @@ -46,7 +46,7 @@ module PCellLibModule end def coerce_parameters_impl - # TODO: use x to access parameter x and set_x to modify it's value + # TODO: use x to access parameter x and set_x to modify its value end def produce_impl diff --git a/src/lay/lay/macro_templates/pcell_python.lym b/src/lay/lay/macro_templates/pcell_python.lym index 1f36444ff..474f91a9a 100644 --- a/src/lay/lay/macro_templates/pcell_python.lym +++ b/src/lay/lay/macro_templates/pcell_python.lym @@ -34,7 +34,7 @@ class PCell(pya.PCellDeclarationHelper): return "TODO: create description" def coerce_parameters_impl(self): - # TODO: use x to access parameter x and set_x to modify it's value + # TODO: use x to access parameter x and set_x to modify its value def produce_impl(self): # TODO: produce the cell content diff --git a/src/lay/lay/salt_templates/pcell_lib/macros/pcell.lym b/src/lay/lay/salt_templates/pcell_lib/macros/pcell.lym index 8965f06c3..bda3d447f 100644 --- a/src/lay/lay/salt_templates/pcell_lib/macros/pcell.lym +++ b/src/lay/lay/salt_templates/pcell_lib/macros/pcell.lym @@ -48,7 +48,7 @@ module PCellPackageModule end def coerce_parameters_impl - # TODO: use x to access parameter x and set_x to modify it's value + # TODO: use x to access parameter x and set_x to modify its value end def produce_impl diff --git a/src/laybasic/laybasic/gsiDeclLayLayers.cc b/src/laybasic/laybasic/gsiDeclLayLayers.cc index 787eab65d..e7b9caf9c 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayers.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayers.cc @@ -1241,7 +1241,7 @@ Class decl_LayerPropertiesNode ( "Each layer properties node object has a unique ID that is created \n" "when a new LayerPropertiesNode object is instantiated. The ID is\n" "copied when the object is copied. The ID can be used to identify the\n" - "object irregardless of it's content.\n" + "object irregardless of its content.\n" ), "@brief A layer properties node structure\n" "\n" @@ -1441,7 +1441,7 @@ Class decl_LayerPropertiesIterator ( "@brief Returns the index of the child within the parent\n" "\n" "This method returns the index of that the properties node the iterator points to in the list\n" - "of children of it's parent. If the element does not have a parent, the \n" + "of children of its parent. If the element does not have a parent, the \n" "index of the element in the global list is returned.\n" ), "@brief Layer properties iterator\n" diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc index 43b8af32b..39dbe2404 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutViewBase.cc @@ -1438,7 +1438,7 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi "@brief Hierarchically iterates over the layers in the given layer list\n" "\n" "This version of this method allows specification of the layer list to be iterated over. " - "The layer list is specified by it's index which is a value between 0 and \\num_layer_lists-1." + "The layer list is specified by its index which is a value between 0 and \\num_layer_lists-1." "For details see the parameter-less version of this method.\n" "\n" "This method was introduced in version 0.25." @@ -1666,7 +1666,7 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi "\n" "If a file is loaded, this event is triggered.\n" "When this event is triggered, the file was already loaded and the new file is the new active cellview.\n" - "Despite it's name, this event is also triggered if a layout object is loaded into the view.\n" + "Despite its name, this event is also triggered if a layout object is loaded into the view.\n" "\n" "Before version 0.25 this event was based on the observer pattern obsolete now. The corresponding methods " "(add_file_open_observer/remove_file_open_observer) have been removed in 0.25.\n" @@ -1683,7 +1683,7 @@ LAYBASIC_PUBLIC Class decl_LayoutViewBase ("lay", "LayoutVi gsi::event ("on_layer_list_changed", static_cast (lay::LayoutViewBase::*)> (&lay::LayoutViewBase::layer_list_changed_event), gsi::arg ("flags"), "@brief An event indicating that the layer list has changed\n" "\n" - "This event is triggered after the layer list has changed it's configuration.\n" + "This event is triggered after the layer list has changed its configuration.\n" "The integer argument gives a hint about the nature of the changed:\n" "Bit 0 is set, if the properties (visibility, color etc.) of one or more layers have changed. Bit 1 is\n" "set if the hierarchy has changed. Bit 2 is set, if layer names have changed." @@ -2239,7 +2239,7 @@ Class decl_CellView ("lay", "CellView", "\n" "This method will construct any path to this cell, not a \n" "particular one. It will clear the context path\n" - "and update the context and target cell. Note that the cell is specified by it's index.\n" + "and update the context and target cell. Note that the cell is specified by its index.\n" ) + method ("cell_name=|set_cell_name", (void (lay::CellViewRef::*) (const std::string &)) &lay::CellViewRef::set_cell, gsi::arg ("cell_name"), "@brief Sets the cell by name\n" @@ -2394,9 +2394,9 @@ Class decl_CellView ("lay", "CellView", "is addressed by an cell_index or a cell object reference.\n" "The layout pointer can be nil, indicating that the cell view is invalid.\n" "\n" - "The cell is not only identified by it's index or object but also \n" + "The cell is not only identified by its index or object but also \n" "by the path leading to that cell. This path indicates how to find the\n" - "cell in the hierarchical context of it's parent cells. \n" + "cell in the hierarchical context of its parent cells. \n" "\n" "The path is in fact composed of two parts: first in an unspecific fashion,\n" "just describing which parent cells are used. The target of this path\n" diff --git a/src/laybasic/laybasic/gsiDeclLayPlugin.cc b/src/laybasic/laybasic/gsiDeclLayPlugin.cc index 7b9d449e2..2ff01425c 100644 --- a/src/laybasic/laybasic/gsiDeclLayPlugin.cc +++ b/src/laybasic/laybasic/gsiDeclLayPlugin.cc @@ -730,7 +730,7 @@ Class decl_Plugin ("lay", "Plugin", callback ("config_finalize", &gsi::PluginBase::config_finalize, &gsi::PluginBase::f_config_finalize, "@brief Sends the post-configuration request to the plugin\n" "After all configuration parameters have been sent, 'config_finalize' is called to given the plugin a chance to " - "update it's internal state according to the new configuration.\n" + "update its internal state according to the new configuration.\n" ) + callback ("key_event", &gsi::PluginBase::key_event, &gsi::PluginBase::f_key_event, gsi::arg ("key"), gsi::arg ("buttons"), "@brief Handles the key pressed event\n" @@ -840,7 +840,7 @@ Class decl_Plugin ("lay", "Plugin", ), "@brief The plugin object\n" "\n" - "This class provides the actual plugin implementation. Each view gets it's own instance of the plugin class. The plugin factory \\PluginFactory class " + "This class provides the actual plugin implementation. Each view gets its own instance of the plugin class. The plugin factory \\PluginFactory class " "must be specialized to provide a factory for new objects of the Plugin class. See the documentation there for details about the plugin mechanism and " "the basic concepts.\n" "\n" diff --git a/src/laybasic/laybasic/gtf.cc b/src/laybasic/laybasic/gtf.cc index 8d3a8ecb6..a719a7dca 100644 --- a/src/laybasic/laybasic/gtf.cc +++ b/src/laybasic/laybasic/gtf.cc @@ -1532,7 +1532,7 @@ Recorder::eventFilter (QObject *object, QEvent *event) if (event->type() == QEvent::MouseButtonPress) { - // send the test event to make the object print it's content + // send the test event to make the object print its content QEvent event (QEvent::MaxUser); event.ignore (); diff --git a/src/laybasic/laybasic/layAbstractMenu.cc b/src/laybasic/laybasic/layAbstractMenu.cc index 06ff6435a..14b55bf13 100644 --- a/src/laybasic/laybasic/layAbstractMenu.cc +++ b/src/laybasic/laybasic/layAbstractMenu.cc @@ -52,7 +52,7 @@ namespace lay #if defined(__APPLE__) -// On MacOS, the main menu bar and it's decendent children +// On MacOS, the main menu bar and its decendent children // can't be modified using "removeAction", followed by "addAction" // to achieve a move operation.If we try to do so, segmentation faults happen // in the timer event that presumably tries to merge the menu bar diff --git a/src/laybasic/laybasic/layBitmapRenderer.cc b/src/laybasic/laybasic/layBitmapRenderer.cc index e5d67ccb6..c5289162f 100644 --- a/src/laybasic/laybasic/layBitmapRenderer.cc +++ b/src/laybasic/laybasic/layBitmapRenderer.cc @@ -54,7 +54,7 @@ void BitmapRenderer::clear () { // this implementation is efficient but does not free memory - - // the idea is to let the BitmapRenderer object manage it's workspace. + // the idea is to let the BitmapRenderer object manage its workspace. m_edges.erase (m_edges.begin (), m_edges.end ()); // might be manhattan m_ortho = true; diff --git a/src/layui/layui/NetExportDialog.ui b/src/layui/layui/NetExportDialog.ui index dd56a1849..267ff77df 100644 --- a/src/layui/layui/NetExportDialog.ui +++ b/src/layui/layui/NetExportDialog.ui @@ -216,7 +216,7 @@ - If this option is selected, the subcircuits parts of a net are represented by individual cells. Otherwise the net with it's subcircuit parts is exported as a whole (flattened). + If this option is selected, the subcircuits parts of a net are represented by individual cells. Otherwise the net with its subcircuit parts is exported as a whole (flattened). true diff --git a/src/layui/layui/gsiDeclLayDialogs.cc b/src/layui/layui/gsiDeclLayDialogs.cc index c08a774fe..585673997 100644 --- a/src/layui/layui/gsiDeclLayDialogs.cc +++ b/src/layui/layui/gsiDeclLayDialogs.cc @@ -344,7 +344,7 @@ Class decl_BrowserDialog (QT_EXTERNAL_BASE (QDialog) "lay", "The browser dialog displays HTML code in a browser panel. The HTML code is delivered through a separate " "object of class \\BrowserSource which acts as a \"server\" for a specific kind of URL scheme. Whenever the " "browser sees a URL starting with \"int:\" it will ask the connected BrowserSource object for the HTML code " - "of that page using it's 'get' method. The task of the BrowserSource object is to format the data requested " + "of that page using its 'get' method. The task of the BrowserSource object is to format the data requested " "in HTML and deliver it.\n" "\n" "One use case for that class is the implementation of rich data browsers for structured information. In a " @@ -699,7 +699,7 @@ Class decl_InputDialog ("lay", "InputDialog", "@param title The title to display for the dialog\n" "@param label The label text to display for the dialog\n" "@param value The initial value for the input field\n" - "@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n" + "@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n" "Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent." ) + gsi::method ("#get_item", &get_item, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("items"), gsi::arg ("value"), @@ -708,7 +708,7 @@ Class decl_InputDialog ("lay", "InputDialog", "@param label The label text to display for the dialog\n" "@param items The list of items to show in the selection element\n" "@param selection The initial selection (index of the element selected initially)\n" - "@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n" + "@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n" "Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent." ) + gsi::method ("#get_string_password", &get_string_password, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), @@ -716,7 +716,7 @@ Class decl_InputDialog ("lay", "InputDialog", "@param title The title to display for the dialog\n" "@param label The label text to display for the dialog\n" "@param value The initial value for the input field\n" - "@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n" + "@return A \\StringValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n" "Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent." ) + gsi::method ("#get_double", &get_double, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), gsi::arg ("digits"), @@ -725,7 +725,7 @@ Class decl_InputDialog ("lay", "InputDialog", "@param label The label text to display for the dialog\n" "@param value The initial value for the input field\n" "@param digits The number of digits allowed\n" - "@return A \\DoubleValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n" + "@return A \\DoubleValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n" "Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent." ) + gsi::method ("#get_double_ex", &get_double_ex, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), gsi::arg ("min"), gsi::arg ("max"), gsi::arg ("digits"), @@ -736,7 +736,7 @@ Class decl_InputDialog ("lay", "InputDialog", "@param min The minimum value allowed\n" "@param max The maximum value allowed\n" "@param digits The number of digits allowed\n" - "@return A \\DoubleValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n" + "@return A \\DoubleValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n" "Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent." ) + gsi::method ("#get_int", &get_int, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), @@ -744,7 +744,7 @@ Class decl_InputDialog ("lay", "InputDialog", "@param title The title to display for the dialog\n" "@param label The label text to display for the dialog\n" "@param value The initial value for the input field\n" - "@return A \\IntValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n" + "@return A \\IntValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n" "Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent." ) + gsi::method ("#get_int_ex", &get_int_ex, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), gsi::arg ("min"), gsi::arg ("max"), gsi::arg ("step"), @@ -755,7 +755,7 @@ Class decl_InputDialog ("lay", "InputDialog", "@param min The minimum value allowed\n" "@param max The maximum value allowed\n" "@param step The step size for the spin buttons\n" - "@return A \\IntValue object with has_value? set to true, if \"Ok\" was pressed and the value given in it's value attribute\n" + "@return A \\IntValue object with has_value? set to true, if \"Ok\" was pressed and the value given in its value attribute\n" "Starting from 0.22, this method is deprecated and it is recommended to use the ask_... equivalent." ) + gsi::method ("ask_string", &ask_string, gsi::arg ("title"), gsi::arg ("label"), gsi::arg ("value"), diff --git a/src/layui/layui/layHierarchyControlPanel.cc b/src/layui/layui/layHierarchyControlPanel.cc index 4fb1d64e8..3e74fb2e4 100644 --- a/src/layui/layui/layHierarchyControlPanel.cc +++ b/src/layui/layui/layHierarchyControlPanel.cc @@ -84,7 +84,7 @@ HCPCellTreeWidget::HCPCellTreeWidget (QWidget *parent, const char *name, QWidget HCPCellTreeWidget::~HCPCellTreeWidget () { // NOTE: this should not be required, but I got a strange crash on closing the app with Qt 5.12.8 - // after using changePersistentIndex inside the model when ~QTreeWidget tried to clean up it's + // after using changePersistentIndex inside the model when ~QTreeWidget tried to clean up its // persistent indexes and only found a model which was deleted already. QAbstractItemModel *m = model (); if (m) { diff --git a/src/layui/layui/layLayoutViewFunctions.cc b/src/layui/layui/layLayoutViewFunctions.cc index 157b978ba..e2c917a89 100644 --- a/src/layui/layui/layLayoutViewFunctions.cc +++ b/src/layui/layui/layLayoutViewFunctions.cc @@ -735,7 +735,7 @@ void LayoutViewFunctions::cm_cell_cut () { if (view ()->hierarchy_panel ()) { - // TODO: currently the hierarchy panel's cut function does it's own transaction handling. + // TODO: currently the hierarchy panel's cut function does its own transaction handling. // Otherwise the cut function is not working propertly. view ()->hierarchy_panel ()->cut (); } @@ -1873,12 +1873,12 @@ LayoutViewFunctions::cm_edit_layer () { lay::LayerPropertiesConstIterator sel = view ()->current_layer (); if (sel.is_null ()) { - throw tl::Exception (tl::to_string (tr ("No layer selected for editing it's properties"))); + throw tl::Exception (tl::to_string (tr ("No layer selected for editing its properties"))); } int index = sel->cellview_index (); if (sel->has_children () || index < 0 || int (view ()->cellviews ()) <= index || sel->layer_index () < 0) { - throw tl::Exception (tl::to_string (tr ("No valid layer selected for editing it's properties"))); + throw tl::Exception (tl::to_string (tr ("No valid layer selected for editing its properties"))); } const lay::CellView &cv = view ()->cellview (index); diff --git a/src/layview/layview/layLayoutView_qt.cc b/src/layview/layview/layLayoutView_qt.cc index 038890594..43df835f3 100644 --- a/src/layview/layview/layLayoutView_qt.cc +++ b/src/layview/layview/layLayoutView_qt.cc @@ -1356,7 +1356,7 @@ void LayoutView::cut () { if (mp_hierarchy_panel && mp_hierarchy_panel->has_focus ()) { - // TODO: currently the hierarchy panel's cut function does it's own transaction handling. + // TODO: currently the hierarchy panel's cut function does its own transaction handling. // Otherwise the cut function is not working propertly. mp_hierarchy_panel->cut (); } else if (mp_control_panel && mp_control_panel->has_focus ()) { diff --git a/src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc b/src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc index 0914f5ed4..71301dcb6 100755 --- a/src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc +++ b/src/plugins/streamers/dxf/db_plugin/gsiDeclDbDXF.cc @@ -328,11 +328,11 @@ gsi::ClassExt dxf_reader_options ( "This method has been added in version 0.25.3." ) + gsi::method_ext ("dxf_keep_other_cells=", &set_dxf_keep_other_cells, gsi::arg ("value"), - "@brief If this option is set to true, all cells are kept, not only the top cell and it's children\n" + "@brief If this option is set to true, all cells are kept, not only the top cell and its children\n" "\nThis property has been added in version 0.21.15.\n" ) + gsi::method_ext ("dxf_keep_other_cells?|#dxf_keep_other_cells", &get_dxf_keep_other_cells, - "@brief If this option is true, all cells are kept, not only the top cell and it's children\n" + "@brief If this option is true, all cells are kept, not only the top cell and its children\n" "\nThis property has been added in version 0.21.15.\n" ) + gsi::method_ext ("dxf_polyline_mode=", &set_dxf_polyline_mode, gsi::arg ("mode"), diff --git a/src/plugins/streamers/dxf/lay_plugin/DXFReaderOptionPage.ui b/src/plugins/streamers/dxf/lay_plugin/DXFReaderOptionPage.ui index 9465e76b7..dcba064a3 100644 --- a/src/plugins/streamers/dxf/lay_plugin/DXFReaderOptionPage.ui +++ b/src/plugins/streamers/dxf/lay_plugin/DXFReaderOptionPage.ui @@ -266,7 +266,7 @@ - Check this box to keep all cells, not only the top cell and it's children + Check this box to keep all cells, not only the top cell and its children diff --git a/src/rdb/rdb/gsiDeclRdb.cc b/src/rdb/rdb/gsiDeclRdb.cc index 0f26862dc..0b67f6ce4 100644 --- a/src/rdb/rdb/gsiDeclRdb.cc +++ b/src/rdb/rdb/gsiDeclRdb.cc @@ -184,7 +184,7 @@ Class decl_RdbCell ("rdb", "RdbCell", "@brief Gets the cell name\n" "The cell name is an string that identifies the category in the database. " "Additionally, a cell may carry a variant identifier which is a string that uniquely identifies a cell " - "in the context of it's variants. The \"qualified name\" contains both the cell name and the variant name. " + "in the context of its variants. The \"qualified name\" contains both the cell name and the variant name. " "Cell names are also used to identify report database cell's with layout cells. " "@return The cell name\n" ) + @@ -347,7 +347,7 @@ Class decl_RdbCategory ("rdb", "RdbCategory", ) + gsi::method_ext ("scan_layer", &scan_layer, gsi::arg ("layout"), gsi::arg ("layer"), gsi::arg ("cell", (const db::Cell *) 0, "nil"), gsi::arg ("levels", -1), gsi::arg ("with_properties", true), "@brief Scans a layer from a layout into this category, starting with a given cell and a depth specification\n" - "Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n" + "Creates RDB items for each polygon or edge shape read from the cell and its children in the layout on the given layer and puts them into this category.\n" "New cells will be generated when required.\n" "\"levels\" is the number of hierarchy levels to take the child cells from. 0 means to use only \"cell\" and don't descend, -1 means \"all levels\".\n" "Other settings like database unit, description, top cell etc. are not made in the RDB.\n" @@ -1031,7 +1031,7 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", ) + gsi::method ("description", &rdb::Database::description, "@brief Gets the databases description\n" - "The description is a general purpose string that is supposed to further describe the database and it's content " + "The description is a general purpose string that is supposed to further describe the database and its content " "in a human-readable form.\n" "@return The description string\n" ) + From 559c45a5854b46096d624aa624c732111c5acb51 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 30 Jul 2023 14:50:53 +0200 Subject: [PATCH 11/22] it's -> its --- src/doc/doc/about/drc_ref_global.xml | 2 +- src/doc/doc/about/drc_ref_layer.xml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/doc/about/drc_ref_global.xml b/src/doc/doc/about/drc_ref_global.xml index 3deac6889..0e80df7f3 100644 --- a/src/doc/doc/about/drc_ref_global.xml +++ b/src/doc/doc/about/drc_ref_global.xml @@ -768,7 +768,7 @@ is called on. This operation represents all "other" primary polygons while

This feature opens new options for processing layouts beyond the abilities of the classical DRC concept. For classic DRC, intra-layer interactions -are always symmetric: a polygon cannot be considered separated from it's neighbors +are always symmetric: a polygon cannot be considered separated from its neighbors on the same layer.

The following example computes every part of the input which is closer than diff --git a/src/doc/doc/about/drc_ref_layer.xml b/src/doc/doc/about/drc_ref_layer.xml index 6efff2012..2e5e6b2b9 100644 --- a/src/doc/doc/about/drc_ref_layer.xml +++ b/src/doc/doc/about/drc_ref_layer.xml @@ -676,7 +676,7 @@ out = l1.drc((secondary(l2) & primary).area > 1.0)

Some filters operate on properties of the full, local, per-primary shape set. While the loop is executed, the DRC expressions will collect shapes, either -from the primary, it's neighborhood (secondaries) or from deriving shape sets. +from the primary, its neighborhood (secondaries) or from deriving shape sets.

Obviously the primary is a simple one: it consists of a single shape, because this is how the loop operates. Derived shape sets however can be more complex. @@ -1537,7 +1537,7 @@ from the other layer. Two polygons overlapping or touching at two locations are

This operation is similar to the "&" operator, but it does also report intersection points -between non-colinear, but intersection edges. Such points are reported as point-like, +between non-colinear, but intersecting edges. Such points are reported as point-like, degenerated edge objects.

This method is available for edge layers. The argument must be an edge layer. @@ -3609,7 +3609,7 @@ This method is available for polygon or edge pair layers.

  • layer.with_area_ratio(min, max)
  • -The area ratio is a measure how far a polygon is approximated by it's +The area ratio is a measure how far a polygon is approximated by its bounding box. The value is always larger or equal to 1. Boxes have a area ratio of 1. Larger values mean more empty area inside the bounding box.

    @@ -3883,7 +3883,7 @@ upper limit.

    This method is available for polygon layers only.

    -

    "with_relative_height" - Selects polygons by the ratio of the height vs. width of it's bounding box

    +

    "with_relative_height" - Selects polygons by the ratio of the height vs. width of its bounding box

    Usage:

      From bf95e51332429b2eae96a8d691479230324bb60d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 1 Aug 2023 22:06:46 +0200 Subject: [PATCH 12/22] Resolve include-coded lines for DRC/LVS logs in verbose mode --- src/drc/drc/built-in-macros/_drc_engine.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index 6bc5f4c72..1fea174ca 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -2317,7 +2317,11 @@ CODE c !~ /drc.lym:/ && c !~ /_drc_\w+\.rb:/ && c !~ /\(eval\)/ end if cc =~ /(.*)\s*:\s*(\d+)\s*:\s*in.*$/ - return File::basename($1) + ":" + $2 + path = $1 + line = $2.to_i + real_path = RBA::Macro::real_path(path, line) + real_line = RBA::Macro::real_line(path, line) + return File::basename(real_path) + ":" + real_line.to_s else return cc end From 6bfd2a7368678fd1464df32ba170763c75c6f6e1 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 2 Aug 2023 23:27:44 +0200 Subject: [PATCH 13/22] Fixed warning in case of Qt bindings not being compiled in --- src/img/img/gsiDeclImg.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/img/img/gsiDeclImg.cc b/src/img/img/gsiDeclImg.cc index 4a7ee22cb..6199de34c 100644 --- a/src/img/img/gsiDeclImg.cc +++ b/src/img/img/gsiDeclImg.cc @@ -451,7 +451,7 @@ static ImageRef *new_image_pbt (const tl::PixelBuffer &pixel_buffer, const db::D return new ImageRef (img::Object (pixel_buffer, trans)); } -#if HAVE_QT +#if defined(HAVE_QTBINDINGS) static ImageRef *new_image_qit (const QImage &image, const db::DCplxTrans &trans) { return new ImageRef (img::Object (image, trans)); @@ -597,7 +597,7 @@ gsi::Class decl_Image (decl_BasicImage, "lay", "Image", "@param filename The path to the image file to load.\n" "@param trans The transformation to apply to the image when displaying it.\n" ) + -#if defined(HAVE_QT) +#if defined(HAVE_QTBINDINGS) gsi::constructor ("new", &gsi::new_image_qit, gsi::arg ("image"), gsi::arg ("trans", db::DCplxTrans (), "unity"), "@brief Constructor from a image pixel buffer\n" "\n" From cfc84252ab741ff316d1729042288b284b85b46c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 2 Aug 2023 23:47:45 +0200 Subject: [PATCH 14/22] DRC/LVS: Fixed a typo + allowing 'report' also for cases without default layout (only 'layout' specs) --- src/drc/drc/built-in-macros/_drc_engine.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/drc/drc/built-in-macros/_drc_engine.rb b/src/drc/drc/built-in-macros/_drc_engine.rb index 1fea174ca..53ac76a5a 100644 --- a/src/drc/drc/built-in-macros/_drc_engine.rb +++ b/src/drc/drc/built-in-macros/_drc_engine.rb @@ -2912,7 +2912,7 @@ CODE def _make_path(file) # resolves the file path relative to the source's path - sp = self.source.path + sp = (@def_source || @def_layout) && self.source.path if sp if File.respond_to?(:absolute_path) return File::absolute_path(file, File::dirname(sp)) @@ -3242,7 +3242,7 @@ CODE cn = cellname && cellname.to_s cn ||= @def_cell && @def_cell.name - cn ||= source && source.cell_name + cn ||= @def_source && @def_source.cell_obj && @def_source.cell_obj.name cn || raise("No cell name specified - either the source was not specified before 'report' or there is no default source. In the latter case, specify a cell name as the third parameter") @@ -3285,7 +3285,7 @@ CODE cn ||= @def_cell && @def_cell.name cn ||= @def_source && @def_source.cell_obj && @def_source.cell_obj.name - cn || raise("No cell name specified - either the source was not specified before 'report' or there is no default source. In the latter case, specify a cell name as the third parameter") + cn || raise("No cell name specified - either the source was not specified before 'report' or there is no default source. In the latter case, specify a cell name as the second parameter") output_layout = RBA::Layout::new output_cell = output_layout.create_cell(cn) From 2eca865bd8a060560dd98dc769fc6f7dbfe26305 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 2 Aug 2023 23:56:51 +0200 Subject: [PATCH 15/22] Added tests for last change --- src/drc/unit_tests/drcSimpleTests.cc | 71 ++++++++++++++++++++++++++++ testdata/drc/drcSimpleTests_14c.drc | 27 +++++++++++ 2 files changed, 98 insertions(+) create mode 100644 testdata/drc/drcSimpleTests_14c.drc diff --git a/src/drc/unit_tests/drcSimpleTests.cc b/src/drc/unit_tests/drcSimpleTests.cc index c0825e751..74db2a3fa 100644 --- a/src/drc/unit_tests/drcSimpleTests.cc +++ b/src/drc/unit_tests/drcSimpleTests.cc @@ -800,6 +800,77 @@ TEST(14b_SideTargetsAndReports) compare_text_files (report2, au_report2); } +TEST(14c_OnlySpecialInputsAndReports) +{ + std::string rs = tl::testdata (); + rs += "/drc/drcSimpleTests_14c.drc"; + + // apart from that it's a variant of 14b ... + + std::string input = tl::testdata (); + input += "/drc/drcSimpleTests_14b.gds"; + + std::string au = tl::testdata (); + au += "/drc/drcSimpleTests_au14b.gds"; + + std::string au2 = tl::testdata (); + au2 += "/drc/drcSimpleTests_au14b_2.gds"; + + std::string au_report = tl::testdata (); + au_report += "/drc/drcSimpleTests_au14b.lyrdb"; + + std::string au_report2 = tl::testdata (); + au_report2 += "/drc/drcSimpleTests_au14b_2.lyrdb"; + + std::string output = this->tmp_file ("tmp.gds"); + std::string output2 = this->tmp_file ("tmp2.gds"); + std::string report = this->tmp_file ("tmp.lydrc"); + std::string report2 = this->tmp_file ("tmp2.lydrc"); + + { + // Set some variables + lym::Macro config; + config.set_text (tl::sprintf ( + "$drc_force_gc = true\n" + "$drc_test_source = '%s'\n" + "$drc_test_target = '%s'\n" + "$drc_test_target2 = '%s'\n" + "$drc_test_report = '%s'\n" + "$drc_test_report2 = '%s'\n" + , input, output, output2, report, report2) + ); + config.set_interpreter (lym::Macro::Ruby); + EXPECT_EQ (config.run (), 0); + } + + lym::Macro drc; + drc.load_from (rs); + EXPECT_EQ (drc.run (), 0); + + db::Layout layout; + + { + tl::InputStream stream (output); + db::Reader reader (stream); + reader.read (layout); + } + + db::compare_layouts (_this, layout, au, db::NoNormalization); + + db::Layout layout2; + + { + tl::InputStream stream (output2); + db::Reader reader (stream); + reader.read (layout2); + } + + db::compare_layouts (_this, layout2, au2, db::NoNormalization); + + compare_text_files (report, au_report); + compare_text_files (report2, au_report2); +} + TEST(15_issue548) { std::string rs = tl::testdata (); diff --git a/testdata/drc/drcSimpleTests_14c.drc b/testdata/drc/drcSimpleTests_14c.drc new file mode 100644 index 000000000..8ea96ae69 --- /dev/null +++ b/testdata/drc/drcSimpleTests_14c.drc @@ -0,0 +1,27 @@ + +lyin = layout($drc_test_source) +cn = lyin.layout.top_cell.name + +lyin2 = layout($drc_test_source) + +target($drc_test_target, cn) + +l1 = lyin.input(1, 0) +l2 = lyin2.input(2, 0) + +tcopy = new_target($drc_test_target2, cn) +rcopy = new_report("Report 2", $drc_test_report2, cn) + +l1.output(tcopy, 101, 0) +l2.output(tcopy, 102, 0) + +l1.output(1, 0) +l1.space(1.0.um).output(100, 0) + +report("Report 1", $drc_test_report, cn) + +l2.space(1.0.um).output("l2 space < 1µm") +l1.width(1.0.um).output("l1 width < 1µm") + +l1.sep(l2, 1.0.um).output(rcopy, "l1 sep l2 < 1µm") + From 7509e7a18c5c0cf9dab6d4415f310974ac6d85de Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 3 Aug 2023 00:01:44 +0200 Subject: [PATCH 16/22] Fixed a typo --- src/buddies/src/bd/bdWriterOptions.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/buddies/src/bd/bdWriterOptions.cc b/src/buddies/src/bd/bdWriterOptions.cc index 93c559a86..c8be61c03 100644 --- a/src/buddies/src/bd/bdWriterOptions.cc +++ b/src/buddies/src/bd/bdWriterOptions.cc @@ -105,7 +105,7 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin if (format.empty () || format == gds2_format_name || format == gds2text_format_name) { cmd << tl::arg (group + "#--keep-instances", &m_keep_instances, "Keeps instances of dropped cells", - "If given, instances of dropped cell's won't be removed. Hence, ghost cells are " + "If given, instances of dropped cells won't be removed. Hence, ghost cells are " "produced. The resulting layout may not be readable by consumers that require " "all instantiated cells to be present as actual cells.\n" "Dropped cells are those which are removed by a negative cell selection (see " From f583d5e3dba6c4de992b02200584aaf4ca780f2a Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 3 Aug 2023 19:22:11 +0200 Subject: [PATCH 17/22] Fixed a potential segfault of application exit --- src/laybasic/laybasic/layPlugin.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/laybasic/laybasic/layPlugin.cc b/src/laybasic/laybasic/layPlugin.cc index ca24ed090..44b4d072d 100644 --- a/src/laybasic/laybasic/layPlugin.cc +++ b/src/laybasic/laybasic/layPlugin.cc @@ -327,6 +327,10 @@ Plugin::~Plugin () if (mp_parent) { mp_parent->unregister_plugin (this); } + // remove us from the children's parent + for (auto c = m_children.begin (); c != m_children.end (); ++c) { + c->mp_parent = 0; + } } void From 7d749140f7cdb9b559d35e4c3bf130f894a2f6f8 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 3 Aug 2023 21:35:37 +0200 Subject: [PATCH 18/22] Enhancements for macro editor's search and replace: replace single wasn't working properly and now there is find next and previous --- src/icons/icons.qrc | 4 + src/icons/images/find_next_16px.png | Bin 0 -> 689 bytes src/icons/images/find_next_16px@2x.png | Bin 0 -> 1534 bytes src/icons/images/find_prev_16px.png | Bin 0 -> 702 bytes src/icons/images/find_prev_16px@2x.png | Bin 0 -> 1514 bytes src/icons/svg/find_next_16px.svg | 231 +++++++++++++++++++++++++ src/icons/svg/find_prev_16px.svg | 231 +++++++++++++++++++++++++ src/lay/lay/MacroEditorDialog.ui | 23 ++- src/lay/lay/layMacroEditorDialog.cc | 21 ++- src/lay/lay/layMacroEditorDialog.h | 2 +- src/lay/lay/layMacroEditorPage.cc | 65 +++++-- src/lay/lay/layMacroEditorPage.h | 3 +- 12 files changed, 555 insertions(+), 25 deletions(-) create mode 100644 src/icons/images/find_next_16px.png create mode 100644 src/icons/images/find_next_16px@2x.png create mode 100644 src/icons/images/find_prev_16px.png create mode 100644 src/icons/images/find_prev_16px@2x.png create mode 100644 src/icons/svg/find_next_16px.svg create mode 100644 src/icons/svg/find_prev_16px.svg diff --git a/src/icons/icons.qrc b/src/icons/icons.qrc index 7067e958d..e7c2d7a30 100644 --- a/src/icons/icons.qrc +++ b/src/icons/icons.qrc @@ -284,5 +284,9 @@ images/bookmark_16px@2x.png images/bookmark_24px.png images/bookmark_24px@2x.png + images/find_next_16px.png + images/find_next_16px@2x.png + images/find_prev_16px.png + images/find_prev_16px@2x.png diff --git a/src/icons/images/find_next_16px.png b/src/icons/images/find_next_16px.png new file mode 100644 index 0000000000000000000000000000000000000000..aeb6b16f7be7e1eb249febe55b6f58df5d35aca4 GIT binary patch literal 689 zcmV;i0#5yjP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10zOGZ zK~y-6g^)i>TTvW_-+MhVVlZTjB*EnhibE~EToLZR^9ah$isVlgo^Gz0+1<#JF;q1|p{Z*R{} zCX-*Mr>8#y_+l7F{U6Ef?CkeaslPU;ryCD^Wh54*}F}1xUWoT3_z$?1ZDEqs(M7-D6o6H#avKhGFD+-s?LT zB>9TuWu;OHEz9b{TU%QUf`AJP3$$%}!?x|1*-Ky;#wP&tQp#v~c{z&5<5*f+ilmgf zTrR_PT>uE~Y;dE=8(}CeR5XQ6I_j zv3+!&-+j+>-edSbOTEdY3l}a}*=)AMFpO5ElxVG&8yXrG#>dC2?-d}GN)1|;b=9`* zr0cq2(=?9&c%JvFR4T1itJSZ4-~aW)hY$b$P67J*`oga3-ibsasg{jvX$&=l#>vH7C5t7Ly(P)%l zFo^H_Y;0_>xVXs7%naFVmQtz2%F4=gxm^BiYHDiktpWP_`of`5=!?^*Pj?4{K~kv{ zU0q#RmIZ+C`}n?JfBI6X#N)@0nV6WMSS+%k5BobpiJw4wI zg+g4sc#%`5P7w?S2?PSzwvA<3oH%iUXf%pp7!->|nwpx3L?S$W`V_};n)CVmcNP~H zZ|}PTsZ?sPy}kX9$z-ze+_`h~_V!}iHnwe3%Yg6uM5EDqMPM@*wfEZCFbu7f5?}-P z9Js2Kn%xbczLMiOzdCm8SmV*7N9pP5!M1H2#~~01)D1-h)7()slv0QYN~!H2hEhrc zA>hZr1rZtC4Z?uUbM81!!nSQXJ3Fx~3(KdBL@{HC)$4M9^CAfO*&E zb%2J3hJ{=%_p)3rH!mzK5Q#+U+h7<*9pHV)02m)1uX>*Mb*WV1$&)7(3I&SAB85T$ ztu?V&jPCC41DlD+f{6T1MB+OD0JPS>U0q$xzIgG1OeRC2P{8+ndU|?jY;1h({J*7Q zz|Vj$MdbJnfQgBTFLJqDx>Bi-PN$ihn_gKu zxpCtLhGB5|@@1x`rViwI`0!y&(Toy=Th)Ip-cwUkbDrl7E-fwn`O%|CC4f*U z#PIO&fr1#1$7O76Ot-YO)V>qEyo44tmJ9l{Y>>16?&9!N| zzUF=aY7&v}0lx==0Q2+nYG`Q41Q;6|)5&B~06fn#u3x`yXsuaUSz&2uiJ6(1ue8=5 zPfkv*zBRxW#P_!#9Dv!`S*4U>TR1DvpFjV_(9qB?`}_O*j~_qIg9i`3T3=tUn;!^Z z3*tw>UBLdvPZi*&N~u2$3=A}yrui4gaVQiDJIvpSMC2n8`Dg8PY>hwKK4)NHps^OZ k_a+f(5s{W}pSe^20WR2>OICg0!2kdN07*qoM6N<$f=Dp$lmGw# literal 0 HcmV?d00001 diff --git a/src/icons/images/find_prev_16px.png b/src/icons/images/find_prev_16px.png new file mode 100644 index 0000000000000000000000000000000000000000..cf9d4b6a47af2ae46794823da596989f9e4aff66 GIT binary patch literal 702 zcmV;v0zv(WP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10!v9m zK~y-6b&^d>8(|cMpG+ok5dCFNYhU848#Agfv)RnB9ZtqIXO8$J3E^g z9v;T?JSvq6rfD{+)v6hW;qzW5DnL9Qe>*)rJ)h6#6aD@D0BD-V`1m+eQ&WkHi;Jfx zCnxKMVZ7?O#nRH!&#kR3IX^!a%d*6>EUDM)(!%xiwFE&RzVE+&C|0uBY$_Iujipkl z4k8Ew01U%mW@ZM%Fo;H@A4Q~N3&n99X*QcUj)QI6TwY${x-Nr*gY50?vAVj7<2V$H zMNHFFfOQdh*)}*jI{Ix{R`vAsl&h;Nf*@dMXoym&#Paeox3{+dIF7^0$_l%?yHVhi zh`az$0J*uj+1T0HY1p<+I-Tb5@Q}sD#kRNw*L5iti|p_3M}f~G@;C~RPN%=ywmmm7 zG4V)5qJ=_%Mx)UyaD3lqb90kiE~ku+j#k=)uIuXB+S&)-_rq5DBO@bS?;e^WlIfZt zA{p0pO%V}I(>lbOrb!S4a(sOJr&g=YwKC{Dib$l~*Vp&;u71cNA{-nXBo`JI-efYF zSeL;an!OCdFhoR1CX)aj+?{d{Yy)1kT8%vt<807*qoM6N<$g4>lm%K!iX literal 0 HcmV?d00001 diff --git a/src/icons/images/find_prev_16px@2x.png b/src/icons/images/find_prev_16px@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe78865c343d38eac5a04dfc05cbde2f77c31779 GIT binary patch literal 1514 zcmV2N>f#&4N@g46)1KML2N70Ux2!; zS~mR)-L+j*y)R&aL?lFo96K1IAQB}ICN{Ps8|Px?e&%$M%qS*KY(p>a>dZH1zW15) zog45!i>as6$&)9!VzJoCvTO&#Fq9CI4F-eq=;)~RuL6X_;X#h$zT|nnTau&}kH^yt z0ES^KX_~fZS=Ov=+h2{1js5kH0`&Lyw@8xoV;~R+x3{L|Y}>}l$_g@> z3?4mtgkrG>P1BIi=O=YtKQlf)KJ&@|{r&wdKA-Q-p+krIL{UUI9LE0r`@wM>0Km3w z*tYHdy{2iHn3zB!k$|eI$Y!&XhG7gQlgXue0X*v;y1Kf4K6vopyFQ-}!^6WkaNqz$ zQG_4};CUV#$6?>TeF%j@U|ANbs-m^E6@fqixm*rSO-*e}OG|HOGMOJ59)WN;Jh*Gu zuHU-5yLTKvejJAn9|q6!;CUX-9I$O0?d|R0c^&{zDwU8FEK-ao{)(JkP`H^+J*)NRkAv*9+4$p{nYJM00a44y z0D$Lt7QpY6($jST6pO`9pU>9<0HIK*);B1Z%N5VEEF%($AQFi{mSra_0QiYg`e97~ zkH_<-AP9a!2t-k=Sm(N~LseC%stR4#!7vPh!JwNUlgS_&jpEs}XKp*4PCKt90Dn+Q zKiCog00jM59qmPfu?)vPh@Xh{a;a z<#JA_3BV0X>H8Z1Mn^|2!!TwwO~b>751}ZEYYqT=_wI$qv$|(3FE3+cWCT-FQ=6JQ znwy)$`Sa(I&*z=c8(1yJI~4!`KnVG|P$(1^78a07rQBif>+5qjo|Tmq#9}c_Oia`? zcl6}Rlb0dlgF+{G@H$xPALJ0)YU4)pb8IGJ;ep)v&pv+1XjdVlfnpMJF`8 z0U(u1E$X^{CY#Mpnx+ZMvY;pmE?>TkWHR~6=8mSOrVx!r@%;I7H&*pRGB7aE?D2TM zzjp1~@X*kZw_2Z_J9pM)x^6#sS-&t0^C?^HO){BWipS$0-@SYH;)@qAjB0%trmpKG zD5cfHB>-1}IxeM@(jH3bw*XEt3?n)5&dyE{LTUoYvg|Hl+qO$A%iaQTm0_4^0N`pR zU>Ifwz$a@k1^|97UekQ-8@GMp#EC4W^oy~vF?V;WT7s?eHQ2vG9*?KbvaFj&j~;c8 z+*by0w&hx~ZQE_LEDMg~-m)y~=D@(fj{h8>t*y;zx|63-fMuuA=o}z~!0-2iVVDOj z%YK+lCJR6vlkg?o0`M6CjE|3Rw!|tViXwp3dx9*>4+tTydBdWV_EJhqv_a{*POe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/icons/svg/find_prev_16px.svg b/src/icons/svg/find_prev_16px.svg new file mode 100644 index 000000000..51d796955 --- /dev/null +++ b/src/icons/svg/find_prev_16px.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lay/lay/MacroEditorDialog.ui b/src/lay/lay/MacroEditorDialog.ui index 80f62e53c..fa02c8421 100644 --- a/src/lay/lay/MacroEditorDialog.ui +++ b/src/lay/lay/MacroEditorDialog.ui @@ -463,10 +463,6 @@ ... - - - :/breakpoint_16px.png:/breakpoint_16px.png - F9 @@ -636,7 +632,7 @@ - :/find_16px.png:/find_16px.png + :/find_next_16px.png:/find_next_16px.png Ctrl+F @@ -646,6 +642,23 @@ + + + + ... + + + + :/find_prev_16px.png:/find_prev_16px.png + + + Ctrl+Shift+F + + + true + + + diff --git a/src/lay/lay/layMacroEditorDialog.cc b/src/lay/lay/layMacroEditorDialog.cc index e75c60dfa..bf8c9ed03 100644 --- a/src/lay/lay/layMacroEditorDialog.cc +++ b/src/lay/lay/layMacroEditorDialog.cc @@ -493,6 +493,7 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection connect (replaceModeButton, SIGNAL (clicked ()), this, SLOT (replace_mode_button_clicked ())); connect (replaceNextButton, SIGNAL (clicked ()), this, SLOT (replace_next_button_clicked ())); connect (findNextButton, SIGNAL (clicked ()), this, SLOT (find_next_button_clicked ())); + connect (findPrevButton, SIGNAL (clicked ()), this, SLOT (find_prev_button_clicked ())); connect (replaceAllButton, SIGNAL (clicked ()), this, SLOT (replace_all_button_clicked ())); connect (allVariables, SIGNAL (clicked (bool)), variableList, SLOT (set_show_all (bool))); @@ -2021,7 +2022,7 @@ MacroEditorDialog::replace_all_button_clicked () } void -MacroEditorDialog::search_requested (const QString &s) +MacroEditorDialog::search_requested (const QString &s, bool prev) { if (! s.isNull ()) { searchEditBox->setText (s); @@ -2029,7 +2030,21 @@ MacroEditorDialog::search_requested (const QString &s) searchEditBox->selectAll (); } searchEditBox->setFocus (); - search_editing (); + + MacroEditorPage *page = dynamic_cast (tabWidget->currentWidget ()); + if (! page) { + return; + } + + apply_search (); + page->find_reset (); // search from the initial position + if (! page->has_multi_block_selection ()) { + if (! prev) { + page->find_next (); + } else { + page->find_prev (); + } + } } void @@ -3511,7 +3526,7 @@ MacroEditorDialog::create_page (lym::Macro *macro) editor->exec_model ()->set_run_mode (m_in_exec); editor->connect_macro (macro); connect (editor.get (), SIGNAL (help_requested (const QString &)), this, SLOT (help_requested (const QString &))); - connect (editor.get (), SIGNAL (search_requested (const QString &)), this, SLOT (search_requested (const QString &))); + connect (editor.get (), SIGNAL (search_requested (const QString &, bool)), this, SLOT (search_requested (const QString &, bool))); connect (editor.get (), SIGNAL (edit_trace (bool)), this, SLOT (add_edit_trace (bool))); return editor.release (); } diff --git a/src/lay/lay/layMacroEditorDialog.h b/src/lay/lay/layMacroEditorDialog.h index 54d9428df..24bd3eccf 100644 --- a/src/lay/lay/layMacroEditorDialog.h +++ b/src/lay/lay/layMacroEditorDialog.h @@ -222,7 +222,7 @@ private slots: void find_next_button_clicked (); void find_prev_button_clicked (); void help_requested (const QString &s); - void search_requested (const QString &s); + void search_requested (const QString &s, bool prev); void macro_changed (lym::Macro *macro); void macro_deleted (lym::Macro *macro); void macro_collection_deleted (lym::MacroCollection *collection); diff --git a/src/lay/lay/layMacroEditorPage.cc b/src/lay/lay/layMacroEditorPage.cc index 408949cd2..3abaa328b 100644 --- a/src/lay/lay/layMacroEditorPage.cc +++ b/src/lay/lay/layMacroEditorPage.cc @@ -1077,12 +1077,10 @@ MacroEditorPage::find_prev () first = false; int i = -1; - int l = 0; int p = 0; while (true) { int ii = m_current_search.indexIn (b.text (), p); if (ii >= 0 && (o < 0 || ii < o)) { - l = m_current_search.matchedLength (); i = ii; p = ii + 1; } else { @@ -1091,8 +1089,7 @@ MacroEditorPage::find_prev () } if (i >= 0) { QTextCursor newc (b); - newc.setPosition (i + b.position () + l); - newc.setPosition (i + b.position (), QTextCursor::KeepAnchor); + newc.setPosition (i + b.position ()); m_ignore_cursor_changed_event = true; mp_text->setTextCursor (newc); m_ignore_cursor_changed_event = false; @@ -1136,8 +1133,7 @@ MacroEditorPage::find_next () int i = m_current_search.indexIn (b.text (), o); if (i >= 0) { QTextCursor newc (b); - newc.setPosition (i + b.position () + m_current_search.matchedLength ()); - newc.setPosition (i + b.position (), QTextCursor::KeepAnchor); + newc.setPosition (i + b.position ()); m_ignore_cursor_changed_event = true; mp_text->setTextCursor (newc); m_ignore_cursor_changed_event = false; @@ -1158,6 +1154,39 @@ MacroEditorPage::find_next () return false; } +bool +MacroEditorPage::select_match_here () +{ + if (m_current_search == QRegExp ()) { + return false; + } + + QTextCursor c = mp_text->textCursor (); + if (c.isNull ()) { + return false; + } + + if (c.hasSelection ()) { + return true; + } + + QTextBlock b = c.block (); + int pos = c.position () - b.position (); + int i = m_current_search.indexIn (b.text (), pos); + if (i == pos) { + QTextCursor newc (b); + newc.setPosition (i + b.position () + m_current_search.matchedLength ()); + newc.setPosition (i + b.position (), QTextCursor::KeepAnchor); + m_ignore_cursor_changed_event = true; + mp_text->setTextCursor (newc); + m_ignore_cursor_changed_event = false; + emit edit_trace (false); + return true; + } else { + return false; + } +} + void MacroEditorPage::set_editor_focus () { @@ -1196,7 +1225,9 @@ MacroEditorPage::replace_and_find_next (const QString &replace) return; } - replace_in_selection (replace, true); + if (select_match_here ()) { + replace_in_selection (replace, true); + } find_next (); } @@ -1280,12 +1311,8 @@ MacroEditorPage::replace_in_selection (const QString &replace, bool first) o = i + r.size (); if (first) { - - // in single-selection mode, put cursor past substitution - c.setPosition (i + b.position ()); has_selection = false; done = true; - } else if (b == be) { pe += int (r.size ()) - int (m_current_search.matchedLength ()); } @@ -1734,6 +1761,11 @@ static bool is_find_key (QKeyEvent *ke) return ke->key () == Qt::Key_F && (ke->modifiers () & Qt::ControlModifier) != 0; } +static bool is_find_backwards_key (QKeyEvent *ke) +{ + return ke->key () == Qt::Key_F && (ke->modifiers () & Qt::ControlModifier) != 0 && (ke->modifiers () & Qt::ShiftModifier) != 0; +} + static bool is_up_key (QKeyEvent *ke) { return ke->key () == Qt::Key_Up; @@ -1755,6 +1787,7 @@ static bool is_any_known_key (QKeyEvent *ke) is_help_key (ke) || is_find_next_key (ke) || is_find_key (ke) || + is_find_backwards_key (ke) || is_up_key (ke) || is_down_key (ke); } @@ -1848,19 +1881,21 @@ MacroEditorPage::eventFilter (QObject *watched, QEvent *event) QApplication::sendEvent (mp_completer_list, event); return true; - } else if (is_find_key (ke)) { + } else if (is_find_key (ke) || is_find_backwards_key (ke)) { + + bool prev = is_find_backwards_key (ke); QTextCursor c = mp_text->textCursor (); if (c.selectionStart () != c.selectionEnd ()) { QTextBlock s = mp_text->document ()->findBlock (c.selectionStart ()); QTextBlock e = mp_text->document ()->findBlock (c.selectionEnd ()); if (e == s) { - emit search_requested (c.selectedText ()); + emit search_requested (c.selectedText (), prev); } else { - emit search_requested (QString ()); + emit search_requested (QString (), prev); } } else { - emit search_requested (QString ()); + emit search_requested (QString (), prev); } return true; diff --git a/src/lay/lay/layMacroEditorPage.h b/src/lay/lay/layMacroEditorPage.h index a689aefe5..c298a32b4 100644 --- a/src/lay/lay/layMacroEditorPage.h +++ b/src/lay/lay/layMacroEditorPage.h @@ -271,7 +271,7 @@ public: signals: void help_requested (const QString &s); - void search_requested (const QString &s); + void search_requested (const QString &s, bool backward); void edit_trace (bool); public slots: @@ -314,6 +314,7 @@ private: void fill_completer_list (); void complete (); QTextCursor get_completer_cursor (int &pos0, int &pos); + bool select_match_here (); void replace_in_selection (const QString &replace, bool first); bool eventFilter (QObject *watched, QEvent *event); From f518d1aa1d974897cfeb1ef057057125eeceef40 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 3 Aug 2023 23:27:31 +0200 Subject: [PATCH 19/22] Added variable/expression interpolation to LEF paths so it is possible use environment variables there. --- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index dc706400e..5c4a4a4a8 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -37,14 +37,29 @@ namespace db // ----------------------------------------------------------------------------------- // Path resolution utility -std::string correct_path (const std::string &fn, const db::Layout &layout, const std::string &base_path) +std::string correct_path (const std::string &fn_in, const db::Layout &layout, const std::string &base_path) { + const db::Technology *tech = layout.technology (); + + // Allow LEF reference through expressions, i.e. + // $(base_path) - path of the main file + // $(tech_dir) - the location of the .lyt file if a technology is specified + // $(tech_name) - the name of the technology if one is specified + // In addition expressions are interpolated, e.g. "$(env('HOME'))". + + tl::Eval expr; + expr.set_var ("base_path", base_path); + if (tech) { + expr.set_var ("tech_dir", tech->base_path ()); + expr.set_var ("tech_name", tech->name ()); + } + + std::string fn = expr.interpolate (fn_in); + if (! tl::is_absolute (fn)) { // if a technology is given and the file can be found in the technology's base path, take it // from there. - const db::Technology *tech = layout.technology (); - if (tech && ! tech->base_path ().empty ()) { std::string new_fn = tl::combine_path (tech->base_path (), fn); if (tl::file_exists (new_fn)) { From cbc9123db4fbe1e671e8f878aadf2845b7861e5d Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Fri, 4 Aug 2023 23:23:43 +0200 Subject: [PATCH 20/22] Mitigate the effect of overriding a globally-defined technology with -nn on the command line by creating tech variants --- src/lay/lay/layApplication.cc | 35 ++++++++++++++++++++++++-- src/lay/lay/layTechnologyController.cc | 3 +++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index 6a825293d..b4309db4a 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -686,28 +686,59 @@ ApplicationBase::init_app () tc->add_path (*p); } + tc->load (); + + bool needs_reload = false; + + // disambiguator for tech name + std::map tech_disambiguator; + std::map tech_name_for_file; + + for (auto t = db::Technologies::instance ()->begin (); t != db::Technologies::instance ()->end (); ++t) { + tech_disambiguator.insert (std::make_pair (t->name (), 0)); + } + // import technologies from the command line for (std::vector > >::iterator f = m_files.begin (); f != m_files.end (); ++f) { if (f->first == layout_file_with_tech_file) { + const std::string &tech_file = f->second.second; + if (tl::verbosity () >= 20) { tl::info << "Importing technology from " << f->second.second; } db::Technology t; - t.load (f->second.second); + t.load (tech_file); + + // disambiguate the name, so we do not overwrite technologies with the same name from the config + if (tech_name_for_file.find (tech_file) != tech_name_for_file.end ()) { + t.set_name (tech_name_for_file [tech_file]); + } else if (tech_disambiguator.find (t.name ()) != tech_disambiguator.end ()) { + int &index = tech_disambiguator [t.name ()]; + index += 1; + t.set_name (t.name () + tl::sprintf ("[%d]", index)); + tech_name_for_file.insert (std::make_pair (tech_file, t.name ())); + } else { + tech_disambiguator.insert (std::make_pair (t.name (), 0)); + tech_name_for_file.insert (std::make_pair (tech_file, t.name ())); + } tc->add_temp_tech (t); f->first = layout_file_with_tech; f->second.second = t.name (); + needs_reload = true; + } } - tc->load (); + if (needs_reload) { + tc->load (); + } } diff --git a/src/lay/lay/layTechnologyController.cc b/src/lay/lay/layTechnologyController.cc index 103e7a1cc..212e2a7df 100644 --- a/src/lay/lay/layTechnologyController.cc +++ b/src/lay/lay/layTechnologyController.cc @@ -609,6 +609,9 @@ TechnologyController::rescan (db::Technologies &technologies) for (std::vector::const_iterator t = m_temp_tech.begin (); t != m_temp_tech.end (); ++t) { db::Technology *tech = new db::Technology (*t); + if (tl::verbosity () >= 20) { + tl::info << "Registering special technology from " << tech->tech_file_path () << " as " << tech->name (); + } tech->set_persisted (false); // don't save that one in the configuration tech->set_tech_file_path (std::string ()); // don't save to a file either tech->set_readonly (true); // don't edit From 32fdb4664953d9f29af92b103e95b35c54c7c099 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 5 Aug 2023 00:58:16 +0200 Subject: [PATCH 21/22] Allowing PINNAME and LEFPINNAME purposes in LEF/DEF .map files for a more consistent format (avoids the NAME notation) --- .../lefdef/db_plugin/dbLEFDEFImporter.cc | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc index 5c4a4a4a8..0c74b0633 100644 --- a/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc +++ b/src/plugins/streamers/lefdef/db_plugin/dbLEFDEFImporter.cc @@ -893,16 +893,18 @@ LEFDEFReaderOptions::special_routing_datatype_str () const LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path) : mp_importer (0), m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc) { - if (! tc->map_file ().empty ()) { + if (! tc) { + + // use default options + + } else if (! tc->map_file ().empty ()) { read_map_file (tc->map_file (), layout, base_path); } else { - if (tc) { - m_layer_map = tc->layer_map (); - m_create_layers = tc->read_all_layers (); - } + m_layer_map = tc->layer_map (); + m_create_layers = tc->read_all_layers (); } } @@ -1007,7 +1009,6 @@ LEFDEFReaderState::read_map_file (const std::string &filename, db::Layout &layou // build an explicit layer mapping now. - tl_assert (m_has_explicit_layer_mapping); m_layers.clear (); m_layer_map.clear (); @@ -1030,9 +1031,12 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map purpose_translation; purpose_translation ["LEFPIN"] = LEFPins; purpose_translation ["PIN"] = Pins; + purpose_translation ["LEFPINNAME"] = LEFLabel; + purpose_translation ["PINNAME"] = Label; purpose_translation ["FILL"] = Fills; purpose_translation ["FILLOPC"] = FillsOPC; purpose_translation ["LEFOBS"] = Obstructions; @@ -1042,6 +1046,11 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::mapsecond == All) { - for (std::map::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) { - if (p->second != All && p->second != Blockage) { - translated_purposes.insert (LayerDetailsKey (p->second, mask, via_size)); - } + for (LayerPurpose *p = all_purposes; p != all_purposes + sizeof (all_purposes) / sizeof (all_purposes[0]); ++p) { + translated_purposes.insert (LayerDetailsKey (*p, mask, via_size)); } } else { From 5b7e336b334c035b710a4cb89ce6f6c5f8fc5586 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 5 Aug 2023 01:02:37 +0200 Subject: [PATCH 22/22] Added test for LEF/DEF map file NAME substitute --- .../lefdef/unit_tests/dbLEFDEFImportTests.cc | 4 ++++ testdata/lefdef/mapfile/test-nonames.map | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 testdata/lefdef/mapfile/test-nonames.map diff --git a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc index 788770b82..176642309 100644 --- a/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc +++ b/src/plugins/streamers/lefdef/unit_tests/dbLEFDEFImportTests.cc @@ -540,6 +540,10 @@ TEST(111_mapfile) options.set_map_file ("test.map"); run_test (_this, "mapfile", "read:in.def", "au.oas.gz", options, false); + + options.set_map_file ("test-nonames.map"); + + run_test (_this, "mapfile", "read:in.def", "au.oas.gz", options, false); } TEST(112_via_properties) diff --git a/testdata/lefdef/mapfile/test-nonames.map b/testdata/lefdef/mapfile/test-nonames.map new file mode 100644 index 000000000..cfb23ee5a --- /dev/null +++ b/testdata/lefdef/mapfile/test-nonames.map @@ -0,0 +1,19 @@ +DIEAREA ALL 100 0 +M0PO LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 10 0 +VIA0 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 11 0 +M1 LEFPIN 12 0 +M1 LEFOBS 12 1 +M1 PIN 12 2 +M1 NET 12 3 +M1 SPNET 12 4 +M1 VIA 12 5 +M1 FILLOPC 12 100 +M1 FILLOPC:MASK:1 12 101 +M1 FILLOPC:MASK:2 12 102 +M1 BLOCKAGEFILL 12 150 +M1 BLOCKAGE 12 151 +M1 FILL 12 152 +M1 PINNAME 12 10 +M1 LEFPINNAME 12 10 +VIA1 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 13 0 +M2 LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 14 0