WIP: preparations for callbacks in PCell code

This commit is contained in:
Matthias Koefferlein 2022-10-28 23:41:31 +02:00
parent d82ff4d3f8
commit eb8c96054c
5 changed files with 233 additions and 158 deletions

View File

@ -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)
{

View File

@ -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 &parameter (const std::string &name)
{
return m_states [name];
}
ParameterState &parameter (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 &parameter (const std::string &name) const
{
return const_cast<ParameterStates *> (this)->parameter (name);
}
const ParameterState &parameter (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<std::string, ParameterState> m_states;

View File

@ -555,7 +555,7 @@ InstPropertiesPage::create_applicator (db::Cell & /*cell*/, const db::Instance &
tl_assert (mp_pcell_parameters);
std::vector<tl::Variant> param = mp_pcell_parameters->get_parameters (0);
const std::vector<tl::Variant> &initial_param = mp_pcell_parameters->initial_parameters ();
std::vector<tl::Variant> initial_param = mp_pcell_parameters->initial_parameters ();
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_parameters->pcell_decl ()->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::const_iterator pd = pcp.begin (); pd != pcp.end (); ++pd) {

View File

@ -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<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::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<tl::Variant> 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<db::PCellParameterDeclaration> &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<tl::Variant>
PCellParametersPage::get_parameters (bool *ok)
void
PCellParametersPage::get_parameters (db::ParameterStates &states, bool *ok)
{
std::vector<tl::Variant> 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<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::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<tl::Variant>
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<tl::Variant> &parameters)
return;
}
size_t r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::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<tl::Variant> &parameters)
// 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<tl::Variant> &parameters, bool tentatively)
PCellParametersPage::update_widgets_from_states (const db::ParameterStates &states)
{
if (! mp_pcell_decl) {
return;
}
size_t i = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::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<tl::Variant> &pa
size_t r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::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<tl::Variant> &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<tl::Variant>
PCellParametersPage::parameter_from_states (const db::ParameterStates &states) const
{
std::vector<tl::Variant> parameters;
if (mp_pcell_decl) {
const std::vector<db::PCellParameterDeclaration> &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<tl::Variant> &parameters)
{
if (! mp_pcell_decl) {
return;
}
size_t r = 0;
const std::vector<db::PCellParameterDeclaration> &pcp = mp_pcell_decl->parameter_declarations ();
for (std::vector<db::PCellParameterDeclaration>::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

View File

@ -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<tl::Variant> 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<tl::Variant> &initial_parameters () const
std::vector<tl::Variant> 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<PCellParametersPage> dm_parameter_changed;
std::vector<tl::Variant> 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<tl::Variant> &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<tl::Variant> parameter_from_states (const db::ParameterStates &states) const;
void states_from_parameters (db::ParameterStates &states, const std::vector<tl::Variant> &parameters);
};
}