";
}
stream << "";
diff --git a/src/lay/lay/laySaltGrainDetailsTextWidget.h b/src/lay/lay/laySaltGrainDetailsTextWidget.h
index 1e0221235..47dc485ed 100644
--- a/src/lay/lay/laySaltGrainDetailsTextWidget.h
+++ b/src/lay/lay/laySaltGrainDetailsTextWidget.h
@@ -55,6 +55,9 @@ public:
protected:
virtual QVariant loadResource (int type, const QUrl &url);
+public slots:
+ void show_detailed_view (bool f);
+
private slots:
void open_link (const QUrl &url);
@@ -62,6 +65,7 @@ private:
std::unique_ptr mp_grain;
QString details_text ();
+ bool m_detailed_view;
};
}
From e6da3fc22c0ece2d57e0df01e25d1383420f7f78 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Thu, 27 Oct 2022 00:42:28 +0200
Subject: [PATCH 02/29] WIP: callbacks for PCells
---
src/db/db/dbPCellDeclaration.h | 189 ++++++++++-
src/db/db/gsiDeclDbLibrary.cc | 8 +-
src/edt/edt/edtPCellParametersPage.cc | 438 +++++++++++++++++---------
src/edt/edt/edtPCellParametersPage.h | 11 +-
4 files changed, 498 insertions(+), 148 deletions(-)
diff --git a/src/db/db/dbPCellDeclaration.h b/src/db/db/dbPCellDeclaration.h
index 808a75fe2..aaecb02df 100644
--- a/src/db/db/dbPCellDeclaration.h
+++ b/src/db/db/dbPCellDeclaration.h
@@ -61,6 +61,7 @@ public:
t_layer, // a layer (value is a db::LayerProperties object)
t_shape, // a shape (a db::Point, db::Box, db::Polygon, db::Edge or db::Path) rendering a guiding shape
t_list, // a list of strings
+ t_callback, // callback only (button)
t_none // no specific type
};
@@ -323,6 +324,174 @@ public:
std::string symbolic;
};
+/**
+ * @brief Represents the dynamic state of a single parameter
+ */
+class DB_PUBLIC ParameterState
+{
+public:
+ /**
+ * @brief Parameterized constructor
+ */
+ ParameterState ()
+ : m_value (), m_visible (true), m_enabled (true),
+ m_value_changed (false), m_visible_changed (false), m_enabled_changed (false)
+ {
+ // .. nothing yet ..
+ }
+
+ /**
+ * @brief Gets the value
+ */
+ const tl::Variant &value () const
+ {
+ return m_value;
+ }
+
+ /**
+ * @brief Sets the value
+ */
+ void set_value (const tl::Variant &v)
+ {
+ if (m_value != v) {
+ m_value = v;
+ m_value_changed = true;
+ }
+ }
+
+ /**
+ * @brief Gets a value indicating wheter the value has changed
+ */
+ bool value_changed () const
+ {
+ return m_value_changed;
+ }
+
+ /**
+ * @brief Gets the visibility state
+ */
+ bool is_visible () const
+ {
+ return m_visible;
+ }
+
+ /**
+ * @brief Sets the visibility
+ */
+ void set_visible (bool v)
+ {
+ if (m_visible != v) {
+ m_visible = v;
+ m_visible_changed = true;
+ }
+ }
+
+ /**
+ * @brief Gets a value indicating wheter the visibility has changed
+ */
+ bool visible_changed () const
+ {
+ return m_visible_changed;
+ }
+
+ /**
+ * @brief Gets the enabled state
+ */
+ bool is_enabled () const
+ {
+ return m_enabled;
+ }
+
+ /**
+ * @brief Sets the enabled state
+ */
+ void set_enabled (bool v)
+ {
+ if (m_enabled != v) {
+ m_enabled = v;
+ m_enabled_changed = true;
+ }
+ }
+
+ /**
+ * @brief Gets a value indicating wheter the enabled state has changed
+ */
+ bool enabled_changed () const
+ {
+ return m_enabled_changed;
+ }
+
+ /**
+ * @brief Resets the modified flags
+ */
+ void reset ()
+ {
+ m_enabled_changed = m_visible_changed = m_value_changed = false;
+ }
+
+private:
+ tl::Variant m_value;
+ bool m_visible, m_enabled;
+ bool m_value_changed, m_visible_changed, m_enabled_changed;
+};
+
+/**
+ * @brief Represents the state of call parameters for the callback implementation
+ */
+class DB_PUBLIC ParameterStates
+{
+public:
+ /**
+ * @brief Default constructor
+ */
+ ParameterStates ()
+ : m_states ()
+ {
+ // .. nothing yet ..
+ }
+
+ /**
+ * @brief Sets a parameter from a given state
+ */
+ void set_parameter (const std::string &name, const ParameterState &ps)
+ {
+ m_states [name] = ps;
+ }
+
+ /**
+ * @brief Gets the parameter state for the parameter with the given name
+ *
+ * If the name is not a valid parameter name, the behavior is undefined.
+ */
+ ParameterState ¶meter (const std::string &name)
+ {
+ return m_states [name];
+ }
+
+ /**
+ * @brief Gets the parameter state for the parameter with the given name
+ *
+ * If the name is not a valid parameter name, the behavior is undefined.
+ */
+ const ParameterState ¶meter (const std::string &name) const
+ {
+ return const_cast (this)->parameter (name);
+ }
+
+ /**
+ * @brief Resets the modified flags
+ */
+ void reset ()
+ {
+ for (auto p = m_states.begin (); p != m_states.end (); ++p) {
+ p->second.reset ();
+ }
+ }
+
+public:
+ std::map m_states;
+};
+
/**
* @brief A declaration for a PCell
*/
@@ -374,7 +543,25 @@ public:
}
/**
- * @brief Produce a layout for the given parameter set and using the given layers.
+ * @brief Callback on parameter change
+ *
+ * This method allows implementing dynamic behavior on the change of a parameter value.
+ * A ParameterStatus object is supplied that allows changing parameter enabled status, visibility and value.
+ * The callback also acts as receiver for t_callback type parameters which only present a button.
+ *
+ * The callback function receives the name of the parameter that was changed.
+ * On some occasions, the callback is called unspecifically, for example for the initialization.
+ * In that case, the parameter name is empty.
+ *
+ * Exceptions from this implementation are ignored.
+ */
+ virtual void callback (const db::Layout & /*layout*/, const std::string & /*name*/, ParameterStates & /*states*/) const
+ {
+ // the default implementation does nothing
+ }
+
+ /**
+ * @brief Produces a layout for the given parameter set and using the given layers.
*
* A reimplementation of that method should produce the desired layout for the given parameter set.
* The layout shall be put into the given cell. This code may create cell instances to other cells
diff --git a/src/db/db/gsiDeclDbLibrary.cc b/src/db/db/gsiDeclDbLibrary.cc
index d6537599f..dd306f0cb 100644
--- a/src/db/db/gsiDeclDbLibrary.cc
+++ b/src/db/db/gsiDeclDbLibrary.cc
@@ -634,6 +634,11 @@ static unsigned int pd_type_list ()
return (unsigned int) db::PCellParameterDeclaration::t_list;
}
+static unsigned int pd_type_callback ()
+{
+ return (unsigned int) db::PCellParameterDeclaration::t_callback;
+}
+
static unsigned int pd_type_none ()
{
return (unsigned int) db::PCellParameterDeclaration::t_none;
@@ -763,7 +768,8 @@ Class decl_PCellParameterDeclaration ("db", "PCel
gsi::method ("TypeList", &pd_type_list, "@brief Type code: a list of variants") +
gsi::method ("TypeLayer", &pd_type_layer, "@brief Type code: a layer (a \\LayerInfo object)") +
gsi::method ("TypeShape", &pd_type_shape, "@brief Type code: a guiding shape (Box, Edge, Point, Polygon or Path)") +
- gsi::method ("TypeNone", &pd_type_none, "@brief Type code: unspecific type")
+ gsi::method ("TypeCallback", &pd_type_callback, "@brief Type code: a button triggering a callback") +
+ gsi::method ("TypeNone", &pd_type_none, "@brief Type code: unspecific type")
,
"@brief A PCell parameter declaration\n"
"\n"
diff --git a/src/edt/edt/edtPCellParametersPage.cc b/src/edt/edt/edtPCellParametersPage.cc
index ed28773cf..426c2becf 100644
--- a/src/edt/edt/edtPCellParametersPage.cc
+++ b/src/edt/edt/edtPCellParametersPage.cc
@@ -238,13 +238,15 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
mp_pcell_decl.reset (const_cast (pcell_decl)); // no const weak_ptr ...
mp_view = view;
m_cv_index = cv_index;
- m_parameters = parameters;
+ m_states = db::ParameterStates ();
+ m_initial_parameters.clear ();
if (mp_parameters_area) {
delete mp_parameters_area;
}
m_widgets.clear ();
+ m_all_widgets.clear ();
mp_parameters_area = new QScrollArea (this);
mp_parameters_area->setFrameShape (QFrame::NoFrame);
@@ -276,7 +278,23 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
const std::vector &pcp = pcell_decl->parameter_declarations ();
for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
- if (p->is_hidden () || p->get_type () == db::PCellParameterDeclaration::t_shape) {
+ tl::Variant value;
+ if (r < int (parameters.size ())) {
+ value = parameters [r];
+ } else {
+ value = p->get_default ();
+ }
+
+ m_initial_parameters.push_back (value);
+
+ db::ParameterState &ps = m_states.parameter (p->get_name ());
+ ps.set_value (value);
+ ps.set_enabled (! p->is_readonly ());
+ ps.set_visible (! p->is_hidden ());
+
+ m_all_widgets.push_back (std::vector ());
+
+ if (p->get_type () == db::PCellParameterDeclaration::t_shape) {
m_widgets.push_back (0);
continue;
}
@@ -324,13 +342,10 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
}
- inner_grid->addWidget (new QLabel (tl::to_qstring (description), inner_frame), row, 0);
-
- tl::Variant value;
- if (r < int (parameters.size ())) {
- value = parameters [r];
- } else {
- value = p->get_default ();
+ if (p->get_type () != db::PCellParameterDeclaration::t_callback) {
+ QLabel *l = new QLabel (tl::to_qstring (description), inner_frame);
+ inner_grid->addWidget (l, row, 0);
+ m_all_widgets.back ().push_back (l);
}
if (p->get_choices ().empty ()) {
@@ -347,7 +362,6 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
f->setFrameShape (QFrame::NoFrame);
QLineEdit *le = new QLineEdit (f);
- le->setEnabled (! p->is_readonly ());
hb->addWidget (le);
le->setMaximumWidth (150);
le->setObjectName (tl::to_qstring (p->get_name ()));
@@ -358,20 +372,36 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
ul->setText (tl::to_qstring (p->get_unit ()));
inner_grid->addWidget (f, row, 1);
+ m_all_widgets.back ().push_back (f);
connect (le, SIGNAL (editingFinished ()), this, SLOT (parameter_changed ()));
}
break;
+ case db::PCellParameterDeclaration::t_callback:
+ {
+ QPushButton *pb = new QPushButton (inner_frame);
+ pb->setObjectName (tl::to_qstring (p->get_name ()));
+ pb->setText (tl::to_qstring (description));
+ pb->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred);
+ m_widgets.push_back (pb);
+
+ inner_grid->addWidget (pb, row, 1);
+ m_all_widgets.back ().push_back (pb);
+
+ connect (pb, SIGNAL (clicked ()), this, SLOT (parameter_changed ()));
+ }
+ break;
+
case db::PCellParameterDeclaration::t_string:
case db::PCellParameterDeclaration::t_shape:
case db::PCellParameterDeclaration::t_list:
{
QLineEdit *le = new QLineEdit (inner_frame);
- le->setEnabled (! p->is_readonly ());
le->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (le);
inner_grid->addWidget (le, row, 1);
+ m_all_widgets.back ().push_back (le);
connect (le, SIGNAL (editingFinished ()), this, SLOT (parameter_changed ()));
}
@@ -380,12 +410,12 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
case db::PCellParameterDeclaration::t_layer:
{
lay::LayerSelectionComboBox *ly = new lay::LayerSelectionComboBox (inner_frame);
- ly->setEnabled (! p->is_readonly ());
ly->set_no_layer_available (true);
ly->set_view (mp_view, m_cv_index, true /*all layers*/);
ly->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (ly);
inner_grid->addWidget (ly, row, 1);
+ m_all_widgets.back ().push_back (ly);
connect (ly, SIGNAL (activated (int)), this, SLOT (parameter_changed ()));
}
@@ -396,10 +426,10 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
QCheckBox *cbx = new QCheckBox (inner_frame);
// this makes the checkbox not stretch over the full width - better when navigating with tab
cbx->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred));
- cbx->setEnabled (! p->is_readonly ());
cbx->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (cbx);
inner_grid->addWidget (cbx, row, 1);
+ m_all_widgets.back ().push_back (cbx);
connect (cbx, SIGNAL (stateChanged (int)), this, SLOT (parameter_changed ()));
}
@@ -426,16 +456,14 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
connect (cb, SIGNAL (activated (int)), this, SLOT (parameter_changed ()));
- cb->setEnabled (! p->is_readonly ());
cb->setMinimumContentsLength (30);
cb->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
m_widgets.push_back (cb);
inner_grid->addWidget (cb, row, 1);
+ m_all_widgets.back ().push_back (cb);
}
- set_value (*p, m_widgets.back (), value);
-
++row;
if (inner_frame == main_frame) {
++main_row;
@@ -443,12 +471,64 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
}
+ // initial callback
+
+ try {
+ mp_pcell_decl->callback (mp_view->cellview (m_cv_index)->layout (), std::string (), m_states);
+ } catch (tl::Exception &ex) {
+ // potentially caused by script errors in callback implementation
+ tl::error << ex.msg ();
+ } catch (std::runtime_error &ex) {
+ tl::error << ex.what ();
+ } catch (...) {
+ // ignore other errors
+ }
+
+ update_widgets_from_states (m_states);
+ m_states.reset ();
+
mp_parameters_area->setWidget (main_frame);
main_frame->show ();
update_current_parameters ();
}
+void
+PCellParametersPage::update_widgets_from_states (const db::ParameterStates &states)
+{
+ if (! mp_pcell_decl) {
+ return;
+ }
+
+ bool update_needed = false;
+
+ size_t i = 0;
+ const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
+ for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++i) {
+
+ const std::string &name = p->get_name ();
+ const db::ParameterState &ps = states.parameter (name);
+
+ if (ps.value_changed ()) {
+ update_needed = true;
+ set_value (*p, m_widgets [i], ps.value ());
+ }
+
+ if (ps.enabled_changed ()) {
+ m_widgets [i]->setEnabled (ps.is_enabled ());
+ }
+
+ if (ps.visible_changed ()) {
+ for (auto w = m_all_widgets [i].begin (); w != m_all_widgets [i].end (); ++w) {
+ (*w)->setVisible (ps.is_enabled ());
+ }
+ }
+
+ }
+
+ mp_update_frame->setVisible (update_needed);
+}
+
PCellParametersPage::State
PCellParametersPage::get_state ()
{
@@ -483,9 +563,51 @@ PCellParametersPage::set_state (const State &s)
}
}
-void
+void
PCellParametersPage::parameter_changed ()
{
+ if (! mp_pcell_decl) {
+ return;
+ }
+ if (! mp_view->cellview (m_cv_index).is_valid ()) {
+ return;
+ }
+
+ const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
+ const db::PCellParameterDeclaration *pd = 0;
+ for (auto w = m_widgets.begin (); w != m_widgets.end (); ++w) {
+ if (*w == sender ()) {
+ pd = &pcp [w - m_widgets.begin ()];
+ break;
+ }
+ }
+
+ try {
+
+ db::ParameterStates states = m_states;
+ states.reset ();
+
+ bool edit_error = false;
+ get_parameters_internal (states, edit_error);
+ if (! edit_error) {
+
+ mp_pcell_decl->callback (mp_view->cellview (m_cv_index)->layout (), pd ? pd->get_name () : std::string (), states);
+
+ update_widgets_from_states (states);
+ states.reset ();
+ m_states = states;
+
+ }
+
+ } catch (tl::Exception &ex) {
+ // potentially caused by script errors in callback implementation
+ tl::error << ex.msg ();
+ } catch (std::runtime_error &ex) {
+ tl::error << ex.what ();
+ } catch (...) {
+ // ignore other errors
+ }
+
dm_parameter_changed ();
}
@@ -493,9 +615,10 @@ void
PCellParametersPage::do_parameter_changed ()
{
// does a coerce and update
- bool ok = false;
- std::vector parameters = get_parameters (&ok);
- if (ok && ! lazy_evaluation ()) {
+ bool edit_error = false;
+ db::ParameterStates states = m_states;
+ get_parameters_internal (states, edit_error);
+ if (! edit_error && ! lazy_evaluation ()) {
emit edited ();
}
}
@@ -521,6 +644,125 @@ PCellParametersPage::update_current_parameters ()
return ok;
}
+void
+PCellParametersPage::get_parameters_internal (db::ParameterStates &states, bool &edit_error)
+{
+ edit_error = true;
+
+ int r = 0;
+ const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
+ for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
+
+ db::ParameterState &ps = states.parameter (p->get_name ());
+
+ if (! ps.is_visible () || ! ps.is_enabled () || p->get_type () == db::PCellParameterDeclaration::t_shape) {
+ continue;
+ }
+
+ if (p->get_choices ().empty ()) {
+
+ switch (p->get_type ()) {
+
+ case db::PCellParameterDeclaration::t_int:
+ {
+ QLineEdit *le = dynamic_cast (m_widgets [r]);
+ if (le) {
+
+ try {
+
+ int v = 0;
+ tl::from_string_ext (tl::to_string (le->text ()), v);
+
+ ps.set_value (tl::Variant (v));
+ lay::indicate_error (le, (tl::Exception *) 0);
+
+ } catch (tl::Exception &ex) {
+
+ lay::indicate_error (le, &ex);
+ edit_error = false;
+
+ }
+
+ }
+ }
+ break;
+
+ case db::PCellParameterDeclaration::t_double:
+ {
+ QLineEdit *le = dynamic_cast (m_widgets [r]);
+ if (le) {
+
+ try {
+
+ double v = 0;
+ tl::from_string_ext (tl::to_string (le->text ()), v);
+
+ ps.set_value (tl::Variant (v));
+ lay::indicate_error (le, (tl::Exception *) 0);
+
+ } catch (tl::Exception &ex) {
+
+ lay::indicate_error (le, &ex);
+ edit_error = false;
+
+ }
+
+ }
+ }
+ break;
+
+ case db::PCellParameterDeclaration::t_string:
+ {
+ QLineEdit *le = dynamic_cast (m_widgets [r]);
+ if (le) {
+ ps.set_value (tl::Variant (tl::to_string (le->text ())));
+ }
+ }
+ break;
+
+ case db::PCellParameterDeclaration::t_list:
+ {
+ QLineEdit *le = dynamic_cast (m_widgets [r]);
+ if (le) {
+ std::vector values = tl::split (tl::to_string (le->text ()), ",");
+ ps.set_value (tl::Variant (values.begin (), values.end ()));
+ }
+ }
+ break;
+
+ case db::PCellParameterDeclaration::t_layer:
+ {
+ lay::LayerSelectionComboBox *ly = dynamic_cast (m_widgets [r]);
+ if (ly) {
+ ps.set_value (tl::Variant (ly->current_layer_props ()));
+ }
+ }
+ break;
+ case db::PCellParameterDeclaration::t_boolean:
+ {
+ QCheckBox *cbx = dynamic_cast (m_widgets [r]);
+ if (cbx) {
+ ps.set_value (tl::Variant (cbx->isChecked ()));
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ } else {
+
+ QComboBox *cb = dynamic_cast (m_widgets [r]);
+ if (cb && cb->currentIndex () >= 0 && cb->currentIndex () < int (p->get_choices ().size ())) {
+ ps.set_value (p->get_choices () [cb->currentIndex ()]);
+ }
+
+ }
+
+ }
+}
+
std::vector
PCellParametersPage::get_parameters (bool *ok)
{
@@ -532,130 +774,17 @@ PCellParametersPage::get_parameters (bool *ok)
throw tl::Exception (tl::to_string (tr ("PCell no longer valid.")));
}
- bool edit_error = true;
+ bool edit_error = false;
+
+ db::ParameterStates states = m_states;
+ get_parameters_internal (states, edit_error);
- int r = 0;
const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
- for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
-
- if (p->is_hidden () || p->get_type () == db::PCellParameterDeclaration::t_shape) {
-
- if (r < (int) m_parameters.size ()) {
- parameters.push_back (m_parameters [r]);
- } else {
- parameters.push_back (p->get_default ());
- }
-
- } else {
-
- parameters.push_back (tl::Variant ());
-
- if (p->get_choices ().empty ()) {
-
- switch (p->get_type ()) {
-
- case db::PCellParameterDeclaration::t_int:
- {
- QLineEdit *le = dynamic_cast (m_widgets [r]);
- if (le) {
-
- try {
-
- int v = 0;
- tl::from_string_ext (tl::to_string (le->text ()), v);
-
- parameters.back () = tl::Variant (v);
- lay::indicate_error (le, (tl::Exception *) 0);
-
- } catch (tl::Exception &ex) {
-
- lay::indicate_error (le, &ex);
- edit_error = false;
-
- }
-
- }
- }
- break;
-
- case db::PCellParameterDeclaration::t_double:
- {
- QLineEdit *le = dynamic_cast (m_widgets [r]);
- if (le) {
-
- try {
-
- double v = 0;
- tl::from_string_ext (tl::to_string (le->text ()), v);
-
- parameters.back () = tl::Variant (v);
- lay::indicate_error (le, (tl::Exception *) 0);
-
- } catch (tl::Exception &ex) {
-
- lay::indicate_error (le, &ex);
- edit_error = false;
-
- }
-
- }
- }
- break;
-
- case db::PCellParameterDeclaration::t_string:
- {
- QLineEdit *le = dynamic_cast (m_widgets [r]);
- if (le) {
- parameters.back () = tl::Variant (tl::to_string (le->text ()));
- }
- }
- break;
-
- case db::PCellParameterDeclaration::t_list:
- {
- QLineEdit *le = dynamic_cast (m_widgets [r]);
- if (le) {
- std::vector values = tl::split (tl::to_string (le->text ()), ",");
- parameters.back () = tl::Variant (values.begin (), values.end ());
- }
- }
- break;
-
- case db::PCellParameterDeclaration::t_layer:
- {
- lay::LayerSelectionComboBox *ly = dynamic_cast (m_widgets [r]);
- if (ly) {
- parameters.back () = tl::Variant (ly->current_layer_props ());
- }
- }
- break;
- case db::PCellParameterDeclaration::t_boolean:
- {
- QCheckBox *cbx = dynamic_cast (m_widgets [r]);
- if (cbx) {
- parameters.back () = tl::Variant (cbx->isChecked ());
- }
- }
- break;
-
- default:
- break;
- }
-
- } else {
-
- QComboBox *cb = dynamic_cast (m_widgets [r]);
- if (cb && cb->currentIndex () >= 0 && cb->currentIndex () < int (p->get_choices ().size ())) {
- parameters.back () = p->get_choices () [cb->currentIndex ()];
- }
-
- }
-
- }
-
+ for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p) {
+ parameters.push_back (states.parameter (p->get_name ()).value ());
}
- if (! edit_error) {
+ if (edit_error) {
throw tl::Exception (tl::to_string (tr ("There are errors. See the highlighted edit fields for details.")));
}
@@ -698,7 +827,34 @@ PCellParametersPage::get_parameters (bool *ok)
void
PCellParametersPage::set_parameters (const std::vector ¶meters)
{
- m_parameters = parameters;
+ if (! mp_pcell_decl) {
+ return;
+ }
+
+ size_t r = 0;
+ const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
+ for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
+ db::ParameterState &ps = m_states.parameter (p->get_name ());
+ if (r < parameters.size ()) {
+ ps.set_value (parameters [r]);
+ } else {
+ ps.set_value (p->get_default ());
+ }
+ }
+
+ try {
+ if (mp_view->cellview (m_cv_index).is_valid ()) {
+ mp_pcell_decl->callback (mp_view->cellview (m_cv_index)->layout (), std::string (), m_states);
+ }
+ } catch (tl::Exception &ex) {
+ // potentially caused by script errors in callback implementation
+ tl::error << ex.msg ();
+ } catch (std::runtime_error &ex) {
+ tl::error << ex.what ();
+ } catch (...) {
+ // ignore other errors
+ }
+
set_parameters_internal (parameters, false);
}
diff --git a/src/edt/edt/edtPCellParametersPage.h b/src/edt/edt/edtPCellParametersPage.h
index 83eadfea1..ea21b1f94 100644
--- a/src/edt/edt/edtPCellParametersPage.h
+++ b/src/edt/edt/edtPCellParametersPage.h
@@ -103,12 +103,10 @@ public:
/**
* @brief Gets the initial parameters
- *
- * The initial parameters are the ones present on "setup".
*/
const std::vector &initial_parameters () const
{
- return m_parameters;
+ return m_initial_parameters;
}
/**
@@ -141,18 +139,21 @@ private:
QFrame *mp_error_frame, *mp_update_frame;
tl::weak_ptr mp_pcell_decl;
std::vector m_widgets;
+ std::vector > m_all_widgets;
lay::LayoutViewBase *mp_view;
int m_cv_index;
- db::pcell_parameters_type m_parameters;
bool m_dense;
tl::DeferredMethod dm_parameter_changed;
- std::vector m_current_parameters;
+ std::vector m_current_parameters, m_initial_parameters;
+ db::ParameterStates m_states;
void init ();
void do_parameter_changed ();
bool lazy_evaluation ();
void set_parameters_internal (const std::vector &values, bool tentatively);
bool update_current_parameters ();
+ void update_widgets_from_states (const db::ParameterStates &states);
+ void get_parameters_internal (db::ParameterStates &states, bool &edit_error);
};
}
From d82ff4d3f83f5e8c7bf9be75404223200d0b148c Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Fri, 28 Oct 2022 23:40:48 +0200
Subject: [PATCH 03/29] [consider merging] Fixed a problem with editing guiding
shapes
---
src/laybasic/laybasic/layObjectInstPath.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/laybasic/laybasic/layObjectInstPath.cc b/src/laybasic/laybasic/layObjectInstPath.cc
index d22f654e8..2187e9c1d 100644
--- a/src/laybasic/laybasic/layObjectInstPath.cc
+++ b/src/laybasic/laybasic/layObjectInstPath.cc
@@ -65,7 +65,7 @@ ObjectInstPath::is_valid (lay::LayoutViewBase *view) const
}
if (! is_cell_inst ()) {
- if (! ly.is_valid_layer (layer ())) {
+ if (! ly.is_valid_layer (layer ()) && layer () != ly.guiding_shape_layer ()) {
return false;
}
if (! ly.cell (ci).shapes (layer ()).is_valid (shape ())) {
From eb8c96054c528329eaf2f4c849b9747331022c50 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Fri, 28 Oct 2022 23:41:31 +0200
Subject: [PATCH 04/29] WIP: preparations for callbacks in PCell code
---
src/db/db/dbPCellDeclaration.cc | 74 ++++++++++
src/db/db/dbPCellDeclaration.h | 101 ++++----------
src/edt/edt/edtInstPropertiesPage.cc | 2 +-
src/edt/edt/edtPCellParametersPage.cc | 189 +++++++++++++++-----------
src/edt/edt/edtPCellParametersPage.h | 25 +++-
5 files changed, 233 insertions(+), 158 deletions(-)
diff --git a/src/db/db/dbPCellDeclaration.cc b/src/db/db/dbPCellDeclaration.cc
index 05ad1f4c1..acc1cafde 100644
--- a/src/db/db/dbPCellDeclaration.cc
+++ b/src/db/db/dbPCellDeclaration.cc
@@ -27,6 +27,80 @@
namespace db
{
+// -----------------------------------------------------------------------------------------
+// ParameterStates implementation
+
+ParameterStates::ParameterStates ()
+ : m_states ()
+{
+ // .. nothing yet ..
+}
+
+ParameterStates::ParameterStates (const ParameterStates &other)
+ : m_states (other.m_states)
+{
+ // .. nothing yet ..
+}
+
+ParameterStates::ParameterStates (ParameterStates &&other)
+ : m_states (std::move (other.m_states))
+{
+ // .. nothing yet ..
+}
+
+ParameterStates &
+ParameterStates::operator= (const ParameterStates &other)
+{
+ if (this != &other) {
+ m_states = other.m_states;
+ }
+ return *this;
+}
+
+void
+ParameterStates::set_parameter (const std::string &name, const ParameterState &ps)
+{
+ m_states [name] = ps;
+}
+
+ParameterState &
+ParameterStates::parameter (const std::string &name)
+{
+ return m_states [name];
+}
+
+const ParameterState &
+ParameterStates::parameter (const std::string &name) const
+{
+ auto i = m_states.find (name);
+ if (i == m_states.end ()) {
+ static ParameterState empty;
+ return empty;
+ } else {
+ return i->second;
+ }
+}
+
+bool
+ParameterStates::has_parameter (const std::string &name) const
+{
+ return m_states.find (name) != m_states.end ();
+}
+
+bool
+ParameterStates::values_are_equal (const db::ParameterStates &other) const
+{
+ auto i = m_states.begin (), j = other.m_states.begin ();
+ while (i != m_states.end () && j != other.m_states.end () && i->first == j->first && i->second.value () == j->second.value ()) {
+ ++i; ++j;
+ }
+ return i == m_states.end () && j == other.m_states.end ();
+}
+
+
+// -----------------------------------------------------------------------------------------
+// PCellDeclaration implementation
+
PCellDeclaration::PCellDeclaration ()
: m_ref_count (0), m_id (0), mp_layout (0), m_has_parameter_declarations (false)
{
diff --git a/src/db/db/dbPCellDeclaration.h b/src/db/db/dbPCellDeclaration.h
index aaecb02df..f73aa895b 100644
--- a/src/db/db/dbPCellDeclaration.h
+++ b/src/db/db/dbPCellDeclaration.h
@@ -334,8 +334,7 @@ public:
* @brief Parameterized constructor
*/
ParameterState ()
- : m_value (), m_visible (true), m_enabled (true),
- m_value_changed (false), m_visible_changed (false), m_enabled_changed (false)
+ : m_value (), m_visible (true), m_enabled (true)
{
// .. nothing yet ..
}
@@ -353,18 +352,7 @@ public:
*/
void set_value (const tl::Variant &v)
{
- if (m_value != v) {
- m_value = v;
- m_value_changed = true;
- }
- }
-
- /**
- * @brief Gets a value indicating wheter the value has changed
- */
- bool value_changed () const
- {
- return m_value_changed;
+ m_value = v;
}
/**
@@ -380,18 +368,7 @@ public:
*/
void set_visible (bool v)
{
- if (m_visible != v) {
- m_visible = v;
- m_visible_changed = true;
- }
- }
-
- /**
- * @brief Gets a value indicating wheter the visibility has changed
- */
- bool visible_changed () const
- {
- return m_visible_changed;
+ m_visible = v;
}
/**
@@ -407,32 +384,12 @@ public:
*/
void set_enabled (bool v)
{
- if (m_enabled != v) {
- m_enabled = v;
- m_enabled_changed = true;
- }
- }
-
- /**
- * @brief Gets a value indicating wheter the enabled state has changed
- */
- bool enabled_changed () const
- {
- return m_enabled_changed;
- }
-
- /**
- * @brief Resets the modified flags
- */
- void reset ()
- {
- m_enabled_changed = m_visible_changed = m_value_changed = false;
+ m_enabled = v;
}
private:
tl::Variant m_value;
bool m_visible, m_enabled;
- bool m_value_changed, m_visible_changed, m_enabled_changed;
};
/**
@@ -444,49 +401,51 @@ public:
/**
* @brief Default constructor
*/
- ParameterStates ()
- : m_states ()
- {
- // .. nothing yet ..
- }
+ ParameterStates ();
+
+ /**
+ * @brief Copy constructor
+ */
+ ParameterStates (const ParameterStates &other);
+
+ /**
+ * @brief Move constructor
+ */
+ ParameterStates (ParameterStates &&other);
+
+ /**
+ * @brief Assignment
+ */
+ ParameterStates &operator= (const ParameterStates &other);
/**
* @brief Sets a parameter from a given state
*/
- void set_parameter (const std::string &name, const ParameterState &ps)
- {
- m_states [name] = ps;
- }
+ void set_parameter (const std::string &name, const ParameterState &ps);
/**
* @brief Gets the parameter state for the parameter with the given name
*
* If the name is not a valid parameter name, the behavior is undefined.
*/
- ParameterState ¶meter (const std::string &name)
- {
- return m_states [name];
- }
+ ParameterState ¶meter (const std::string &name);
/**
* @brief Gets the parameter state for the parameter with the given name
*
* If the name is not a valid parameter name, the behavior is undefined.
*/
- const ParameterState ¶meter (const std::string &name) const
- {
- return const_cast (this)->parameter (name);
- }
+ const ParameterState ¶meter (const std::string &name) const;
/**
- * @brief Resets the modified flags
+ * @brief Gets a value indicating whether a parameter with that name is present
*/
- void reset ()
- {
- for (auto p = m_states.begin (); p != m_states.end (); ++p) {
- p->second.reset ();
- }
- }
+ bool has_parameter (const std::string &name) const;
+
+ /**
+ * @brief Returns true, if the values of the parameter states are equal
+ */
+ bool values_are_equal (const db::ParameterStates &other) const;
public:
std::map m_states;
diff --git a/src/edt/edt/edtInstPropertiesPage.cc b/src/edt/edt/edtInstPropertiesPage.cc
index ce5c0d14e..8cfdac462 100644
--- a/src/edt/edt/edtInstPropertiesPage.cc
+++ b/src/edt/edt/edtInstPropertiesPage.cc
@@ -555,7 +555,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
tl_assert (mp_pcell_parameters);
std::vector param = mp_pcell_parameters->get_parameters (0);
- const std::vector &initial_param = mp_pcell_parameters->initial_parameters ();
+ std::vector initial_param = mp_pcell_parameters->initial_parameters ();
const std::vector &pcp = mp_pcell_parameters->pcell_decl ()->parameter_declarations ();
for (std::vector::const_iterator pd = pcp.begin (); pd != pcp.end (); ++pd) {
diff --git a/src/edt/edt/edtPCellParametersPage.cc b/src/edt/edt/edtPCellParametersPage.cc
index 426c2becf..f5687abae 100644
--- a/src/edt/edt/edtPCellParametersPage.cc
+++ b/src/edt/edt/edtPCellParametersPage.cc
@@ -239,7 +239,6 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
mp_view = view;
m_cv_index = cv_index;
m_states = db::ParameterStates ();
- m_initial_parameters.clear ();
if (mp_parameters_area) {
delete mp_parameters_area;
@@ -285,8 +284,6 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
value = p->get_default ();
}
- m_initial_parameters.push_back (value);
-
db::ParameterState &ps = m_states.parameter (p->get_name ());
ps.set_value (value);
ps.set_enabled (! p->is_readonly ());
@@ -484,8 +481,8 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
// ignore other errors
}
+ m_initial_states = m_states;
update_widgets_from_states (m_states);
- m_states.reset ();
mp_parameters_area->setWidget (main_frame);
main_frame->show ();
@@ -493,42 +490,6 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
update_current_parameters ();
}
-void
-PCellParametersPage::update_widgets_from_states (const db::ParameterStates &states)
-{
- if (! mp_pcell_decl) {
- return;
- }
-
- bool update_needed = false;
-
- size_t i = 0;
- const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
- for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++i) {
-
- const std::string &name = p->get_name ();
- const db::ParameterState &ps = states.parameter (name);
-
- if (ps.value_changed ()) {
- update_needed = true;
- set_value (*p, m_widgets [i], ps.value ());
- }
-
- if (ps.enabled_changed ()) {
- m_widgets [i]->setEnabled (ps.is_enabled ());
- }
-
- if (ps.visible_changed ()) {
- for (auto w = m_all_widgets [i].begin (); w != m_all_widgets [i].end (); ++w) {
- (*w)->setVisible (ps.is_enabled ());
- }
- }
-
- }
-
- mp_update_frame->setVisible (update_needed);
-}
-
PCellParametersPage::State
PCellParametersPage::get_state ()
{
@@ -585,16 +546,17 @@ PCellParametersPage::parameter_changed ()
try {
db::ParameterStates states = m_states;
- states.reset ();
bool edit_error = false;
+ // Silent and without coerce - this will be done later in do_parameter_changed().
+ // This is just about providing the inputs for the callback.
get_parameters_internal (states, edit_error);
+
if (! edit_error) {
mp_pcell_decl->callback (mp_view->cellview (m_cv_index)->layout (), pd ? pd->get_name () : std::string (), states);
update_widgets_from_states (states);
- states.reset ();
m_states = states;
}
@@ -614,11 +576,10 @@ PCellParametersPage::parameter_changed ()
void
PCellParametersPage::do_parameter_changed ()
{
- // does a coerce and update
- bool edit_error = false;
+ bool ok = true;
db::ParameterStates states = m_states;
- get_parameters_internal (states, edit_error);
- if (! edit_error && ! lazy_evaluation ()) {
+ get_parameters (states, &ok); // includes coerce
+ if (ok && ! lazy_evaluation ()) {
emit edited ();
}
}
@@ -634,10 +595,11 @@ PCellParametersPage::update_button_pressed ()
bool
PCellParametersPage::update_current_parameters ()
{
- bool ok = false;
- std::vector parameters = get_parameters (&ok);
+ bool ok = true;
+ db::ParameterStates states = m_states;
+ get_parameters (states, &ok); // includes coerce
if (ok) {
- m_current_parameters = parameters;
+ m_current_states = states;
mp_update_frame->hide ();
}
@@ -647,7 +609,7 @@ PCellParametersPage::update_current_parameters ()
void
PCellParametersPage::get_parameters_internal (db::ParameterStates &states, bool &edit_error)
{
- edit_error = true;
+ edit_error = false;
int r = 0;
const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
@@ -679,7 +641,7 @@ PCellParametersPage::get_parameters_internal (db::ParameterStates &states, bool
} catch (tl::Exception &ex) {
lay::indicate_error (le, &ex);
- edit_error = false;
+ edit_error = true;
}
@@ -703,7 +665,7 @@ PCellParametersPage::get_parameters_internal (db::ParameterStates &states, bool
} catch (tl::Exception &ex) {
lay::indicate_error (le, &ex);
- edit_error = false;
+ edit_error = true;
}
@@ -763,11 +725,9 @@ PCellParametersPage::get_parameters_internal (db::ParameterStates &states, bool
}
}
-std::vector
-PCellParametersPage::get_parameters (bool *ok)
+void
+PCellParametersPage::get_parameters (db::ParameterStates &states, bool *ok)
{
- std::vector parameters;
-
try {
if (! mp_pcell_decl) {
@@ -776,23 +736,25 @@ PCellParametersPage::get_parameters (bool *ok)
bool edit_error = false;
- db::ParameterStates states = m_states;
get_parameters_internal (states, edit_error);
- const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
- for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p) {
- parameters.push_back (states.parameter (p->get_name ()).value ());
- }
-
if (edit_error) {
throw tl::Exception (tl::to_string (tr ("There are errors. See the highlighted edit fields for details.")));
}
- // coerce the parameters
+ // coerces the parameters and writes the changed values back
if (mp_view->cellview (m_cv_index).is_valid ()) {
+
+ auto parameters = parameter_from_states (states);
+ auto before_coerce = parameters;
mp_pcell_decl->coerce_parameters (mp_view->cellview (m_cv_index)->layout (), parameters);
+
+ if (parameters != before_coerce) {
+ states_from_parameters (states, parameters);
+ set_parameters_internal (states, lazy_evaluation ());
+ }
+
}
- set_parameters_internal (parameters, lazy_evaluation ());
if (ok) {
*ok = true;
@@ -820,8 +782,15 @@ PCellParametersPage::get_parameters (bool *ok)
}
}
+}
- return parameters;
+std::vector
+PCellParametersPage::get_parameters (bool *ok)
+{
+ db::ParameterStates states = m_states;
+ get_parameters (states, ok);
+
+ return parameter_from_states (states);
}
void
@@ -831,16 +800,7 @@ PCellParametersPage::set_parameters (const std::vector ¶meters)
return;
}
- size_t r = 0;
- const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
- for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
- db::ParameterState &ps = m_states.parameter (p->get_name ());
- if (r < parameters.size ()) {
- ps.set_value (parameters [r]);
- } else {
- ps.set_value (p->get_default ());
- }
- }
+ states_from_parameters (m_states, parameters);
try {
if (mp_view->cellview (m_cv_index).is_valid ()) {
@@ -855,11 +815,39 @@ PCellParametersPage::set_parameters (const std::vector ¶meters)
// ignore other errors
}
- set_parameters_internal (parameters, false);
+ m_initial_states = m_states;
+ set_parameters_internal (m_states, false);
}
void
-PCellParametersPage::set_parameters_internal (const std::vector ¶meters, bool tentatively)
+PCellParametersPage::update_widgets_from_states (const db::ParameterStates &states)
+{
+ if (! mp_pcell_decl) {
+ return;
+ }
+
+ size_t i = 0;
+ const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
+ for (std::vector::const_iterator p = pcp.begin (); p != pcp.end () && i < m_widgets.size (); ++p, ++i) {
+
+ const std::string &name = p->get_name ();
+ const db::ParameterState &ps = states.parameter (name);
+
+ if (m_widgets [i]) {
+ m_widgets [i]->setEnabled (ps.is_enabled ());
+ }
+
+ for (auto w = m_all_widgets [i].begin (); w != m_all_widgets [i].end (); ++w) {
+ (*w)->setVisible (ps.is_visible ());
+ }
+
+ }
+
+ set_parameters_internal (states, lazy_evaluation ());
+}
+
+void
+PCellParametersPage::set_parameters_internal (const db::ParameterStates &states, bool tentatively)
{
if (! mp_pcell_decl) {
return;
@@ -869,8 +857,8 @@ PCellParametersPage::set_parameters_internal (const std::vector &pa
size_t r = 0;
const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
- if (r < parameters.size () && m_widgets [r]) {
- set_value (*p, m_widgets [r], parameters [r]);
+ if (m_widgets [r]) {
+ set_value (*p, m_widgets [r], states.parameter (p->get_name ()).value ());
}
}
@@ -879,14 +867,53 @@ PCellParametersPage::set_parameters_internal (const std::vector &pa
bool update_needed = false;
if (! tentatively) {
- m_current_parameters = parameters;
+ m_current_states = states;
} else {
- update_needed = (m_current_parameters != parameters);
+ update_needed = ! m_current_states.values_are_equal (states);
}
mp_update_frame->setVisible (update_needed);
}
+std::vector
+PCellParametersPage::parameter_from_states (const db::ParameterStates &states) const
+{
+ std::vector parameters;
+ if (mp_pcell_decl) {
+
+ const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
+ for (auto p = pcp.begin (); p != pcp.end (); ++p) {
+ if (! states.has_parameter (p->get_name ())) {
+ parameters.push_back (p->get_default ());
+ } else {
+ parameters.push_back (states.parameter (p->get_name ()).value ());
+ }
+ }
+
+ }
+
+ return parameters;
+}
+
+void
+PCellParametersPage::states_from_parameters (db::ParameterStates &states, const std::vector ¶meters)
+{
+ if (! mp_pcell_decl) {
+ return;
+ }
+
+ size_t r = 0;
+ const std::vector &pcp = mp_pcell_decl->parameter_declarations ();
+ for (std::vector::const_iterator p = pcp.begin (); p != pcp.end (); ++p, ++r) {
+ db::ParameterState &ps = states.parameter (p->get_name ());
+ if (r < parameters.size ()) {
+ ps.set_value (parameters [r]);
+ } else {
+ ps.set_value (p->get_default ());
+ }
+ }
+}
+
}
#endif
diff --git a/src/edt/edt/edtPCellParametersPage.h b/src/edt/edt/edtPCellParametersPage.h
index ea21b1f94..ec44c1578 100644
--- a/src/edt/edt/edtPCellParametersPage.h
+++ b/src/edt/edt/edtPCellParametersPage.h
@@ -93,7 +93,7 @@ public:
void set_state (const State &s);
/**
- * @brief Get the current parameters
+ * @brief Gets the current parameters
*
* *ok is set to true, if there is no error. In case of an error it's set to false.
* The error is indicated in the error label in the editor page.
@@ -101,12 +101,25 @@ public:
*/
std::vector get_parameters (bool *ok = 0);
+ /**
+ * @brief Gets the current parameters into a ParameterStates object
+ *
+ * *ok is set to true, if there is no error. In case of an error it's set to false.
+ * The error is indicated in the error label in the editor page.
+ * If ok is null, an exception is thrown.
+ *
+ * The value fields of the ParameterState members is set to the parameter value.
+ * The other attributes are not changed. Parameters not present inside the
+ * ParameterStates object are created with their corresponding name.
+ */
+ void get_parameters (db::ParameterStates &states, bool *ok = 0);
+
/**
* @brief Gets the initial parameters
*/
- const std::vector &initial_parameters () const
+ std::vector initial_parameters () const
{
- return m_initial_parameters;
+ return parameter_from_states (m_initial_states);
}
/**
@@ -144,16 +157,18 @@ private:
int m_cv_index;
bool m_dense;
tl::DeferredMethod dm_parameter_changed;
- std::vector m_current_parameters, m_initial_parameters;
+ db::ParameterStates m_current_states, m_initial_states;
db::ParameterStates m_states;
void init ();
void do_parameter_changed ();
bool lazy_evaluation ();
- void set_parameters_internal (const std::vector &values, bool tentatively);
+ void set_parameters_internal (const db::ParameterStates &states, bool tentatively);
bool update_current_parameters ();
void update_widgets_from_states (const db::ParameterStates &states);
void get_parameters_internal (db::ParameterStates &states, bool &edit_error);
+ std::vector parameter_from_states (const db::ParameterStates &states) const;
+ void states_from_parameters (db::ParameterStates &states, const std::vector ¶meters);
};
}
From d00c4a94d61c7b42e9d40a01ebb49a800b3852db Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 29 Oct 2022 00:22:54 +0200
Subject: [PATCH 05/29] WIP: first version GSI binding for callbacks
---
src/db/db/gsiDeclDbLibrary.cc | 102 +++++++++++++++++++++++++++++++---
1 file changed, 94 insertions(+), 8 deletions(-)
diff --git a/src/db/db/gsiDeclDbLibrary.cc b/src/db/db/gsiDeclDbLibrary.cc
index dd306f0cb..38a5e0cb2 100644
--- a/src/db/db/gsiDeclDbLibrary.cc
+++ b/src/db/db/gsiDeclDbLibrary.cc
@@ -276,15 +276,16 @@ static db::pcell_parameters_type coerce_parameters_native (const db::PCellDeclar
// Provide a binding for db::PCellDeclaration for native PCell implementations
Class decl_PCellDeclaration_Native ("db", "PCellDeclaration_Native",
- gsi::method_ext ("get_layers", &get_layer_declarations_native) +
+ gsi::method_ext ("get_layers", &get_layer_declarations_native, gsi::arg ("parameters")) +
gsi::method ("get_parameters", &db::PCellDeclaration::get_parameter_declarations) +
- gsi::method ("produce", &db::PCellDeclaration::produce) +
- gsi::method_ext ("coerce_parameters", &coerce_parameters_native) +
- gsi::method ("can_create_from_shape", &db::PCellDeclaration::can_create_from_shape) +
- gsi::method ("parameters_from_shape", &db::PCellDeclaration::parameters_from_shape) +
- gsi::method ("transformation_from_shape", &db::PCellDeclaration::transformation_from_shape) +
+ gsi::method ("produce", &db::PCellDeclaration::produce, gsi::arg ("layout"), gsi::arg ("layers"), gsi::arg ("parameters"), gsi::arg ("cell")) +
+ gsi::method ("callback", &db::PCellDeclaration::callback, gsi::arg ("layout"), gsi::arg ("name"), gsi::arg ("states")) +
+ gsi::method_ext ("coerce_parameters", &coerce_parameters_native, gsi::arg ("layout"), gsi::arg ("parameters")) +
+ gsi::method ("can_create_from_shape", &db::PCellDeclaration::can_create_from_shape, gsi::arg ("layout"), gsi::arg ("shape"), gsi::arg ("layer")) +
+ gsi::method ("parameters_from_shape", &db::PCellDeclaration::parameters_from_shape, gsi::arg ("layout"), gsi::arg ("shape"), gsi::arg ("layer")) +
+ gsi::method ("transformation_from_shape", &db::PCellDeclaration::transformation_from_shape, gsi::arg ("layout"), gsi::arg ("shape"), gsi::arg ("layer")) +
gsi::method ("wants_lazy_evaluation", &db::PCellDeclaration::wants_lazy_evaluation) +
- gsi::method ("display_text", &db::PCellDeclaration::get_display_name) +
+ gsi::method ("display_text", &db::PCellDeclaration::get_display_name, gsi::arg ("parameters")) +
gsi::method ("layout", &db::PCellDeclaration::layout,
"@brief Gets the Layout object the PCell is registered in or nil if it is not registered yet.\n"
"This attribute has been added in version 0.27.5."
@@ -299,6 +300,56 @@ Class decl_PCellDeclaration_Native ("db", "PCellDeclaratio
"@hide\n@alias PCellDeclaration\n"
);
+// Provide a binding for db::ParameterState for native PCell implementations
+Class decl_PCellParameterState ("db", "PCellParameterState",
+ gsi::method("value=", &db::ParameterState::set_value, gsi::arg ("v"),
+ "@brief Sets the value of the parameter\n"
+ ) +
+ gsi::method("value", &db::ParameterState::value,
+ "@brief Gets the value of the parameter\n"
+ ) +
+ gsi::method("visible=", &db::ParameterState::set_visible, gsi::arg ("f"),
+ "@brief Sets a value indicating whether the parameter is visible in the parameter form\n"
+ ) +
+ gsi::method("is_visible?", &db::ParameterState::is_visible,
+ "@brief Gets a value indicating whether the parameter is visible in the parameter form\n"
+ ) +
+ gsi::method("enabled=", &db::ParameterState::set_enabled, gsi::arg ("f"),
+ "@brief Sets a value indicating whether the parameter is enabled in the parameter form\n"
+ ) +
+ gsi::method("is_enabled?", &db::ParameterState::is_enabled,
+ "@brief Gets a value indicating whether the parameter is enabled in the parameter form\n"
+ ),
+ "@brief Provides access to the attributes of a single parameter within \\PCellParameterStates.\n"
+ "\n"
+ "See \\PCellParameterStates for details about this feature.\n"
+ "\n"
+ "This class has been introduced in version 0.28."
+);
+
+// Provide a binding for db::ParameterStates for native PCell implementations
+Class decl_PCellParameterStates ("db", "PCellParameterStates",
+ gsi::method ("has_parameter?", &db::ParameterStates::has_parameter, gsi::arg ("name"),
+ "@brief Gets a value indicating whether a parameter with that name exists\n"
+ ) +
+ gsi::method ("parameter", static_cast (&db::ParameterStates::parameter), gsi::arg ("name"),
+ "@brief Gets the parameter by name\n"
+ "\n"
+ "This will return a \\PCellParameterState object that can be used to manipulate the "
+ "parameter state."
+ ),
+ "@brief Provides access to the parameter states inside a 'callback' implementation of a PCell\n"
+ "\n"
+ "Example: enables or disables a parameter 'n' based on the value:\n"
+ "\n"
+ "@code\n"
+ "n_param = states.parameter(\"n\")\n"
+ "n_param.enabled = n_param.value > 1.0\n"
+ "@/code\n"
+ "\n"
+ "This class has been introduced in version 0.28."
+);
+
class PCellDeclarationImpl
: public db::PCellDeclaration
{
@@ -359,6 +410,20 @@ public:
}
}
+ virtual void callback_fb (const db::Layout &layout, const std::string &name, db::ParameterStates &states) const
+ {
+ db::PCellDeclaration::callback (layout, name, states);
+ }
+
+ virtual void callback (const db::Layout &layout, const std::string &name, db::ParameterStates &states) const
+ {
+ if (cb_callback.can_issue ()) {
+ cb_callback.issue (&db::PCellDeclaration::callback, layout, name, states);
+ } else {
+ db::PCellDeclaration::callback (layout, name, states);
+ }
+ }
+
void produce_fb (const db::Layout &layout, const std::vector &layer_ids, const db::pcell_parameters_type ¶meters, db::Cell &cell) const
{
return db::PCellDeclaration::produce (layout, layer_ids, parameters, cell);
@@ -451,6 +516,7 @@ public:
gsi::Callback cb_transformation_from_shape;
gsi::Callback cb_wants_lazy_evaluation;
gsi::Callback cb_coerce_parameters;
+ gsi::Callback cb_callback;
gsi::Callback cb_get_display_name;
};
@@ -458,6 +524,7 @@ Class decl_PCellDeclaration (decl_PCellDeclaration_Native,
// fallback implementations to reroute Ruby calls to the base class:
gsi::method ("get_parameters", &PCellDeclarationImpl::get_parameter_declarations_fb, "@hide") +
gsi::method ("produce", &PCellDeclarationImpl::produce_fb, "@hide") +
+ gsi::method ("callback", &PCellDeclarationImpl::callback_fb, "@hide") +
gsi::method ("can_create_from_shape", &PCellDeclarationImpl::can_create_from_shape_fb, "@hide") +
gsi::method ("parameters_from_shape", &PCellDeclarationImpl::parameters_from_shape_fb, "@hide") +
gsi::method ("transformation_from_shape", &PCellDeclarationImpl::transformation_from_shape_fb, "@hide") +
@@ -493,6 +560,25 @@ Class decl_PCellDeclaration (decl_PCellDeclaration_Native,
"\n"
"It can raise an exception to indicate that something is not correct.\n"
) +
+ gsi::callback ("callback", &PCellDeclarationImpl::callback, &PCellDeclarationImpl::cb_callback, gsi::arg ("layout"), gsi::arg ("name"), gsi::arg ("states"),
+ "@brief Indicates a parameter change and allows implementing actions based on the parameter value\n"
+ "@param layout The layout object in which the PCell will be produced\n"
+ "@param name The name of the parameter which has changed or an empty string if all parameters need to be considered\n"
+ "@param states A \\PCellParameterStates object which can be used to manipulate the parameter states\n"
+ "This method may be reimplemented to implement parameter-specific actions upon value change or button callbacks. "
+ "Whenever the value of a parameter is changed in the PCell parameter form, this method is called with the name of the parameter "
+ "in 'name'. The implementation can manipulate values or states (enabled, visible) or parameters using the "
+ "\\PCellParameterStates object passed in 'states'.\n"
+ "\n"
+ "Initially, this method will be called with an empty parameter name to indicate a global change. The implementation "
+ "may then consolidate all states. The initial state is build from the 'readonly' (disabled) or 'hidden' (invisible) parameter "
+ "declarations.\n"
+ "\n"
+ "This method is also called when a button-type parameter is present and the button is pressed. In this case the parameter "
+ "name is the name of the button.\n"
+ "\n"
+ "This feature has been introduced in version 0.28."
+ ) +
gsi::callback ("produce", &PCellDeclarationImpl::produce, &PCellDeclarationImpl::cb_produce, gsi::arg ("layout"), gsi::arg ("layer_ids"), gsi::arg ("parameters"), gsi::arg ("cell"),
"@brief The production callback\n"
"@param layout The layout object where the cell resides\n"
@@ -768,7 +854,7 @@ Class decl_PCellParameterDeclaration ("db", "PCel
gsi::method ("TypeList", &pd_type_list, "@brief Type code: a list of variants") +
gsi::method ("TypeLayer", &pd_type_layer, "@brief Type code: a layer (a \\LayerInfo object)") +
gsi::method ("TypeShape", &pd_type_shape, "@brief Type code: a guiding shape (Box, Edge, Point, Polygon or Path)") +
- gsi::method ("TypeCallback", &pd_type_callback, "@brief Type code: a button triggering a callback") +
+ gsi::method ("TypeCallback", &pd_type_callback, "@brief Type code: a button triggering a callback\n\nThis code has been introduced in version 0.28.") +
gsi::method ("TypeNone", &pd_type_none, "@brief Type code: unspecific type")
,
"@brief A PCell parameter declaration\n"
From 0e5842d36e6316a0a6883c011375cf1fec11cbb3 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 29 Oct 2022 21:19:35 +0200
Subject: [PATCH 06/29] Fixed some qrc files, added more attributes to
PCellParameterState (tool tip, readonly, icon), added option to show
parameter names
---
src/db/db/dbPCellDeclaration.h | 64 +++++++++-
src/db/db/gsiDeclDbLibrary.cc | 42 +++++++
src/edt/edt/AlignOptionsDialog.ui | 18 +--
src/edt/edt/DistributeOptionsDialog.ui | 18 +--
src/edt/edt/EditorOptionsInst.ui | 4 +-
src/edt/edt/InstPropertiesPage.ui | 5 +-
src/edt/edt/MakeCellOptionsDialog.ui | 20 +--
src/edt/edt/edtPCellParametersPage.cc | 114 +++++++++++++++---
src/edt/edt/edtPCellParametersPage.h | 11 +-
.../lay_plugin/LEFDEFImportOptionsDialog.ui | 10 +-
.../magic/lay_plugin/MAGReaderOptionPage.ui | 10 +-
.../oasis/lay_plugin/OASISWriterOptionPage.ui | 6 +-
.../streamers/oasis/lay_plugin/lay_plugin.pro | 1 +
13 files changed, 258 insertions(+), 65 deletions(-)
diff --git a/src/db/db/dbPCellDeclaration.h b/src/db/db/dbPCellDeclaration.h
index f73aa895b..5afa58c35 100644
--- a/src/db/db/dbPCellDeclaration.h
+++ b/src/db/db/dbPCellDeclaration.h
@@ -330,11 +330,21 @@ public:
class DB_PUBLIC ParameterState
{
public:
+ /**
+ * @brief A enum describing the icon type
+ */
+ enum Icon {
+ NoIcon = 0,
+ InfoIcon = 1,
+ ErrorIcon = 2,
+ WarningIcon = 3
+ };
+
/**
* @brief Parameterized constructor
*/
ParameterState ()
- : m_value (), m_visible (true), m_enabled (true)
+ : m_value (), m_visible (true), m_enabled (true), m_readonly (false), m_icon (NoIcon)
{
// .. nothing yet ..
}
@@ -387,9 +397,59 @@ public:
m_enabled = v;
}
+ /**
+ * @brief Gets a value indicating whether the parameter is read-only
+ */
+ bool is_readonly () const
+ {
+ return m_readonly;
+ }
+
+ /**
+ * @brief Sets a value indicating whether the parameter is read-only
+ */
+ void set_readonly (bool f)
+ {
+ m_readonly = f;
+ }
+
+ /**
+ * @brief Gets the tooltip for the parameter
+ */
+ const std::string &tooltip () const
+ {
+ return m_tooltip;
+ }
+
+ /**
+ * @brief Sets the tooltip
+ */
+ void set_tooltip (const std::string &s)
+ {
+ m_tooltip = s;
+ }
+
+ /**
+ * @brief Gets the icon
+ */
+ Icon icon () const
+ {
+ return m_icon;
+ }
+
+ /**
+ * @brief Sets the icon
+ */
+ void set_icon (Icon i)
+ {
+ m_icon = i;
+ }
+
private:
tl::Variant m_value;
- bool m_visible, m_enabled;
+ bool m_visible, m_enabled, m_readonly;
+ std::string m_tooltip;
+ Icon m_icon;
};
/**
diff --git a/src/db/db/gsiDeclDbLibrary.cc b/src/db/db/gsiDeclDbLibrary.cc
index 38a5e0cb2..e2f89007b 100644
--- a/src/db/db/gsiDeclDbLibrary.cc
+++ b/src/db/db/gsiDeclDbLibrary.cc
@@ -23,6 +23,7 @@
#include "gsiDecl.h"
+#include "gsiEnums.h"
#include "dbLayout.h"
#include "dbLibrary.h"
#include "dbPCellDeclaration.h"
@@ -319,6 +320,26 @@ Class decl_PCellParameterState ("db", "PCellParameterState",
) +
gsi::method("is_enabled?", &db::ParameterState::is_enabled,
"@brief Gets a value indicating whether the parameter is enabled in the parameter form\n"
+ ) +
+ gsi::method("readonly=", &db::ParameterState::set_readonly, gsi::arg ("f"),
+ "@brief Sets a value indicating whether the parameter is made read-only (not editable) in the parameter form\n"
+ ) +
+ gsi::method("is_readonly?", &db::ParameterState::is_readonly,
+ "@brief Gets a value indicating whether the parameter is read-only (not editable) in the parameter form\n"
+ ) +
+ gsi::method("tooltip=", &db::ParameterState::set_tooltip, gsi::arg ("s"),
+ "@brief Sets the tool tip text\n"
+ "\n"
+ "The tool tip is shown when hovering over the parameter label or edit field."
+ ) +
+ gsi::method("tooltip", &db::ParameterState::tooltip,
+ "@brief Gets the tool tip text\n"
+ ) +
+ gsi::method("icon=", &db::ParameterState::set_icon, gsi::arg ("i"),
+ "@brief Sets the icon for the parameter\n"
+ ) +
+ gsi::method("tooltip", &db::ParameterState::tooltip,
+ "@brief Gets the icon for the parameter\n"
),
"@brief Provides access to the attributes of a single parameter within \\PCellParameterStates.\n"
"\n"
@@ -327,6 +348,27 @@ Class decl_PCellParameterState ("db", "PCellParameterState",
"This class has been introduced in version 0.28."
);
+gsi::EnumIn decl_PCellParameterState_Icon ("db", "ParameterStateIcon",
+ gsi::enum_const ("NoIcon", db::ParameterState::NoIcon,
+ "@brief No icon is shown for the parameter\n"
+ ) +
+ gsi::enum_const ("InfoIcon", db::ParameterState::InfoIcon,
+ "@brief A general 'information' icon is shown\n"
+ ) +
+ gsi::enum_const ("ErrorIcon", db::ParameterState::ErrorIcon,
+ "@brief An icon indicating an error is shown\n"
+ ) +
+ gsi::enum_const ("WarningIcon", db::ParameterState::WarningIcon,
+ "@brief An icon indicating a warning is shown\n"
+ ),
+ "@brief This enum specifies the icon shown next to the parameter in PCell parameter list.\n"
+ "\n"
+ "This enum was introduced in version 0.28.\n"
+);
+
+// Inject the NetlistCrossReference::Status declarations into NetlistCrossReference:
+gsi::ClassExt inject_PCellParameterState_Icon_in_parent (decl_PCellParameterState_Icon.defs ());
+
// Provide a binding for db::ParameterStates for native PCell implementations
Class decl_PCellParameterStates ("db", "PCellParameterStates",
gsi::method ("has_parameter?", &db::ParameterStates::has_parameter, gsi::arg ("name"),
diff --git a/src/edt/edt/AlignOptionsDialog.ui b/src/edt/edt/AlignOptionsDialog.ui
index c6e21d7da..d94795de2 100644
--- a/src/edt/edt/AlignOptionsDialog.ui
+++ b/src/edt/edt/AlignOptionsDialog.ui
@@ -26,7 +26,7 @@
-
+ :/align_none_32px.png:/align_none_32px.png
@@ -43,7 +43,7 @@
-
+ :/align_left_32px.png:/align_left_32px.png
@@ -60,7 +60,7 @@
-
+ :/align_hcenter_32px.png:/align_hcenter_32px.png
@@ -77,7 +77,7 @@
-
+ :/align_right_32px.png:/align_right_32px.png
@@ -204,7 +204,7 @@
-
+ :/align_none_32px.png:/align_none_32px.png
@@ -221,7 +221,7 @@
-
+ :/align_top_32px.png:/align_top_32px.png
@@ -238,7 +238,7 @@
-
+ :/align_vcenter_32px.png:/align_vcenter_32px.png
@@ -308,7 +308,7 @@
-
+ :/align_bottom_32px.png:/align_bottom_32px.png
@@ -432,7 +432,7 @@
buttonBox
-
+
diff --git a/src/edt/edt/DistributeOptionsDialog.ui b/src/edt/edt/DistributeOptionsDialog.ui
index 900a68f5f..f70b9c04a 100644
--- a/src/edt/edt/DistributeOptionsDialog.ui
+++ b/src/edt/edt/DistributeOptionsDialog.ui
@@ -278,7 +278,7 @@
-
+ :/align_none_32px.png:/align_none_32px.png
@@ -311,7 +311,7 @@
-
+ :/align_left_32px.png:/align_left_32px.png
@@ -344,7 +344,7 @@
-
+ :/align_hcenter_32px.png:/align_hcenter_32px.png
@@ -377,7 +377,7 @@
-
+ :/align_right_32px.png:/align_right_32px.png
@@ -456,7 +456,7 @@
-
+ :/align_none_32px.png:/align_none_32px.png
@@ -489,7 +489,7 @@
-
+ :/align_top_32px.png:/align_top_32px.png
@@ -522,7 +522,7 @@
-
+ :/align_vcenter_32px.png:/align_vcenter_32px.png
@@ -555,7 +555,7 @@
-
+ :/align_bottom_32px.png:/align_bottom_32px.png
@@ -676,7 +676,7 @@
buttonBox
-
+
diff --git a/src/edt/edt/EditorOptionsInst.ui b/src/edt/edt/EditorOptionsInst.ui
index bfbe93beb..86b3e2c56 100644
--- a/src/edt/edt/EditorOptionsInst.ui
+++ b/src/edt/edt/EditorOptionsInst.ui
@@ -158,7 +158,7 @@
...
-
+ :/find_16px.png:/find_16px.png
@@ -549,7 +549,7 @@
-
+
diff --git a/src/edt/edt/InstPropertiesPage.ui b/src/edt/edt/InstPropertiesPage.ui
index e022a1cd4..f389d23f1 100644
--- a/src/edt/edt/InstPropertiesPage.ui
+++ b/src/edt/edt/InstPropertiesPage.ui
@@ -59,7 +59,6 @@
Sans Serif12
- 75falsetruefalse
@@ -731,7 +730,7 @@
- :/warn_16px@2x.png
+ :/warn_16px@2x.pngQt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
@@ -899,7 +898,7 @@
inst_pb
-
+
diff --git a/src/edt/edt/MakeCellOptionsDialog.ui b/src/edt/edt/MakeCellOptionsDialog.ui
index 9fae1b2bc..e40f36a75 100644
--- a/src/edt/edt/MakeCellOptionsDialog.ui
+++ b/src/edt/edt/MakeCellOptionsDialog.ui
@@ -144,7 +144,7 @@
...
-
+ :/ct_31px.png:/ct_31px.png
@@ -164,7 +164,7 @@
...
-
+ :/lt_31px.png:/lt_31px.png
@@ -184,7 +184,7 @@
...
-
+ :/rt_31px.png:/rt_31px.png
@@ -204,7 +204,7 @@
...
-
+ :/lc_31px.png:/lc_31px.png
@@ -224,7 +224,7 @@
...
-
+ :/cc_31px.png:/cc_31px.png
@@ -244,7 +244,7 @@
...
-
+ :/rc_31px.png:/rc_31px.png
@@ -264,7 +264,7 @@
...
-
+ :/lb_31px.png:/lb_31px.png
@@ -284,7 +284,7 @@
...
-
+ :/cb_31px.png:/cb_31px.png
@@ -304,7 +304,7 @@
...
-
+ :/rb_31px.png:/rb_31px.png
@@ -366,7 +366,7 @@
-
+
diff --git a/src/edt/edt/edtPCellParametersPage.cc b/src/edt/edt/edtPCellParametersPage.cc
index f5687abae..0f505113a 100644
--- a/src/edt/edt/edtPCellParametersPage.cc
+++ b/src/edt/edt/edtPCellParametersPage.cc
@@ -149,7 +149,7 @@ static void set_value (const db::PCellParameterDeclaration &p, QWidget *widget,
}
PCellParametersPage::PCellParametersPage (QWidget *parent, bool dense)
- : QFrame (parent), m_dense (dense), dm_parameter_changed (this, &PCellParametersPage::do_parameter_changed)
+ : QFrame (parent), m_dense (dense), m_show_parameter_names (false), dm_parameter_changed (this, &PCellParametersPage::do_parameter_changed)
{
init ();
}
@@ -170,7 +170,7 @@ PCellParametersPage::init ()
frame_layout->setContentsMargins (0, 0, 0, 0);
setLayout (frame_layout);
- mp_update_frame = new QFrame ();
+ mp_update_frame = new QFrame (this);
mp_update_frame->setFrameShape (QFrame::NoFrame);
frame_layout->addWidget (mp_update_frame, 0, 0, 1, 1);
@@ -197,7 +197,7 @@ PCellParametersPage::init ()
update_frame_layout->setColumnStretch (2, 1);
- mp_error_frame = new QFrame ();
+ mp_error_frame = new QFrame (this);
mp_error_frame->setFrameShape (QFrame::NoFrame);
frame_layout->addWidget (mp_error_frame, 1, 0, 1, 1);
@@ -224,6 +224,13 @@ PCellParametersPage::init ()
error_frame_layout->addWidget (mp_error_label, 1, 1, 1, 2);
error_frame_layout->setColumnStretch (2, 1);
+
+ mp_show_parameter_names_cb = new QCheckBox (this);
+ mp_show_parameter_names_cb->setText (tr ("Show parameter names"));
+ mp_show_parameter_names_cb->setChecked (m_show_parameter_names);
+ frame_layout->addWidget (mp_show_parameter_names_cb, 3, 0, 1, 1);
+
+ connect (mp_show_parameter_names_cb, SIGNAL (clicked (bool)), this, SLOT (show_parameter_names (bool)));
}
bool
@@ -232,6 +239,18 @@ PCellParametersPage::lazy_evaluation ()
return mp_pcell_decl.get () && mp_pcell_decl->wants_lazy_evaluation ();
}
+void
+PCellParametersPage::show_parameter_names (bool f)
+{
+ if (m_show_parameter_names == f) {
+ return;
+ }
+
+ m_show_parameter_names = f;
+ mp_show_parameter_names_cb->setChecked (f);
+ setup (mp_view, m_cv_index, mp_pcell_decl.get (), get_parameters ());
+}
+
void
PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::PCellDeclaration *pcell_decl, const db::pcell_parameters_type ¶meters)
{
@@ -239,12 +258,14 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
mp_view = view;
m_cv_index = cv_index;
m_states = db::ParameterStates ();
+ m_initial_states = db::ParameterStates ();
if (mp_parameters_area) {
delete mp_parameters_area;
}
m_widgets.clear ();
+ m_icon_widgets.clear ();
m_all_widgets.clear ();
mp_parameters_area = new QScrollArea (this);
@@ -269,6 +290,12 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
QWidget *main_frame = inner_frame;
QGridLayout *main_grid = inner_grid;
+ if (! mp_pcell_decl) {
+ mp_parameters_area->setWidget (main_frame);
+ update_current_parameters ();
+ return;
+ }
+
int main_row = 0;
int row = 0;
std::string group_title;
@@ -286,13 +313,14 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
db::ParameterState &ps = m_states.parameter (p->get_name ());
ps.set_value (value);
- ps.set_enabled (! p->is_readonly ());
+ ps.set_readonly (p->is_readonly ());
ps.set_visible (! p->is_hidden ());
m_all_widgets.push_back (std::vector ());
if (p->get_type () == db::PCellParameterDeclaration::t_shape) {
m_widgets.push_back (0);
+ m_icon_widgets.push_back (0);
continue;
}
@@ -312,7 +340,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
// create a new group
QGroupBox *gb = new QGroupBox (main_frame);
gb->setTitle (tl::to_qstring (gt));
- main_grid->addWidget (gb, main_row, 0, 1, 2);
+ main_grid->addWidget (gb, main_row, 0, 1, 3);
inner_grid = new QGridLayout (gb);
if (m_dense) {
@@ -339,10 +367,28 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
}
+ QLabel *icon_label = new QLabel (QString (), inner_frame);
+ inner_grid->addWidget (icon_label, row, 0);
+ m_icon_widgets.push_back (icon_label);
+ m_all_widgets.back ().push_back (icon_label);
+
if (p->get_type () != db::PCellParameterDeclaration::t_callback) {
- QLabel *l = new QLabel (tl::to_qstring (description), inner_frame);
- inner_grid->addWidget (l, row, 0);
+
+ std::string leader;
+ if (m_show_parameter_names) {
+ leader = tl::sprintf ("[%s] ", p->get_name ());
+ }
+
+ QLabel *l = new QLabel (tl::to_qstring (leader + description), inner_frame);
+ inner_grid->addWidget (l, row, 1);
m_all_widgets.back ().push_back (l);
+
+ } else if (m_show_parameter_names) {
+
+ QLabel *l = new QLabel (tl::to_qstring (tl::sprintf ("[%s]", p->get_name ())), inner_frame);
+ inner_grid->addWidget (l, row, 1);
+ m_all_widgets.back ().push_back (l);
+
}
if (p->get_choices ().empty ()) {
@@ -368,7 +414,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
hb->addWidget (ul, 1);
ul->setText (tl::to_qstring (p->get_unit ()));
- inner_grid->addWidget (f, row, 1);
+ inner_grid->addWidget (f, row, 2);
m_all_widgets.back ().push_back (f);
connect (le, SIGNAL (editingFinished ()), this, SLOT (parameter_changed ()));
@@ -383,7 +429,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
pb->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred);
m_widgets.push_back (pb);
- inner_grid->addWidget (pb, row, 1);
+ inner_grid->addWidget (pb, row, 2);
m_all_widgets.back ().push_back (pb);
connect (pb, SIGNAL (clicked ()), this, SLOT (parameter_changed ()));
@@ -397,7 +443,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
QLineEdit *le = new QLineEdit (inner_frame);
le->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (le);
- inner_grid->addWidget (le, row, 1);
+ inner_grid->addWidget (le, row, 2);
m_all_widgets.back ().push_back (le);
connect (le, SIGNAL (editingFinished ()), this, SLOT (parameter_changed ()));
@@ -411,7 +457,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
ly->set_view (mp_view, m_cv_index, true /*all layers*/);
ly->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (ly);
- inner_grid->addWidget (ly, row, 1);
+ inner_grid->addWidget (ly, row, 2);
m_all_widgets.back ().push_back (ly);
connect (ly, SIGNAL (activated (int)), this, SLOT (parameter_changed ()));
@@ -425,7 +471,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
cbx->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred));
cbx->setObjectName (tl::to_qstring (p->get_name ()));
m_widgets.push_back (cbx);
- inner_grid->addWidget (cbx, row, 1);
+ inner_grid->addWidget (cbx, row, 2);
m_all_widgets.back ().push_back (cbx);
connect (cbx, SIGNAL (stateChanged (int)), this, SLOT (parameter_changed ()));
@@ -456,7 +502,7 @@ PCellParametersPage::setup (lay::LayoutViewBase *view, int cv_index, const db::P
cb->setMinimumContentsLength (30);
cb->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
m_widgets.push_back (cb);
- inner_grid->addWidget (cb, row, 1);
+ inner_grid->addWidget (cb, row, 2);
m_all_widgets.back ().push_back (cb);
}
@@ -499,6 +545,8 @@ PCellParametersPage::get_state ()
s.vScrollPosition = mp_parameters_area->verticalScrollBar ()->value ();
s.hScrollPosition = mp_parameters_area->horizontalScrollBar ()->value ();
+ s.show_parameter_names = m_show_parameter_names;
+
if (focusWidget ()) {
s.focusWidget = focusWidget ()->objectName ();
}
@@ -514,6 +562,10 @@ PCellParametersPage::set_state (const State &s)
mp_parameters_area->verticalScrollBar ()->setValue (s.vScrollPosition);
mp_parameters_area->horizontalScrollBar ()->setValue (s.hScrollPosition);
+ if (s.show_parameter_names != m_show_parameter_names) {
+ show_parameter_names (s.show_parameter_names);
+ }
+
if (! s.focusWidget.isEmpty ()) {
QWidget *c = findChild (s.focusWidget);
if (c) {
@@ -617,7 +669,7 @@ PCellParametersPage::get_parameters_internal (db::ParameterStates &states, bool
db::ParameterState &ps = states.parameter (p->get_name ());
- if (! ps.is_visible () || ! ps.is_enabled () || p->get_type () == db::PCellParameterDeclaration::t_shape) {
+ if (! ps.is_visible () || ! ps.is_enabled () || ps.is_readonly () || p->get_type () == db::PCellParameterDeclaration::t_shape) {
continue;
}
@@ -834,11 +886,43 @@ PCellParametersPage::update_widgets_from_states (const db::ParameterStates &stat
const db::ParameterState &ps = states.parameter (name);
if (m_widgets [i]) {
- m_widgets [i]->setEnabled (ps.is_enabled ());
+ m_widgets [i]->setEnabled (ps.is_enabled () && ! ps.is_readonly ());
}
for (auto w = m_all_widgets [i].begin (); w != m_all_widgets [i].end (); ++w) {
+ if (*w != m_widgets [i]) {
+ (*w)->setEnabled (ps.is_enabled ());
+ }
(*w)->setVisible (ps.is_visible ());
+ (*w)->setToolTip (tl::to_qstring (ps.tooltip ()));
+ }
+
+ if (m_icon_widgets [i]) {
+
+ static QPixmap error (":/error_16px@2x.png");
+ static QPixmap info (":/info_16px@2x.png");
+ static QPixmap warning (":/warn_16px@2x.png");
+
+ switch (ps.icon ()) {
+ case db::ParameterState::NoIcon:
+ default:
+ m_icon_widgets [i]->setPixmap (QPixmap ());
+ m_icon_widgets [i]->hide ();
+ break;
+ case db::ParameterState::InfoIcon:
+ m_icon_widgets [i]->setPixmap (info);
+ m_icon_widgets [i]->show ();
+ break;
+ case db::ParameterState::WarningIcon:
+ m_icon_widgets [i]->setPixmap (warning);
+ m_icon_widgets [i]->show ();
+ break;
+ case db::ParameterState::ErrorIcon:
+ m_icon_widgets [i]->setPixmap (error);
+ m_icon_widgets [i]->show ();
+ break;
+ }
+
}
}
diff --git a/src/edt/edt/edtPCellParametersPage.h b/src/edt/edt/edtPCellParametersPage.h
index ec44c1578..05462eb02 100644
--- a/src/edt/edt/edtPCellParametersPage.h
+++ b/src/edt/edt/edtPCellParametersPage.h
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
namespace lay
{
@@ -52,9 +53,10 @@ Q_OBJECT
public:
struct State
{
- State () : valid (false), hScrollPosition (0), vScrollPosition (0) { }
+ State () : valid (false), show_parameter_names (false), hScrollPosition (0), vScrollPosition (0) { }
bool valid;
+ bool show_parameter_names;
int hScrollPosition;
int vScrollPosition;
QString focusWidget;
@@ -138,6 +140,9 @@ public:
signals:
void edited ();
+public slots:
+ void show_parameter_names (bool f);
+
private slots:
void parameter_changed ();
void update_button_pressed ();
@@ -150,12 +155,14 @@ private:
QLabel *mp_changed_icon;
QToolButton *mp_update_button;
QFrame *mp_error_frame, *mp_update_frame;
+ QCheckBox *mp_show_parameter_names_cb;
tl::weak_ptr mp_pcell_decl;
std::vector m_widgets;
+ std::vector m_icon_widgets;
std::vector > m_all_widgets;
lay::LayoutViewBase *mp_view;
int m_cv_index;
- bool m_dense;
+ bool m_dense, m_show_parameter_names;
tl::DeferredMethod dm_parameter_changed;
db::ParameterStates m_current_states, m_initial_states;
db::ParameterStates m_states;
diff --git a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFImportOptionsDialog.ui b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFImportOptionsDialog.ui
index dbb3e9401..f14df467b 100644
--- a/src/plugins/streamers/lefdef/lay_plugin/LEFDEFImportOptionsDialog.ui
+++ b/src/plugins/streamers/lefdef/lay_plugin/LEFDEFImportOptionsDialog.ui
@@ -190,7 +190,7 @@
...
-
+ :/clear_16px.png:/clear_16px.png
@@ -204,7 +204,7 @@
...
-
+ :/add_16px.png:/add_16px.png
@@ -218,7 +218,7 @@
...
-
+ :/up_16px.png:/up_16px.png
@@ -232,7 +232,7 @@
...
-
+ :/down_16px.png:/down_16px.png
@@ -298,7 +298,7 @@
buttonBox
-
+
diff --git a/src/plugins/streamers/magic/lay_plugin/MAGReaderOptionPage.ui b/src/plugins/streamers/magic/lay_plugin/MAGReaderOptionPage.ui
index 4dd76f3b7..107165a8e 100644
--- a/src/plugins/streamers/magic/lay_plugin/MAGReaderOptionPage.ui
+++ b/src/plugins/streamers/magic/lay_plugin/MAGReaderOptionPage.ui
@@ -147,7 +147,7 @@
...
-
+ :/clear_16px.png:/clear_16px.png
@@ -161,7 +161,7 @@
...
-
+ :/down_16px.png:/down_16px.png
@@ -175,7 +175,7 @@
...
-
+ :/add_16px.png:/add_16px.png
@@ -197,7 +197,7 @@ You can use expressions inside the path components for variable paths
...
-
+ :/up_16px.png:/up_16px.png
@@ -315,7 +315,7 @@ You can use expressions inside the path components for variable paths
read_all_cbx
-
+
diff --git a/src/plugins/streamers/oasis/lay_plugin/OASISWriterOptionPage.ui b/src/plugins/streamers/oasis/lay_plugin/OASISWriterOptionPage.ui
index 995fbd702..78110075f 100644
--- a/src/plugins/streamers/oasis/lay_plugin/OASISWriterOptionPage.ui
+++ b/src/plugins/streamers/oasis/lay_plugin/OASISWriterOptionPage.ui
@@ -284,7 +284,7 @@
- :/warn_16px@2x.png
+ :/warn_16px@2x.png
@@ -379,7 +379,7 @@
- :/warn_16px@2x.png
+ :/warn_16px@2x.png
@@ -430,7 +430,7 @@
subst_char
-
+
diff --git a/src/plugins/streamers/oasis/lay_plugin/lay_plugin.pro b/src/plugins/streamers/oasis/lay_plugin/lay_plugin.pro
index 666291b59..4ca7fd7d4 100644
--- a/src/plugins/streamers/oasis/lay_plugin/lay_plugin.pro
+++ b/src/plugins/streamers/oasis/lay_plugin/lay_plugin.pro
@@ -22,3 +22,4 @@ SOURCES = \
FORMS = \
OASISWriterOptionPage.ui \
+
From 194a6f3526514161e1fe4503be7c055bc96a199f Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 29 Oct 2022 22:38:33 +0200
Subject: [PATCH 07/29] Added callback helper for Ruby PCellDeclarationHelper
---
.../pcell_declaration_helper.lym | 178 +++++++++++++++---
1 file changed, 151 insertions(+), 27 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 115f3fdee..3e0d9419a 100644
--- a/src/db/db/built-in-macros/pcell_declaration_helper.lym
+++ b/src/db/db/built-in-macros/pcell_declaration_helper.lym
@@ -157,6 +157,53 @@ It is supposed to adjust parameters to render a consistent parameter set and to
parameter range errors. This method is called for example inside the PCell user interface to
compute the actual parameters when "Apply" is pressed.
+@method callback_impl(name)
+
+@brief Provides a callback on a parameter change
+
+This method applies to user interface changes only. Whenever a parameter is changed
+on the parameter page, this method is called with the name of the parameter.
+
+On some occasions, this method called to establish a configuration unspecifically.
+In this case, the name is an empty string - indicating "all parameters may have changed".
+
+This method can change the state of this or any other parameter. For this, the
+state objects are supplied instead of the parameter values. For example to enable
+parameter "b" when a boolean parameter "a" is true, use the following code:
+
+@code
+def callback_impl(name)
+ if name == "a" || name == ""
+ b.enabled = a.value
+ end
+end
+@/code
+
+The "enabled" attribute of the \\PCellParameterState object indicates whether the
+parameter is enabled in the user interface. "a.value" delivers the value of the
+(boolean type assumed) parameter "a".
+
+Note that the above code also checks for empty name to consider the case of a
+global refresh.
+
+Further useful attributes of the parameters are:
+
+@ul
+ @li
+ @b enabled @/b: the parameter entry is grayed out if false
+ @/li
+ @li
+ @b readonly @/b: the parameter cannot be edited (less strict than enabled)
+ @/li
+ @li
+ @b visible @/b: the parameter entry is not visible if false
+ @/li
+ @li
+ @b icon @/b: Sets an icon in front of the parameter indicating an error or a
+ warning (use \\PCellParameterState#WarningIcon or \\PCellParameterState#ErrorIcon).
+ @/li
+@/ul
+
@method can_create_from_shape_impl
@brief Returns true if the PCell can be created from the given shape
@@ -227,12 +274,13 @@ module RBA
def initialize
@param_decls = []
@param_values = nil
+ @param_states = nil
@layout = nil
@shape = nil
@layer = nil
@cell = nil
@layer_param_index = []
- @layers = []
+ @layers = nil
end
# provide accessors for the current layout and cell (for prod)
@@ -244,6 +292,43 @@ module RBA
def _layout; @layout; end
def _cell; @cell; end
def _shape; @shape; end
+
+ # A helper method to access the nth parameter
+
+ def _param(nth)
+ if @param_states
+ if @param_states.size <= nth
+ return RBA::PCellParameterState::new
+ else
+ return @param_states[nth]
+ end
+ else
+ @param_values || raise("No parameters available.")
+ while @param_values.size <= nth
+ @param_values << nil
+ end
+ return @param_values[nth]
+ end
+ end
+
+ # A helper method to set the nth parameter
+
+ def _set_param(nth, value)
+ @param_values || raise("Cannot set parameter - inside 'callback_impl' use 'param_name.value = ...' to set the parameter's value.")
+ if @param_values.size > nth
+ @param_values[nth] = value
+ end
+ end
+
+ # A helper method to access the nth layer
+
+ def _layer(nth)
+ @layers || raise("No layer index available - layers can be used only inside 'produce_impl'.")
+ while @param_values.size <= nth
+ @param_values << nil
+ end
+ @param_values[nth]
+ end
# define a parameter
# name -> the short name of the parameter
@@ -270,11 +355,11 @@ module RBA
# create accessor methods for the parameters
param_index = @param_decls.length
- self.instance_eval("def #{name.to_s}; @param_values[#{param_index}]; end")
- self.instance_eval("def set_#{name.to_s}(v); @param_values[#{param_index}] = v; end")
- self.instance_eval("def #{name.to_s}=(v); @param_values[#{param_index}] = v; end")
+ self.instance_eval("def #{name.to_s}; self._param(#{param_index}); end")
+ self.instance_eval("def set_#{name.to_s}(v); self._set_param(#{param_index}, v); end")
+ self.instance_eval("def #{name.to_s}=(v); self._set_param(#{param_index}, v); end")
if type == TypeLayer
- self.instance_eval("def #{name.to_s}_layer; @layers[#{@layer_param_index.length}]; end")
+ self.instance_eval("def #{name.to_s}_layer; self._layer(#{@layer_param_index.length}); end")
@layer_param_index.push(param_index)
end
@@ -307,8 +392,11 @@ module RBA
# implementation of display_text
def display_text(parameters)
@param_values = parameters
- text = display_text_impl
- @param_values = nil
+ begin
+ text = display_text_impl
+ ensure
+ @param_values = nil
+ end
text
end
@@ -326,9 +414,28 @@ module RBA
def coerce_parameters(layout, parameters)
@param_values = parameters
@layout = layout
- coerce_parameters_impl
- @layout = nil
- @param_values
+ ret = parameters
+ begin
+ coerce_parameters_impl
+ ensure
+ @layout = nil
+ ret = @param_values
+ @param_values = nil
+ end
+ ret
+ end
+
+ # parameter change callback
+ def callback(layout, name, states)
+ @param_values = nil
+ @param_states = states
+ @layout = layout
+ begin
+ callback_impl(name)
+ ensure
+ @param_states = nil
+ @layout = nil
+ end
end
# produce the layout
@@ -337,22 +444,29 @@ module RBA
@cell = cell
@param_values = parameters
@layout = layout
- produce_impl
- @layers = nil
- @cell = nil
- @param_values = nil
- @layout = nil
+ begin
+ produce_impl
+ ensure
+ @layers = nil
+ @cell = nil
+ @param_values = nil
+ @layout = nil
+ end
end
# produce a helper for can_create_from_shape
def can_create_from_shape(layout, shape, layer)
+ ret = false
@layout = layout
@shape = shape
@layer = layer
- ret = can_create_from_shape_impl
- @layout = nil
- @shape = nil
- @layer = nil
+ begin
+ ret = can_create_from_shape_impl
+ ensure
+ @layout = nil
+ @shape = nil
+ @layer = nil
+ end
ret
end
@@ -361,10 +475,13 @@ module RBA
@layout = layout
@shape = shape
@layer = layer
- t = transformation_from_shape_impl
- @layout = nil
- @shape = nil
- @layer = nil
+ begin
+ t = transformation_from_shape_impl
+ ensure
+ @layout = nil
+ @shape = nil
+ @layer = nil
+ end
t
end
@@ -375,10 +492,13 @@ module RBA
@layout = layout
@shape = shape
@layer = layer
- parameters_from_shape_impl
- @layout = nil
- @shape = nil
- @layer = nil
+ begin
+ parameters_from_shape_impl
+ ensure
+ @layout = nil
+ @shape = nil
+ @layer = nil
+ end
@param_values
end
@@ -391,6 +511,10 @@ module RBA
def coerce_parameters_impl
end
+ # default implementation
+ def callback_impl(name)
+ end
+
# default implementation
def produce_impl
end
From 1b666e1cc8eb4fe07cf412f31003e9b5bf2f71ed Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sat, 29 Oct 2022 23:43:56 +0200
Subject: [PATCH 08/29] Bug fixes.
---
.../db/built-in-macros/pcell_declaration_helper.lym | 13 +++++--------
1 file changed, 5 insertions(+), 8 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 3e0d9419a..229c3b651 100644
--- a/src/db/db/built-in-macros/pcell_declaration_helper.lym
+++ b/src/db/db/built-in-macros/pcell_declaration_helper.lym
@@ -295,7 +295,7 @@ module RBA
# A helper method to access the nth parameter
- def _param(nth)
+ def _get_param(nth)
if @param_states
if @param_states.size <= nth
return RBA::PCellParameterState::new
@@ -322,12 +322,9 @@ module RBA
# A helper method to access the nth layer
- def _layer(nth)
+ def _get_layer(nth)
@layers || raise("No layer index available - layers can be used only inside 'produce_impl'.")
- while @param_values.size <= nth
- @param_values << nil
- end
- @param_values[nth]
+ @layers[nth]
end
# define a parameter
@@ -355,11 +352,11 @@ module RBA
# create accessor methods for the parameters
param_index = @param_decls.length
- self.instance_eval("def #{name.to_s}; self._param(#{param_index}); end")
+ self.instance_eval("def #{name.to_s}; self._get_param(#{param_index}); end")
self.instance_eval("def set_#{name.to_s}(v); self._set_param(#{param_index}, v); end")
self.instance_eval("def #{name.to_s}=(v); self._set_param(#{param_index}, v); end")
if type == TypeLayer
- self.instance_eval("def #{name.to_s}_layer; self._layer(#{@layer_param_index.length}); end")
+ self.instance_eval("def #{name.to_s}_layer; self._get_layer(#{@layer_param_index.length}); end")
@layer_param_index.push(param_index)
end
From 8aa135b964b1f94dce83c2344b1018b48503b8db Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 30 Oct 2022 00:15:48 +0200
Subject: [PATCH 09/29] Python implementation of PCell helper with callback
---
.../pcell_declaration_helper.lym | 136 ++++++++++++++----
1 file changed, 108 insertions(+), 28 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 3632806fd..1df6dcb53 100644
--- a/src/db/db/built-in-pymacros/pcell_declaration_helper.lym
+++ b/src/db/db/built-in-pymacros/pcell_declaration_helper.lym
@@ -162,6 +162,51 @@ It is supposed to adjust parameters to render a consistent parameter set and to
parameter range errors. This method is called for example inside the PCell user interface to
compute the actual parameters when "Apply" is pressed.
+@method callback_impl(name)
+
+@brief Provides a callback on a parameter change
+
+This method applies to user interface changes only. Whenever a parameter is changed
+on the parameter page, this method is called with the name of the parameter.
+
+On some occasions, this method called to establish a configuration unspecifically.
+In this case, the name is an empty string - indicating "all parameters may have changed".
+
+This method can change the state of this or any other parameter. For this, the
+state objects are supplied instead of the parameter values. For example to enable
+parameter "b" when a boolean parameter "a" is true, use the following code:
+
+@code
+def callback_impl(self, name):
+ if name == "a" or name == "":
+ b.enabled = a.value
+@/code
+
+The "enabled" attribute of the \\PCellParameterState object indicates whether the
+parameter is enabled in the user interface. "a.value" delivers the value of the
+(boolean type assumed) parameter "a".
+
+Note that the above code also checks for empty name to consider the case of a
+global refresh.
+
+Further useful attributes of the parameters are:
+
+@ul
+ @li
+ @b enabled @/b: the parameter entry is grayed out if false
+ @/li
+ @li
+ @b readonly @/b: the parameter cannot be edited (less strict than enabled)
+ @/li
+ @li
+ @b visible @/b: the parameter entry is not visible if false
+ @/li
+ @li
+ @b icon @/b: Sets an icon in front of the parameter indicating an error or a
+ warning (use \\PCellParameterState#WarningIcon or \\PCellParameterState#ErrorIcon).
+ @/li
+@/ul
+
@method can_create_from_shape_impl
@brief Returns true if the PCell can be created from the given shape
@@ -232,13 +277,16 @@ class _PCellDeclarationHelperParameterDescriptor(object):
the descriptor acts as a value holder (self.value)
"""
- def __init__(self, param_index):
+ def __init__(self, param_index, param_name):
self.param_index = param_index
+ self.param_name = param_name
self.value = None
def __get__(self, obj, type = None):
if obj._param_values:
return obj._param_values[self.param_index]
+ elif obj._param_states:
+ return obj._param_states.parameter(self.param_name)
else:
return self.value
@@ -261,6 +309,7 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
# "private" attributes
self._param_decls = []
self._param_values = None
+ self._param_states = None
self._layer_param_index = []
self._layers = []
# public attributes
@@ -290,7 +339,7 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
# create accessor methods for the parameters
param_index = len(self._param_decls)
- setattr(type(self), name, _PCellDeclarationHelperParameterDescriptor(param_index))
+ setattr(type(self), name, _PCellDeclarationHelperParameterDescriptor(param_index, name))
if value_type == type(self).TypeLayer:
setattr(type(self), name + "_layer", _PCellDeclarationHelperLayerDescriptor(len(self._layer_param_index)))
@@ -323,8 +372,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
implementation of display_text
"""
self._param_values = parameters
- text = self.display_text_impl()
- self._param_values = None
+ try:
+ text = self.display_text_impl()
+ finally:
+ self._param_values = None
return text
def get_parameters(self):
@@ -341,7 +392,7 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self._param_values = None
return v
- def init_values(self, values = None, layers = None):
+ def init_values(self, values = None, layers = None, states = None):
"""
initializes the temporary parameter values
"values" are the original values. If "None" is given, the
@@ -349,7 +400,11 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
"layers" are the layer indexes corresponding to the layer
parameters.
"""
- if not values:
+ self._param_values = None
+ self._param_states = None
+ if states:
+ self._param_states = states
+ elif not values:
self._param_values = []
for pd in self._param_decls:
self._param_values.append(pd.default)
@@ -359,29 +414,48 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
def finish(self):
"""
- Needs to be called at the end of produce() after init_values was used
+ Needs to be called at the end of an implementation
"""
self._param_values = None
+ self._param_states = None
self._layers = None
+ self._cell = None
+ self._layout = None
+ self._layer = None
+ self._shape = None
def get_layers(self, parameters):
"""
- get the layer definitions
+ gets the layer definitions
"""
layers = []
for i in self._layer_param_index:
layers.append(parameters[i])
return layers
+ def callback(self, layout, name, states):
+ """
+ callback (change state on parameter change)
+ """
+ self.init_values(states = states)
+ self.layout = layout
+ try:
+ self.callback_impl(name)
+ finally:
+ self.finish()
+
def coerce_parameters(self, layout, parameters):
"""
coerce parameters (make consistent)
"""
self.init_values(parameters)
self.layout = layout
- self.coerce_parameters_impl()
- self.layout = None
- return self.get_values()
+ try:
+ self.coerce_parameters_impl()
+ parameters = self.get_values()
+ finally:
+ self.finish()
+ return parameters
def produce(self, layout, layers, parameters, cell):
"""
@@ -390,10 +464,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self.init_values(parameters, layers)
self.cell = cell
self.layout = layout
- self.produce_impl()
- self.cell = None
- self.layout = None
- self.finish()
+ try:
+ self.produce_impl()
+ finally:
+ self.finish()
def can_create_from_shape(self, layout, shape, layer):
"""
@@ -402,10 +476,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self.layout = layout
self.shape = shape
self.layer = layer
- ret = self.can_create_from_shape_impl()
- self.layout = None
- self.shape = None
- self.layer = None
+ try:
+ ret = self.can_create_from_shape_impl()
+ finally:
+ self.finish()
return ret
def transformation_from_shape(self, layout, shape, layer):
@@ -415,10 +489,10 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self.layout = layout
self.shape = shape
self.layer = layer
- t = self.transformation_from_shape_impl()
- self.layout = None
- self.shape = None
- self.layer = None
+ try:
+ t = self.transformation_from_shape_impl()
+ finally:
+ self.finish()
return t
def parameters_from_shape(self, layout, shape, layer):
@@ -430,11 +504,11 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
self.layout = layout
self.shape = shape
self.layer = layer
- self.parameters_from_shape_impl()
- param = self.get_values()
- self.layout = None
- self.shape = None
- self.layer = None
+ try:
+ self.parameters_from_shape_impl()
+ param = self.get_values()
+ finally:
+ self.finish()
return param
def display_text_impl(self):
@@ -449,6 +523,12 @@ class _PCellDeclarationHelper(pya.PCellDeclaration):
"""
pass
+ def callback_impl(self, name):
+ """
+ default implementation
+ """
+ pass
+
def produce_impl(self):
"""
default implementation
From b1b51d3152acb58c6279b9b7003bc8f70c9c8f46 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 30 Oct 2022 00:23:32 +0200
Subject: [PATCH 10/29] Bug fix Ruby PCell declaration helper - needs testing
---
src/db/db/built-in-macros/pcell_declaration_helper.lym | 10 +++++++---
1 file changed, 7 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 229c3b651..f37f64344 100644
--- a/src/db/db/built-in-macros/pcell_declaration_helper.lym
+++ b/src/db/db/built-in-macros/pcell_declaration_helper.lym
@@ -295,12 +295,12 @@ module RBA
# A helper method to access the nth parameter
- def _get_param(nth)
+ def _get_param(nth, name)
if @param_states
if @param_states.size <= nth
return RBA::PCellParameterState::new
else
- return @param_states[nth]
+ return @param_states.parameter(name)
end
else
@param_values || raise("No parameters available.")
@@ -349,10 +349,14 @@ module RBA
# param_{name}_layer
def param(name, type, description, args = {})
+
+ if name !~ /^[_A-Za-z]\w*$/
+ raise "Invalid parameter name #{name} (needs to be a word)"
+ end
# create accessor methods for the parameters
param_index = @param_decls.length
- self.instance_eval("def #{name.to_s}; self._get_param(#{param_index}); end")
+ self.instance_eval("def #{name.to_s}; self._get_param(#{param_index}, '#{name}'); end")
self.instance_eval("def set_#{name.to_s}(v); self._set_param(#{param_index}, v); end")
self.instance_eval("def #{name.to_s}=(v); self._set_param(#{param_index}, v); end")
if type == TypeLayer
From 548db003ed7d97850832b09714ad76b00fead0b2 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 30 Oct 2022 10:00:51 +0100
Subject: [PATCH 11/29] Debugged Ruby PCellDeclarationHelper, small
enhancements
---
src/db/db/built-in-macros/pcell_declaration_helper.lym | 2 +-
src/edt/edt/edtPCellParametersPage.cc | 9 ++++-----
2 files changed, 5 insertions(+), 6 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 f37f64344..30023a97a 100644
--- a/src/db/db/built-in-macros/pcell_declaration_helper.lym
+++ b/src/db/db/built-in-macros/pcell_declaration_helper.lym
@@ -297,7 +297,7 @@ module RBA
def _get_param(nth, name)
if @param_states
- if @param_states.size <= nth
+ if ! @param_states.has_parameter?(name)
return RBA::PCellParameterState::new
else
return @param_states.parameter(name)
diff --git a/src/edt/edt/edtPCellParametersPage.cc b/src/edt/edt/edtPCellParametersPage.cc
index 0f505113a..043034b75 100644
--- a/src/edt/edt/edtPCellParametersPage.cc
+++ b/src/edt/edt/edtPCellParametersPage.cc
@@ -605,12 +605,8 @@ PCellParametersPage::parameter_changed ()
get_parameters_internal (states, edit_error);
if (! edit_error) {
-
mp_pcell_decl->callback (mp_view->cellview (m_cv_index)->layout (), pd ? pd->get_name () : std::string (), states);
-
- update_widgets_from_states (states);
m_states = states;
-
}
} catch (tl::Exception &ex) {
@@ -631,6 +627,7 @@ PCellParametersPage::do_parameter_changed ()
bool ok = true;
db::ParameterStates states = m_states;
get_parameters (states, &ok); // includes coerce
+ update_widgets_from_states (states);
if (ok && ! lazy_evaluation ()) {
emit edited ();
}
@@ -893,7 +890,9 @@ PCellParametersPage::update_widgets_from_states (const db::ParameterStates &stat
if (*w != m_widgets [i]) {
(*w)->setEnabled (ps.is_enabled ());
}
- (*w)->setVisible (ps.is_visible ());
+ if (*w != m_icon_widgets [i]) {
+ (*w)->setVisible (ps.is_visible ());
+ }
(*w)->setToolTip (tl::to_qstring (ps.tooltip ()));
}
From 2dc5c98416d6907514f4f75355d9ea5c2aec562e Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Tue, 1 Nov 2022 13:46:36 +0100
Subject: [PATCH 12/29] Implemented readonly for PCell line-edit parameters as
QLineEdit::readOnly
---
src/edt/edt/edtPCellParametersPage.cc | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/edt/edt/edtPCellParametersPage.cc b/src/edt/edt/edtPCellParametersPage.cc
index 043034b75..e7e72f0c6 100644
--- a/src/edt/edt/edtPCellParametersPage.cc
+++ b/src/edt/edt/edtPCellParametersPage.cc
@@ -883,7 +883,13 @@ PCellParametersPage::update_widgets_from_states (const db::ParameterStates &stat
const db::ParameterState &ps = states.parameter (name);
if (m_widgets [i]) {
- m_widgets [i]->setEnabled (ps.is_enabled () && ! ps.is_readonly ());
+ QLineEdit *le = dynamic_cast (m_widgets [i]);
+ if (le) {
+ le->setEnabled (ps.is_enabled ());
+ le->setReadOnly (ps.is_readonly ());
+ } else {
+ m_widgets [i]->setEnabled (ps.is_enabled () && ! ps.is_readonly ());
+ }
}
for (auto w = m_all_widgets [i].begin (); w != m_all_widgets [i].end (); ++w) {
From 54833db00b098cdec696bb2d5bea22c5bee01598 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Tue, 1 Nov 2022 13:46:48 +0100
Subject: [PATCH 13/29] Added feature for computing area and perimeter from
selection
---
src/edt/edt/AreaAndPerimeterDialog.ui | 130 ++++++++++++++++++++++++++
src/edt/edt/edt.pro | 3 +-
src/edt/edt/edtDialogs.cc | 23 +++++
src/edt/edt/edtDialogs.h | 17 ++++
src/edt/edt/edtMainService.cc | 78 +++++++++++++++-
src/edt/edt/edtMainService.h | 8 ++
src/edt/edt/edtPlugin.cc | 2 +
7 files changed, 258 insertions(+), 3 deletions(-)
create mode 100644 src/edt/edt/AreaAndPerimeterDialog.ui
diff --git a/src/edt/edt/AreaAndPerimeterDialog.ui b/src/edt/edt/AreaAndPerimeterDialog.ui
new file mode 100644
index 000000000..9fd1a263a
--- /dev/null
+++ b/src/edt/edt/AreaAndPerimeterDialog.ui
@@ -0,0 +1,130 @@
+
+
+ AreaAndPerimeterDialog
+
+
+
+ 0
+ 0
+ 367
+ 205
+
+
+
+ Area And Perimeter
+
+
+
+
+
+ Qt::Vertical
+
+
+
+ 10
+ 11
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+ Area
+
+
+
+
+
+
+ µm
+
+
+
+
+
+
+ µm²
+
+
+
+
+
+
+ Perimeter
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Ok
+
+
+
+
+
+
+ Note: area and perimeter are computed in "merged mode". This means, overlapping shapes are counted once for area calculation.
+The perimeter calculation only takes true outside edges into account. Internal edges are ignored.
+
+
+ true
+
+
+
+
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 5
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ AreaAndPerimeterDialog
+ accept()
+
+
+ 303
+ 185
+
+
+ 311
+ 201
+
+
+
+
+
diff --git a/src/edt/edt/edt.pro b/src/edt/edt/edt.pro
index 24075ca3b..7680a9946 100644
--- a/src/edt/edt/edt.pro
+++ b/src/edt/edt/edt.pro
@@ -27,7 +27,8 @@ DEFINES += MAKE_EDT_LIBRARY
RoundCornerOptionsDialog.ui \
TextPropertiesPage.ui \
DistributeOptionsDialog.ui \
- EditorOptionsInstPCellParam.ui
+ EditorOptionsInstPCellParam.ui \
+ AreaAndPerimeterDialog.ui
}
diff --git a/src/edt/edt/edtDialogs.cc b/src/edt/edt/edtDialogs.cc
index 1486b2abf..498eb8e47 100644
--- a/src/edt/edt/edtDialogs.cc
+++ b/src/edt/edt/edtDialogs.cc
@@ -683,6 +683,29 @@ BEGIN_PROTECTED;
END_PROTECTED;
}
+// --------------------------------------------------------------------------------
+// AreaAndPerimeterDialog implementation
+
+AreaAndPerimeterDialog::AreaAndPerimeterDialog (QWidget *parent)
+ : QDialog (parent)
+{
+ setupUi (this);
+}
+
+AreaAndPerimeterDialog::~AreaAndPerimeterDialog ()
+{
+ // .. nothing yet ..
+}
+
+bool
+AreaAndPerimeterDialog::exec_dialog (double area, double perimeter)
+{
+ area_le->setText (tl::to_qstring (tl::sprintf ("%.12g", area)));
+ perimeter_le->setText (tl::to_qstring (tl::sprintf ("%.12g", perimeter)));
+
+ return exec () != 0;
+}
+
}
#endif
diff --git a/src/edt/edt/edtDialogs.h b/src/edt/edt/edtDialogs.h
index 5864a8d54..a108585b5 100644
--- a/src/edt/edt/edtDialogs.h
+++ b/src/edt/edt/edtDialogs.h
@@ -43,6 +43,7 @@
#include "ui_MakeCellOptionsDialog.h"
#include "ui_MakeArrayOptionsDialog.h"
#include "ui_RoundCornerOptionsDialog.h"
+#include "ui_AreaAndPerimeterDialog.h"
namespace lay
{
@@ -205,6 +206,22 @@ private:
bool m_has_extracted;
};
+/**
+ * @brief Result dialog for "area and perimeter"
+ */
+class AreaAndPerimeterDialog
+ : public QDialog,
+ private Ui::AreaAndPerimeterDialog
+{
+Q_OBJECT
+
+public:
+ AreaAndPerimeterDialog (QWidget *parent);
+ ~AreaAndPerimeterDialog ();
+
+ bool exec_dialog (double area, double perimeter);
+};
+
} // namespace edt
#endif
diff --git a/src/edt/edt/edtMainService.cc b/src/edt/edt/edtMainService.cc
index 0f97e0166..c7b51e1b9 100644
--- a/src/edt/edt/edtMainService.cc
+++ b/src/edt/edt/edtMainService.cc
@@ -25,6 +25,7 @@
#include "dbPolygonTools.h"
#include "dbLibrary.h"
#include "dbLibraryManager.h"
+#include "dbRegion.h"
#include "tlExceptions.h"
#include "layLayoutView.h"
#include "laySelector.h"
@@ -82,6 +83,7 @@ MainService::MainService (db::Manager *manager, lay::LayoutViewBase *view, lay::
{
#if defined(HAVE_QT)
mp_round_corners_dialog = 0;
+ mp_area_and_perimeter_dialog = 0;
mp_align_options_dialog = 0;
mp_distribute_options_dialog = 0;
mp_flatten_inst_options_dialog = 0;
@@ -106,6 +108,15 @@ MainService::round_corners_dialog ()
return mp_round_corners_dialog;
}
+edt::AreaAndPerimeterDialog *
+MainService::area_and_perimeter_dialog ()
+{
+ if (! mp_area_and_perimeter_dialog) {
+ mp_area_and_perimeter_dialog = new edt::AreaAndPerimeterDialog (lay::widget_from_view (view ()));
+ }
+ return mp_area_and_perimeter_dialog;
+}
+
edt::AlignOptionsDialog *
MainService::align_options_dialog ()
{
@@ -168,6 +179,8 @@ MainService::menu_activated (const std::string &symbol)
cm_tap ();
} else if (symbol == "edt::sel_round_corners") {
cm_round_corners ();
+ } else if (symbol == "edt::sel_area_perimeter") {
+ cm_area_perimeter ();
} else if (symbol == "edt::sel_convert_to_pcell") {
cm_convert_to_pcell ();
} else if (symbol == "edt::sel_convert_to_cell") {
@@ -1346,6 +1359,67 @@ MainService::cm_convert_to_pcell ()
}
}
+void MainService::cm_area_perimeter ()
+{
+#if ! defined(HAVE_QT)
+ tl_assert (false); // see TODO
+#endif
+
+ double dbu = 0.0;
+
+ std::vector edt_services = view ()->get_plugins ();
+
+ db::Region region;
+
+ // get (common) cellview index of the primary selection
+ for (std::vector::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) {
+
+ for (edt::Service::obj_iterator s = (*es)->selection ().begin (); s != (*es)->selection ().end (); ++s) {
+
+ if (s->is_cell_inst ()) {
+ continue;
+ }
+
+ db::Polygon poly;
+ if (!s->shape ().polygon (poly)) {
+ continue;
+ }
+
+ double shape_dbu = view ()->cellview (s->cv_index ())->layout ().dbu ();
+
+ if (dbu == 0.0) {
+ // first CV is used for reference DBU
+ dbu = shape_dbu;
+ }
+
+ if (fabs (shape_dbu - dbu) < db::epsilon) {
+ region.insert (s->trans () * poly);
+ } else {
+ region.insert ((db::ICplxTrans (shape_dbu / dbu) * s->trans ()) * poly);
+ }
+
+ }
+
+ }
+
+#if defined(HAVE_QT)
+ if (region.count () > 100000) {
+ if (QMessageBox::warning (lay::widget_from_view (view ()), tr ("Warning: Big Selection"),
+ tr ("The selection contains many shapes. Area and perimeter computation may take a long time.\nContinue anyway?"),
+ QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) {
+ return;
+ }
+ }
+#endif
+
+ double area = region.area () * dbu * dbu;
+ double perimeter = region.perimeter () * dbu;
+
+#if defined(HAVE_QT)
+ area_and_perimeter_dialog ()->exec_dialog (area, perimeter);
+#endif
+}
+
static bool extract_rad (std::vector &poly, double &rinner, double &router, unsigned int &n)
{
std::vector new_pts;
@@ -1356,7 +1430,7 @@ static bool extract_rad (std::vector &poly, double &rinner, double
db::Polygon new_poly;
new_pts.clear ();
- if (! extract_rad_from_contour (p->begin_hull (), p->end_hull (), rinner, router, n, &new_pts) &&
+ if (! extract_rad_from_contour (p->begin_hull (), p->end_hull (), rinner, router, n, &new_pts) &&
! extract_rad_from_contour (p->begin_hull (), p->end_hull (), rinner, router, n, &new_pts, true)) {
// ultimate fallback: assign original contour
new_poly.assign_hull (p->begin_hull (), p->end_hull (), false /*don't compress*/);
@@ -1368,7 +1442,7 @@ static bool extract_rad (std::vector &poly, double &rinner, double
for (unsigned int h = 0; h < p->holes (); ++h) {
new_pts.clear ();
- if (! extract_rad_from_contour (p->begin_hole (h), p->end_hole (h), rinner, router, n, &new_pts) &&
+ if (! extract_rad_from_contour (p->begin_hole (h), p->end_hole (h), rinner, router, n, &new_pts) &&
! extract_rad_from_contour (p->begin_hole (h), p->end_hole (h), rinner, router, n, &new_pts, true)) {
// ultimate fallback: assign original contour
new_poly.insert_hole (p->begin_hole (h), p->end_hole (h), false /*don't compress*/);
diff --git a/src/edt/edt/edtMainService.h b/src/edt/edt/edtMainService.h
index e6b26f98b..cc9fc2426 100644
--- a/src/edt/edt/edtMainService.h
+++ b/src/edt/edt/edtMainService.h
@@ -48,6 +48,7 @@ class Service;
class EditorOptionsPages;
class EditorOptionsPage;
class RoundCornerOptionsDialog;
+class AreaAndPerimeterDialog;
class MakeCellOptionsDialog;
class MakeArrayOptionsDialog;
class AlignOptionsDialog;
@@ -104,6 +105,11 @@ public:
*/
void cm_round_corners ();
+ /**
+ * @brief Show area and perimeter of selection
+ */
+ void cm_area_perimeter ();
+
/**
* @brief Convert selection to PCell
*/
@@ -223,6 +229,7 @@ private:
bool m_undo_before_apply;
#if defined(HAVE_QT)
edt::RoundCornerOptionsDialog *mp_round_corners_dialog;
+ edt::AreaAndPerimeterDialog *mp_area_and_perimeter_dialog;
edt::AlignOptionsDialog *mp_align_options_dialog;
edt::DistributeOptionsDialog *mp_distribute_options_dialog;
lay::FlattenInstOptionsDialog *mp_flatten_inst_options_dialog;
@@ -234,6 +241,7 @@ private:
void check_no_guiding_shapes ();
#if defined(HAVE_QT)
edt::RoundCornerOptionsDialog *round_corners_dialog ();
+ edt::AreaAndPerimeterDialog *area_and_perimeter_dialog ();
edt::AlignOptionsDialog *align_options_dialog ();
edt::DistributeOptionsDialog *distribute_options_dialog ();
lay::FlattenInstOptionsDialog *flatten_inst_options_dialog ();
diff --git a/src/edt/edt/edtPlugin.cc b/src/edt/edt/edtPlugin.cc
index 8df9edfa7..f4aed23d9 100644
--- a/src/edt/edt/edtPlugin.cc
+++ b/src/edt/edt/edtPlugin.cc
@@ -342,6 +342,8 @@ public:
menu_entries.push_back (lay::menu_item ("edt::sel_make_cell_variants", "make_cell_variants:edit_mode", "edit_menu.selection_menu.end", tl::to_string (tr ("Make Cell Variants"))));
menu_entries.push_back (lay::menu_item ("edt::sel_convert_to_pcell", "convert_to_pcell:edit_mode", "edit_menu.selection_menu.end", tl::to_string (tr ("Convert To PCell"))));
menu_entries.push_back (lay::menu_item ("edt::sel_convert_to_cell", "convert_to_cell:edit_mode", "edit_menu.selection_menu.end", tl::to_string (tr ("Convert To Static Cell"))));
+ menu_entries.push_back (lay::separator ("hier_group:edit_info", "edit_menu.selection_menu.end"));
+ menu_entries.push_back (lay::menu_item ("edt::sel_area_perimeter", "area_perimeter", "edit_menu.selection_menu.end", tl::to_string (tr ("Area and Perimeter"))));
menu_entries.push_back (lay::menu_item ("edt::combine_mode", "combine_mode:edit_mode", "@toolbar.end_modes", tl::to_string (tr ("Combine{Select background combination mode}"))));
}
From 9f2cf7275f12e1b221a6e5f6d7b10984b87872db Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Tue, 1 Nov 2022 14:17:37 +0100
Subject: [PATCH 14/29] Fixed display of XOR progress (wasn't properly painting
the error bitmaps)
---
src/plugins/tools/xor/lay_plugin/layXORProgress.cc | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/plugins/tools/xor/lay_plugin/layXORProgress.cc b/src/plugins/tools/xor/lay_plugin/layXORProgress.cc
index c5f87c6f0..c0cd49e56 100644
--- a/src/plugins/tools/xor/lay_plugin/layXORProgress.cc
+++ b/src/plugins/tools/xor/lay_plugin/layXORProgress.cc
@@ -202,13 +202,13 @@ public:
} else {
- int y2 = m_pixmap_size - 1 - (iy * m_pixmap_size + m_pixmap_size / 2) / ny;
- int y1 = m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + m_pixmap_size / 2) / ny;
- int x1 = (ix * m_pixmap_size + m_pixmap_size / 2) / nx;
- int x2 = ((ix + 1) * m_pixmap_size + m_pixmap_size / 2) / nx;
+ int y2 = std::min (m_pixmap_size - 1, m_pixmap_size - 1 - (iy * m_pixmap_size + ny / 2) / ny);
+ int y1 = std::max (0, m_pixmap_size - 1 - ((iy + 1) * m_pixmap_size + ny / 2) / ny);
+ int x1 = std::max (0, (ix * m_pixmap_size + nx / 2) / nx);
+ int x2 = std::min (m_pixmap_size - 1, ((ix + 1) * m_pixmap_size + nx / 2) / nx);
// "draw" the field
- for (int y = y1; y <= y2 && y >= 0 && y < m_pixmap_size; ++y) {
+ for (int y = y1; y <= y2; ++y) {
*((uint32_t *) img->scanLine (y)) &= (((1 << x1) - 1) | ~((1 << (x2 + 1)) - 1));
}
@@ -319,8 +319,8 @@ public:
grad.setColorAt (0.0, QColor (248, 248, 248));
grad.setColorAt (1.0, QColor (224, 224, 224));
painter.setBrush (QBrush (grad));
- painter.setPen (QPen (Qt::black));
- painter.drawRect (QRect (QPoint (x, y - 2), QSize (m_pixmap_size + 3, m_pixmap_size + 3)));
+ painter.setPen (QPen (Qt::black, 1.0, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin));
+ painter.drawRect (QRectF (QPointF (x + 1, y - 1), QSizeF (m_pixmap_size + 2, m_pixmap_size + 2)));
painter.setBackgroundMode (Qt::TransparentMode);
painter.setPen (QColor (128, 255, 128));
From c8e60d666cb7c5edfdb13995815c0e2a46c6eef2 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Tue, 1 Nov 2022 14:57:39 +0100
Subject: [PATCH 15/29] Fixed #1167 (delete_cells slow)
---
src/db/db/dbLayout.cc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc
index 067ffc03b..51f249d58 100644
--- a/src/db/db/dbLayout.cc
+++ b/src/db/db/dbLayout.cc
@@ -795,6 +795,8 @@ Layout::delete_cells (const std::set &cells_to_delete)
}
}
+ db::LayoutLocker locker (this);
+
// Clear all instances
for (std::set::const_iterator c = cells_to_delete.begin (); c != cells_to_delete.end (); ++c) {
From d47cbeb2314847f27dbb80cffad48aa32acb940b Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Wed, 2 Nov 2022 23:07:29 +0100
Subject: [PATCH 16/29] [consider merging] Bugfix: generation of texts for
antenna results
---
src/db/db/dbLayoutToNetlist.cc | 2 +-
testdata/drc/drcSimpleTests_au5.gds | Bin 9892 -> 9892 bytes
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc
index 2f47d395f..8a7255ae8 100644
--- a/src/db/db/dbLayoutToNetlist.cc
+++ b/src/db/db/dbLayoutToNetlist.cc
@@ -1414,7 +1414,7 @@ get_merged_shapes_of_net (const db::hier_clusters &clusters, db::c
db::PolygonRef::polygon_edge_iterator e = pr.begin_edge ();
if (! e.at_end ()) {
// pick one reference point for the label
- if (! any_ref && (*e).p1 () < ref) {
+ if (! any_ref || (*e).p1 () < ref) {
ref = (*e).p1 ();
any_ref = true;
}
diff --git a/testdata/drc/drcSimpleTests_au5.gds b/testdata/drc/drcSimpleTests_au5.gds
index e5cca0f9e6baa8df7d3a469ed97cedc92ed1a3a9..3902b4aedf2ea902dec38825a01dc33cd2268320 100644
GIT binary patch
delta 184
zcmZ4DyTn(CfsKKQDS|HqLQ*GR*8*Kd5RqW|NnWwz`(R;
z@&>s$Hg*FzQ?LQfl)eCGswu#k1_f}Y)d4uuRRGTPPk=KcH-MOvIHWh{tC}(b0Nr3L
AGXMYp
delta 184
zcmZ4DyTn(CfsKKQDS|
Date: Wed, 2 Nov 2022 23:08:47 +0100
Subject: [PATCH 17/29] Avoid an assertion in macro editor when no script
support is compiled in
---
src/lay/lay/layMacroController.cc | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/lay/lay/layMacroController.cc b/src/lay/lay/layMacroController.cc
index 51b1111ef..41167c001 100644
--- a/src/lay/lay/layMacroController.cc
+++ b/src/lay/lay/layMacroController.cc
@@ -328,6 +328,10 @@ MacroController::drop_url (const std::string &path_or_url)
void
MacroController::show_editor (const std::string &cat, bool force_add)
{
+ if (macro_categories ().empty ()) {
+ throw tl::Exception (tl::to_string (QObject::tr ("Application has not been compiled with scripting support - no macro IDE available")));
+ }
+
if (mp_macro_editor) {
mp_macro_editor->show (cat, force_add);
}
From a8ea23452287b339c713a037cfebb3d35aaed51f Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Wed, 2 Nov 2022 23:09:44 +0100
Subject: [PATCH 18/29] Enable Qt6 build from build.sh (gcc needs c++17) and
less noisy builds with gcc 11 etc.
---
src/db/db/dbPolygonGenerators.h | 10 ++++++++++
src/klayout.pri | 17 +++++++++++++----
src/lym/unit_tests/lymBasicTests.cc | 4 ++--
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/src/db/db/dbPolygonGenerators.h b/src/db/db/dbPolygonGenerators.h
index e76c3cd87..a4127d59a 100644
--- a/src/db/db/dbPolygonGenerators.h
+++ b/src/db/db/dbPolygonGenerators.h
@@ -124,6 +124,11 @@ public:
*/
virtual void put (const db::Edge &e);
+ /**
+ * @brief Implementation of the EdgeSink interface
+ */
+ virtual void put (const db::Edge & /*e*/, int /*tag*/) { }
+
/**
* @brief Sets the way how holes are resolved dynamically
*
@@ -261,6 +266,11 @@ public:
*/
virtual void put (const db::Edge &e);
+ /**
+ * @brief Implementation of the EdgeSink interface
+ */
+ virtual void put (const db::Edge & /*e*/, int /*tag*/) { }
+
private:
db::Coord m_y;
PolygonSink *mp_psink;
diff --git a/src/klayout.pri b/src/klayout.pri
index 042cf972f..f70c810ba 100644
--- a/src/klayout.pri
+++ b/src/klayout.pri
@@ -162,16 +162,25 @@ msvc {
QMAKE_CXXFLAGS_WARN_ON += \
-pedantic \
-Woverloaded-virtual \
- -Wsign-promo \
-Wsynth \
-Wno-deprecated \
-Wno-long-long \
-Wno-strict-aliasing \
-Wno-deprecated-declarations \
- -Wno-reserved-user-defined-literal \
- # because we use unordered_map/unordered_set:
- QMAKE_CXXFLAGS += -std=c++11
+ # too noisy on Qt:
+ # QMAKE_CXXFLAGS_WARN_ON += \
+ # -Wsign-promo \
+ # -Wno-reserved-user-defined-literal \
+ #
+
+ lessThan(QT_MAJOR_VERSION, 6) {
+ # because we use unordered_map/unordered_set:
+ QMAKE_CXXFLAGS += -std=c++11
+ } else {
+ # because we use unordered_map/unordered_set:
+ QMAKE_CXXFLAGS += -std=c++17
+ }
win32 {
diff --git a/src/lym/unit_tests/lymBasicTests.cc b/src/lym/unit_tests/lymBasicTests.cc
index d0b2eaf14..90fac66bb 100644
--- a/src/lym/unit_tests/lymBasicTests.cc
+++ b/src/lym/unit_tests/lymBasicTests.cc
@@ -53,13 +53,13 @@ private:
std::string m_text;
};
+#if defined(HAVE_RUBY)
+
static std::string np (const std::string &s)
{
return tl::replaced (s, "\\", "/");
}
-#if defined(HAVE_RUBY)
-
TEST(1_BasicRuby)
{
tl_assert (rba::RubyInterpreter::instance () != 0);
From 9ec7c0ca44f77445338dd6e3a181675a755b7700 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Wed, 2 Nov 2022 23:35:06 +0100
Subject: [PATCH 19/29] layout_diff GSI binding: provide interface for edge
pair diffs
---
src/db/db/gsiDeclDbLayoutDiff.cc | 47 ++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/src/db/db/gsiDeclDbLayoutDiff.cc b/src/db/db/gsiDeclDbLayoutDiff.cc
index d6e85f00a..cd9431a75 100644
--- a/src/db/db/gsiDeclDbLayoutDiff.cc
+++ b/src/db/db/gsiDeclDbLayoutDiff.cc
@@ -248,6 +248,26 @@ public:
end_edge_differences_event ();
}
+ virtual void begin_edge_pair_differences ()
+ {
+ begin_edge_pair_differences_event ();
+ }
+
+ virtual void detailed_diff (const db::PropertiesRepository & /*pr*/, const std::vector > &a, const std::vector > &b)
+ {
+ for (std::vector >::const_iterator i = a.begin (); i != a.end (); ++i) {
+ edge_pair_in_a_only_event (i->first, i->second);
+ }
+ for (std::vector >::const_iterator i = b.begin (); i != b.end (); ++i) {
+ edge_pair_in_b_only_event (i->first, i->second);
+ }
+ }
+
+ virtual void end_edge_pair_differences ()
+ {
+ end_edge_pair_differences_event ();
+ }
+
virtual void begin_text_differences ()
{
begin_text_differences_event ();
@@ -353,6 +373,10 @@ public:
tl::event edge_in_a_only_event;
tl::event edge_in_b_only_event;
tl::Event end_edge_differences_event;
+ tl::Event begin_edge_pair_differences_event;
+ tl::event edge_pair_in_a_only_event;
+ tl::event edge_pair_in_b_only_event;
+ tl::Event end_edge_pair_differences_event;
tl::Event begin_text_differences_event;
tl::event text_in_a_only_event;
tl::event text_in_b_only_event;
@@ -671,6 +695,29 @@ gsi::Class decl_LayoutDiff ("db", "LayoutDiff",
gsi::event ("on_end_edge_differences", &LayoutDiff::end_edge_differences_event,
"@brief This signal indicates the end of sequence of edge differences\n"
) +
+ gsi::event ("on_begin_edge_pair_differences", &LayoutDiff::begin_edge_pair_differences_event,
+ "@brief This signal indicates differences in the edge pairs on the current layer\n"
+ "The current layer is indicated by the \\begin_layer_event signal or can be obtained from the diff object "
+ "through \\LayoutDiff#layer_info_a, \\LayoutDiff#layer_index_a, \\LayoutDiff#layer_info_b and \\LayoutDiff#layer_index_b. "
+ "In verbose mode (see \\Verbose flag) more signals will be emitted for edge pairs that are different between the two layouts."
+ "\n"
+ "This event has been introduced in version 0.28."
+ ) +
+ gsi::event ("on_edge_pair_in_a_only", &LayoutDiff::edge_pair_in_a_only_event, gsi::arg ("anotb"), gsi::arg ("prop_id"),
+ "@brief This signal indicates an edge pair that is present in the first layout only"
+ "\n"
+ "This event has been introduced in version 0.28."
+ ) +
+ gsi::event ("on_edge_pair_in_b_only", &LayoutDiff::edge_pair_in_b_only_event, gsi::arg ("bnota"), gsi::arg ("prop_id"),
+ "@brief This signal indicates an edge pair that is present in the second layout only"
+ "\n"
+ "This event has been introduced in version 0.28."
+ ) +
+ gsi::event ("on_end_edge_pair_differences", &LayoutDiff::end_edge_pair_differences_event,
+ "@brief This signal indicates the end of sequence of edge pair differences\n"
+ "\n"
+ "This event has been introduced in version 0.28."
+ ) +
gsi::event ("on_begin_text_differences", &LayoutDiff::begin_text_differences_event,
"@brief This signal indicates differences in the texts on the current layer\n"
"The current layer is indicated by the \\begin_layer_event signal or can be obtained from the diff object "
From 27e04c61a04d047115cfbb5f139d499062e5102e Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Wed, 2 Nov 2022 23:35:18 +0100
Subject: [PATCH 20/29] Less compiler warnings
---
src/db/db/dbPolygonTools.cc | 1 +
src/edt/edt/edtPropertiesPages.h | 8 +++++++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/db/db/dbPolygonTools.cc b/src/db/db/dbPolygonTools.cc
index 7d49fa7e4..a28cb05e1 100644
--- a/src/db/db/dbPolygonTools.cc
+++ b/src/db/db/dbPolygonTools.cc
@@ -911,6 +911,7 @@ class ErrorCatchingEdgeSink
// TODO: we should not use exceptions to indicate a condition, but right now, there is no good alternative
// and this is considered an error anyway.
virtual void put (const db::Edge &) { throw OddPolygonException (); }
+ virtual void put (const db::Edge &, int) { }
virtual void crossing_edge (const db::Edge &) { throw OddPolygonException (); }
};
diff --git a/src/edt/edt/edtPropertiesPages.h b/src/edt/edt/edtPropertiesPages.h
index 834da0fb2..0e933c804 100644
--- a/src/edt/edt/edtPropertiesPages.h
+++ b/src/edt/edt/edtPropertiesPages.h
@@ -52,8 +52,9 @@ public:
virtual size_t count () const;
virtual void select_entries (const std::vector &entries);
virtual std::string description (size_t entry) const;
- virtual QIcon icon (size_t entry, int w, int h) const;
virtual std::string description () const;
+ virtual QIcon icon (size_t entry, int w, int h) const;
+ virtual QIcon icon (int w, int h) const { return lay::PropertiesPage::icon (w, h); }
virtual void leave ();
protected:
@@ -105,6 +106,7 @@ public:
PolygonPropertiesPage (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);
@@ -129,6 +131,7 @@ public:
BoxPropertiesPage (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);
@@ -159,6 +162,7 @@ public:
TextPropertiesPage (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);
@@ -177,6 +181,7 @@ public:
PathPropertiesPage (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);
@@ -198,6 +203,7 @@ public:
EditablePathPropertiesPage (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);
From 8779e2a4ccef56eea9f0ac9880ffc57cd89db579 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Thu, 3 Nov 2022 14:26:17 +0100
Subject: [PATCH 21/29] Enabling build with Qt6
---
src/pymod/bridge_sample/bridge_sample.pro | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/src/pymod/bridge_sample/bridge_sample.pro b/src/pymod/bridge_sample/bridge_sample.pro
index 372729f5e..bfff5c5df 100644
--- a/src/pymod/bridge_sample/bridge_sample.pro
+++ b/src/pymod/bridge_sample/bridge_sample.pro
@@ -79,20 +79,28 @@ LIBS += -L$$LIBDIR -lklayout_db
!msvc {
- # Some standard compiler warnings on
QMAKE_CXXFLAGS_WARN_ON += \
-pedantic \
-Woverloaded-virtual \
- -Wsign-promo \
-Wsynth \
-Wno-deprecated \
-Wno-long-long \
-Wno-strict-aliasing \
-Wno-deprecated-declarations \
- -Wno-reserved-user-defined-literal \
- # because we use unordered_map/unordered_set:
- QMAKE_CXXFLAGS += -std=c++11
+ # too noisy on Qt:
+ # QMAKE_CXXFLAGS_WARN_ON += \
+ # -Wsign-promo \
+ # -Wno-reserved-user-defined-literal \
+ #
+
+ lessThan(QT_MAJOR_VERSION, 6) {
+ # because we use unordered_map/unordered_set:
+ QMAKE_CXXFLAGS += -std=c++11
+ } else {
+ # because we use unordered_map/unordered_set:
+ QMAKE_CXXFLAGS += -std=c++17
+ }
# Python is somewhat sloppy and relies on the compiler initializing fields
# of strucs to 0:
From 9dac047003c68fe2a99a31a1667bebfc9ea90d00 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Fri, 4 Nov 2022 21:25:12 +0100
Subject: [PATCH 22/29] Fixed small doc error
---
src/doc/doc/about/basic_lib.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/doc/doc/about/basic_lib.xml b/src/doc/doc/about/basic_lib.xml
index a2592561e..3fa5c1715 100644
--- a/src/doc/doc/about/basic_lib.xml
+++ b/src/doc/doc/about/basic_lib.xml
@@ -83,7 +83,7 @@
Custom fonts are installed by copying the font file to a folder named "fonts"
in one of the places in KLayout's path. The standard font can be found in
- "src/std_font.gds" in the source package.
+ "src/db/db/std_font.gds" in the source package.
Before nets can be extracted, a layer stack must be specified. Press "Layer Stack" on the user interface to open the
- layer stack dialog. Layers must be specified in the "layer/datatype" notation. The
+ layer stack dialog or use "Edit Layer Stack" in the "Tools" menu. Layers must be specified in the "layer/datatype" notation. The
via specification is optional. If no via layer is specified, both metal layer shapes are required to touch in order to form a
connection. If a via layer is specified, a via shape must be present to form the connection.
- KLayout allows specification of symbolic layers and to use boolean expressions. That way it is possible to
+ The layer stack (also referred to as "Connectivity") is also a technology component. This means
+ if you select a technology for layout, the technology specific stack is selected. To edit the stack
+ for all technologies, use the Technology Manager ("Tools/Manage Technologies") and use the
+ "Connectivity" section from the technologies.
+
+
+
+ A connectivity definition can specify multiple stacks, out of which one has to be selected.
+ This is useful, if your technology setup features multiple routing metal schemes for example.
+ You do not need to setup different technologies for each scheme. If you have declared multiple
+ stacks, you can choose one in the "Trace Net" dialog in the drop-down button right of the
+ "Layer Stack" and the "Configuration" button at the bottom left.
+
+
+
+ Within the stack definition, KLayout allows specification of symbolic layers and to use boolean expressions. That way it is possible to
assign meaningful names to layers (i.e. "POLY" or "VIA1") and to use derived layers (i.e. "ACTIVE-POLY" for
the source and drain regions of a CMOS transistor). Read more about these features in
and .
- If a layer stack has been defined, a net can be traced by pressing the "Trace Net" button and clicking on a point in the
+ Once a layer stack has been defined and selected, a net can be traced by pressing the "Trace Net" button and clicking on a point in the
layout. Starting from shapes found under this point, the net is extracted and listed in the net list on the left side of the
net tracing dialog. If "Lock" is checked, another net can be traced by clicking at another point without having to press
the "Trace Net" button again.
From 131745433d9dd684c42fd34e72793edc231e2f15 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Fri, 4 Nov 2022 23:16:15 +0100
Subject: [PATCH 24/29] Doc fixes
---
src/db/db/gsiDeclDbRegion.cc | 8 --------
1 file changed, 8 deletions(-)
diff --git a/src/db/db/gsiDeclDbRegion.cc b/src/db/db/gsiDeclDbRegion.cc
index 0cc777b8b..926fa368a 100644
--- a/src/db/db/gsiDeclDbRegion.cc
+++ b/src/db/db/gsiDeclDbRegion.cc
@@ -2452,7 +2452,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
- "Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@@ -2491,7 +2490,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
- "Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@@ -2535,7 +2533,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
- "Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@@ -2574,7 +2571,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
- "Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@@ -2617,7 +2613,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
- "Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@@ -2667,7 +2662,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
- "Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@@ -2716,7 +2710,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
- "Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
@@ -2765,7 +2758,6 @@ Class decl_Region (decl_dbShapeCollection, "db", "Region",
"\n"
"\"metrics\" can be one of the constants \\Euclidian, \\Square or \\Projection. See there for "
"a description of these constants.\n"
- "Use nil for this value to select the default (Euclidian metrics).\n"
"\n"
"\"ignore_angle\" specifies the angle limit of two edges. If two edges form an angle equal or "
"above the given value, they will not contribute in the check. "
From f67b28c52a6f813e8d82878e454fc17d07ef00d9 Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Fri, 4 Nov 2022 23:45:10 +0100
Subject: [PATCH 25/29] Supporting LayerInfo objects in fill pattern
generation, doc updates
---
src/doc/doc/about/drc_ref_layer.xml | 19 +++++++++++++++++++
src/drc/drc/built-in-macros/_drc_layer.rb | 19 +++++++++++++++++++
src/drc/drc/built-in-macros/_drc_tags.rb | 4 ++++
testdata/drc/drcSimpleTests_46.drc | 4 ++--
4 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/src/doc/doc/about/drc_ref_layer.xml b/src/doc/doc/about/drc_ref_layer.xml
index 6d105b8ea..4cc344d45 100644
--- a/src/doc/doc/about/drc_ref_layer.xml
+++ b/src/doc/doc/about/drc_ref_layer.xml
@@ -1125,6 +1125,25 @@ A more compact way of writing this is:
p = fill_pattern("FILL_CELL").shape(1, 0, box(0.0, 0.0, 1.0, 1.0))
+The "shape" method takes several forms:
+
+
+
shape(layer, object, object ...) (1)
+
shape(layer, datatype, object, object ...) (2)
+
shape(name, object, object ...) (3)
+
shape(layer_info, object, object ...) (4)
+
+
+The first form takes a GDS2 layer number. The datatype is assumed to be 0.
+The second form takes a GDS layer and datatype number.
+The third form takes a layer name for layout systems with named layers
+(like Magic, CIF or DXF).
+The forth form takes a LayerInfo object to specify the layer.
+All forms take one to many geometry objects which are written to the respective layer.
+Geometry objects can either be created using the generator functions
+(box, polygon, path). The core classes DBox, DPolygon, DPath or
+DText are also accepted as geometry objects.
+
The fill pattern can be given a reference point which is used for placing the pattern. The reference point
is the one which is aligned with the pattern origin. The following code will assign (-0.5, -0.5) as the reference
point for the 1x1 micron rectangle. Hence the reference point is a little below and left of the rectangle which
diff --git a/src/drc/drc/built-in-macros/_drc_layer.rb b/src/drc/drc/built-in-macros/_drc_layer.rb
index 88ab7e0b7..c8e2731a5 100644
--- a/src/drc/drc/built-in-macros/_drc_layer.rb
+++ b/src/drc/drc/built-in-macros/_drc_layer.rb
@@ -4712,6 +4712,25 @@ CODE
# p = fill_pattern("FILL_CELL").shape(1, 0, box(0.0, 0.0, 1.0, 1.0))
# @/code
#
+ # The "shape" method takes several forms:
+ #
+ # @ul
+ # @li @tt shape(layer, object, object ...) @/tt (1) @/li
+ # @li @tt shape(layer, datatype, object, object ...) @/tt (2) @/li
+ # @li @tt shape(name, object, object ...) @/tt (3) @/li
+ # @li @tt shape(layer_info, object, object ...) @/tt (4) @/li
+ # @/ul
+ #
+ # The first form takes a GDS2 layer number. The datatype is assumed to be 0.
+ # The second form takes a GDS layer and datatype number.
+ # The third form takes a layer name for layout systems with named layers
+ # (like Magic, CIF or DXF).
+ # The forth form takes a RBA::LayerInfo object to specify the layer.
+ # All forms take one to many geometry objects which are written to the respective layer.
+ # Geometry objects can either be created using the generator functions
+ # (\global#box, \global#polygon, \global#path). The core classes RBA::DBox, RBA::DPolygon, RBA::DPath or
+ # RBA::DText are also accepted as geometry objects.
+ #
# The fill pattern can be given a reference point which is used for placing the pattern. The reference point
# is the one which is aligned with the pattern origin. The following code will assign (-0.5, -0.5) as the reference
# point for the 1x1 micron rectangle. Hence the reference point is a little below and left of the rectangle which
diff --git a/src/drc/drc/built-in-macros/_drc_tags.rb b/src/drc/drc/built-in-macros/_drc_tags.rb
index dedd797ef..86fd67e8d 100644
--- a/src/drc/drc/built-in-macros/_drc_tags.rb
+++ b/src/drc/drc/built-in-macros/_drc_tags.rb
@@ -256,6 +256,10 @@ module DRC
else
raise("Argument ##{ai+1} not understood for FillCell#shape")
end
+ elsif a.is_a?(RBA::LayerInfo)
+ layer = a.layer
+ datatype = a.datatype
+ name = a.name
elsif a.is_a?(String)
if !name
name = a
diff --git a/testdata/drc/drcSimpleTests_46.drc b/testdata/drc/drcSimpleTests_46.drc
index 1278a4681..493b4aee1 100644
--- a/testdata/drc/drcSimpleTests_46.drc
+++ b/testdata/drc/drcSimpleTests_46.drc
@@ -14,10 +14,10 @@ to_fill = extent - l1
fp1 = fill_pattern("FP1").shape(10, 0, box(0, 0, 800.nm, 800.nm)).origin(-100.nm, -100.nm)
to_fill = to_fill.fill_with_left(fp1, hstep(1.um), vstep(200.nm, 1.um), multi_origin)
-fp2 = fill_pattern("FP2").shape(10, 0, box(0, 0, 400.nm, 400.nm)).origin(-50.nm, -50.nm)
+fp2 = fill_pattern("FP2").shape(10, box(0, 0, 400.nm, 400.nm)).origin(-50.nm, -50.nm)
to_fill = to_fill.fill_with_left(fp2, hstep(0.5.um), vstep(100.nm, 0.5.um), multi_origin)
-fp3 = fill_pattern("FP3").shape(10, 0, box(0, 0, 200.nm, 200.nm)).origin(-25.nm, -25.nm)
+fp3 = fill_pattern("FP3").shape(RBA::LayerInfo::new(10, 0), box(0, 0, 200.nm, 200.nm)).origin(-25.nm, -25.nm)
to_fill = to_fill.fill_with_left(fp3, hstep(0.25.um), vstep(50.nm, 0.25.um), multi_origin)
to_fill.output(100, 0)
From c25223db361e455a3b37c09d30aae5f97f76dc5d Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Fri, 4 Nov 2022 23:49:23 +0100
Subject: [PATCH 26/29] Updated golden test data
---
testdata/drc/drcSimpleTests_au6.gds | Bin 3494 -> 3494 bytes
testdata/drc/drcSimpleTests_au7.gds | Bin 22060 -> 22060 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/testdata/drc/drcSimpleTests_au6.gds b/testdata/drc/drcSimpleTests_au6.gds
index 08fada80ba01d0829e0a726ebc62f28d5a0a336e..70ac9f50b12c115c3dfdd22db6342ed66e262482 100644
GIT binary patch
delta 273
zcmZ1`y-Zq(fsKKQDS|@UW|YHeMv$kUyZ_`uCgIHnOtaWH{{R2!!N9=gF!>*+)Z{lDE^Ph@3=B+r
wfZRAXR{=QF>HwT+PylDDDZrW17vN061~`-50LqL3TJ+}ul;gE|0S_A^05tSHssI20
delta 271
zcmZ1`y-Zq(fsKKQDS|@UW|YHeMv$kUyZ_`uCgIHnOtaWH7@%PCKTfI1Z#Z1oAbcPZ;#6!9nYCuH(J2x86Qp4?=p+mknNpZC0;r+A)H1_r8n03}7$z90uFn1*GTPx4*4
zvOe+$WEtDvt#9uEq%?q1`rjvBuHTiZk#G1r>KoIC!|zQ1X7fU(#TrKdYM;;LT5Mxn
zqV*}Ub|JB9N}L@?oM=nbYJ|;D@)OX<8SfP}zf!nK$7NRLQ*MA9RY
z9+C8jq(>yZZCu5A+c@=m#rv^rbTvHj@r=pOs}H)k9Ui%vGx_gAR~HK;0#PIph&qWt
zlu87mS|Shy6M?8HgHBjYY$c=Ha53iVOZj}fSYRFUOY1mVEU-SJ#Sm#RL|P1y7DJ@P
z5NR<)S}d^oavW`A
HYqZ%POs_Gb)S3_=W|3~~%S$n1$q%Jx_#7`WKjLV_Iqf*BZC
z*cljPSaBM$v1L1>C{{Bz2QY18<6wY-$$Xr3Y!LQjIc{1pvnFqlVBf6F*UgHs*g;Hc
z@&(}}nB@*)H8f&oY~CO-iI)rJV}@0e1vnKZ=cp}$xn;#<1#X4O|I`-@5`i9IXt8bP
z(Bt8OIf!BM1FP7{l~#$cAbMc6j~2{Ljy4
Date: Sat, 5 Nov 2022 14:28:40 +0100
Subject: [PATCH 27/29] [consider merging] Important bug fix - do not use
NDEBUG as ruby.h redefines it and this will lead to crashes in the debugger
---
src/gsi/gsi/gsiMethods.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/gsi/gsi/gsiMethods.h b/src/gsi/gsi/gsiMethods.h
index a2e131587..71cf4ba43 100644
--- a/src/gsi/gsi/gsiMethods.h
+++ b/src/gsi/gsi/gsiMethods.h
@@ -524,7 +524,7 @@ public:
// .. nothing yet ..
}
-#if !defined(NDEBUG)
+#if defined(TRACE_METHOD_CALLS)
public:
/**
From 240281d9ff31727711479baa98c4d9e8102e0c9e Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 6 Nov 2022 01:12:03 +0100
Subject: [PATCH 28/29] [consider merging] Important patch: avoids incorrect
initialization of Python classes
---
src/pya/pya/pyaModule.cc | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/pya/pya/pyaModule.cc b/src/pya/pya/pyaModule.cc
index 191adb70d..8f0fb40a3 100644
--- a/src/pya/pya/pyaModule.cc
+++ b/src/pya/pya/pyaModule.cc
@@ -408,19 +408,19 @@ struct PythonClassClientData
: public gsi::PerClassClientSpecificData
{
PythonClassClientData (const gsi::ClassBase *_cls, PyTypeObject *_py_type, PyTypeObject *_py_type_static)
- : py_type_object (_py_type), py_type_object_static (_py_type_static), method_table (_cls)
+ : py_type_object ((PyObject *) _py_type), py_type_object_static ((PyObject *) _py_type_static), method_table (_cls)
{
// .. nothing yet ..
}
- PyTypeObject *py_type_object;
- PyTypeObject *py_type_object_static;
+ PythonPtr py_type_object;
+ PythonPtr py_type_object_static;
MethodTable method_table;
static PyTypeObject *py_type (const gsi::ClassBase &cls_decl, bool as_static)
{
PythonClassClientData *cd = dynamic_cast(cls_decl.data (gsi::ClientIndex::Python));
- return cd ? (as_static ? cd->py_type_object_static : cd->py_type_object) : 0;
+ return (PyTypeObject *) (cd ? (as_static ? cd->py_type_object_static.get () : cd->py_type_object.get ()) : 0);
}
static void initialize (const gsi::ClassBase &cls_decl, PyTypeObject *py_type, bool as_static)
@@ -428,9 +428,9 @@ struct PythonClassClientData
PythonClassClientData *cd = dynamic_cast(cls_decl.data (gsi::ClientIndex::Python));
if (cd) {
if (as_static) {
- cd->py_type_object_static = py_type;
+ cd->py_type_object_static = (PyObject *) py_type;
} else {
- cd->py_type_object = py_type;
+ cd->py_type_object = (PyObject *) py_type;
}
} else {
cls_decl.set_data (gsi::ClientIndex::Python, new PythonClassClientData (&cls_decl, as_static ? NULL : py_type, as_static ? py_type : NULL));
@@ -2475,7 +2475,11 @@ public:
PyTypeObject *type = (PyTypeObject *) PyObject_Call ((PyObject *) &PyType_Type, args.get (), NULL);
if (type == NULL) {
- check_error ();
+ try {
+ check_error ();
+ } catch (tl::Exception &ex) {
+ tl::error << ex.msg ();
+ }
tl_assert (false);
}
From cd3ca9e53693cb1815ff144ba68b42225c07de9f Mon Sep 17 00:00:00 2001
From: Matthias Koefferlein
Date: Sun, 6 Nov 2022 01:23:39 +0100
Subject: [PATCH 29/29] Do not use zstd compression for Qt6 as there is no
built-in decompression
---
src/klayout.pri | 5 +++++
src/tl/tl/tlStream.cc | 4 ++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/klayout.pri b/src/klayout.pri
index f70c810ba..0cb25c0ab 100644
--- a/src/klayout.pri
+++ b/src/klayout.pri
@@ -130,6 +130,11 @@ equals(HAVE_CRONOLOGY, "1") {
INCLUDEPATH += $$CRONOLOGY_INCLUDE
}
+!lessThan(QT_MAJOR_VERSION, 6) {
+ # internal resource readers to not support zstd so far
+ QMAKE_RESOURCE_FLAGS += --compress-algo zlib
+}
+
msvc {
QMAKE_CXXFLAGS += \
diff --git a/src/tl/tl/tlStream.cc b/src/tl/tl/tlStream.cc
index 2813a9114..7a9c78df3 100644
--- a/src/tl/tl/tlStream.cc
+++ b/src/tl/tl/tlStream.cc
@@ -212,9 +212,9 @@ InputStream::InputStream (const std::string &abstract_path)
QByteArray data;
#if QT_VERSION >= 0x60000
- if (res.compressionAlgorithm () == QResource::ZlibCompression) {
+ if (res.compressionAlgorithm () == QResource::ZlibCompression) {
#else
- if (res.isCompressed ()) {
+ if (res.isCompressed ()) {
#endif
data = qUncompress ((const unsigned char *)res.data (), (int)res.size ());
} else {