Merge pull request #2039 from KLayout/feature/issue-2016

First attempt to implement a solution for issue #2016
This commit is contained in:
Matthias Köfferlein 2025-05-22 19:22:32 +02:00 committed by GitHub
commit ba640b6d04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 66 additions and 39 deletions

View File

@ -517,7 +517,7 @@ PropertiesPage::readonly ()
} }
void void
PropertiesPage::apply () PropertiesPage::apply (bool /*commit*/)
{ {
ant::Object obj; ant::Object obj;
get_object (obj); get_object (obj);

View File

@ -50,7 +50,7 @@ public:
virtual void update (); virtual void update ();
virtual void leave (); virtual void leave ();
virtual bool readonly (); virtual bool readonly ();
virtual void apply (); virtual void apply (bool commit);
private slots: private slots:
void swap_points_clicked (); void swap_points_clicked ();

View File

@ -925,7 +925,7 @@ InstPropertiesPage::do_apply (bool current_only, bool relative)
} }
void void
InstPropertiesPage::apply () InstPropertiesPage::apply (bool /*commit*/)
{ {
do_apply (true, false); do_apply (true, false);
} }
@ -937,7 +937,7 @@ InstPropertiesPage::can_apply_to_all () const
} }
void void
InstPropertiesPage::apply_to_all (bool relative) InstPropertiesPage::apply_to_all (bool relative, bool /*commit*/)
{ {
do_apply (false, relative); do_apply (false, relative);
} }

View File

@ -66,8 +66,8 @@ protected:
edt::PCellParametersPage *mp_pcell_parameters; edt::PCellParametersPage *mp_pcell_parameters;
virtual bool readonly (); virtual bool readonly ();
virtual void apply (); virtual void apply (bool commit);
virtual void apply_to_all (bool relative); virtual void apply_to_all (bool relative, bool commit);
virtual bool can_apply_to_all () const; virtual bool can_apply_to_all () const;
void do_apply (bool current_only, bool relative); void do_apply (bool current_only, bool relative);
virtual ChangeApplicator *create_applicator (db::Cell &cell, const db::Instance &inst, double dbu); virtual ChangeApplicator *create_applicator (db::Cell &cell, const db::Instance &inst, double dbu);

View File

@ -215,7 +215,7 @@ ShapePropertiesPage::recompute_selection_ptrs (const std::vector<lay::ObjectInst
} }
void void
ShapePropertiesPage::do_apply (bool current_only, bool relative) ShapePropertiesPage::do_apply (bool current_only, bool relative, bool commit)
{ {
if (m_indexes.empty ()) { if (m_indexes.empty ()) {
return; return;
@ -321,7 +321,7 @@ ShapePropertiesPage::do_apply (bool current_only, bool relative)
} }
// handle the case of guiding shape updates // handle the case of guiding shape updates
std::pair<bool, lay::ObjectInstPath> gs = mp_service->handle_guiding_shape_changes (new_sel[index]); std::pair<bool, lay::ObjectInstPath> gs = mp_service->handle_guiding_shape_changes (new_sel[index], commit);
if (gs.first) { if (gs.first) {
new_sel[index] = gs.second; new_sel[index] = gs.second;
@ -350,9 +350,9 @@ ShapePropertiesPage::do_apply (bool current_only, bool relative)
} }
void void
ShapePropertiesPage::apply () ShapePropertiesPage::apply (bool commit)
{ {
do_apply (true, false); do_apply (true, false, commit);
} }
bool bool
@ -362,9 +362,9 @@ ShapePropertiesPage::can_apply_to_all () const
} }
void void
ShapePropertiesPage::apply_to_all (bool relative) ShapePropertiesPage::apply_to_all (bool relative, bool commit)
{ {
do_apply (false, relative); do_apply (false, relative, commit);
} }
void void

View File

@ -63,10 +63,10 @@ protected:
private: private:
virtual void update (); virtual void update ();
virtual void apply (); virtual void apply (bool commit);
virtual void apply_to_all (bool relative); virtual void apply_to_all (bool relative, bool commit);
virtual bool can_apply_to_all () const; virtual bool can_apply_to_all () const;
virtual void do_apply (bool current_only, bool relative); virtual void do_apply (bool current_only, bool relative, bool commit);
void recompute_selection_ptrs (const std::vector<lay::ObjectInstPath> &new_sel); void recompute_selection_ptrs (const std::vector<lay::ObjectInstPath> &new_sel);
protected: protected:

View File

@ -76,6 +76,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIter
m_snap_to_objects (true), m_snap_to_objects (true),
m_snap_objects_to_grid (true), m_snap_objects_to_grid (true),
m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000), m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000),
m_pcell_lazy_evaluation (0),
m_hier_copy_mode (-1), m_hier_copy_mode (-1),
m_indicate_secondary_selection (false), m_indicate_secondary_selection (false),
m_seq (0), m_seq (0),
@ -391,6 +392,10 @@ Service::configure (const std::string &name, const std::string &value)
tl::from_string (value, m_hier_copy_mode); tl::from_string (value, m_hier_copy_mode);
service_configuration_changed (); service_configuration_changed ();
} else if (name == cfg_edit_pcell_lazy_eval_mode) {
tl::from_string (value, m_pcell_lazy_evaluation);
} else { } else {
lay::EditorServiceBase::configure (name, value); lay::EditorServiceBase::configure (name, value);
} }
@ -598,7 +603,7 @@ Service::end_move (const db::DPoint & /*p*/, lay::angle_constraint_type ac)
transform (db::DCplxTrans (m_move_trans)); transform (db::DCplxTrans (m_move_trans));
move_cancel (); // formally this functionality fits here move_cancel (); // formally this functionality fits here
// accept changes to guiding shapes // accept changes to guiding shapes
handle_guiding_shape_changes (); handle_guiding_shape_changes (true);
} }
m_alt_ac = lay::AC_Global; m_alt_ac = lay::AC_Global;
} }
@ -846,7 +851,7 @@ Service::transform (const db::DCplxTrans &trans, const std::vector<db::DCplxTran
} }
handle_guiding_shape_changes (); handle_guiding_shape_changes (true);
selection_to_view (); selection_to_view ();
} }
@ -1860,7 +1865,7 @@ Service::add_selection (const lay::ObjectInstPath &sel)
} }
std::pair<bool, lay::ObjectInstPath> std::pair<bool, lay::ObjectInstPath>
Service::handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const Service::handle_guiding_shape_changes (const lay::ObjectInstPath &obj, bool commit) const
{ {
unsigned int cv_index = obj.cv_index (); unsigned int cv_index = obj.cv_index ();
lay::CellView cv = view ()->cellview (cv_index); lay::CellView cv = view ()->cellview (cv_index);
@ -1874,10 +1879,22 @@ Service::handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const
return std::make_pair (false, lay::ObjectInstPath ()); return std::make_pair (false, lay::ObjectInstPath ());
} }
if (! layout->is_pcell_instance (obj.cell_index ()).first) { auto pcell_decl = layout->pcell_declaration_for_pcell_variant (obj.cell_index ());
if (! pcell_decl) {
return std::make_pair (false, lay::ObjectInstPath ()); return std::make_pair (false, lay::ObjectInstPath ());
} }
// Don't update unless we're committing or not in lazy PCell update mode
if (! commit) {
if (m_pcell_lazy_evaluation < 0) {
if (pcell_decl->wants_lazy_evaluation ()) {
return std::make_pair (false, lay::ObjectInstPath ());
}
} else if (m_pcell_lazy_evaluation > 0) {
return std::make_pair (false, lay::ObjectInstPath ());
}
}
db::cell_index_type top_cell = std::numeric_limits<db::cell_index_type>::max (); db::cell_index_type top_cell = std::numeric_limits<db::cell_index_type>::max ();
db::cell_index_type parent_cell = std::numeric_limits<db::cell_index_type>::max (); db::cell_index_type parent_cell = std::numeric_limits<db::cell_index_type>::max ();
db::Instance parent_inst; db::Instance parent_inst;
@ -1944,7 +1961,7 @@ Service::handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const
} }
bool bool
Service::handle_guiding_shape_changes () Service::handle_guiding_shape_changes (bool commit)
{ {
EditableSelectionIterator s = begin_selection (); EditableSelectionIterator s = begin_selection ();
@ -1953,7 +1970,7 @@ Service::handle_guiding_shape_changes ()
return false; return false;
} }
std::pair<bool, lay::ObjectInstPath> gs = handle_guiding_shape_changes (*s); std::pair<bool, lay::ObjectInstPath> gs = handle_guiding_shape_changes (*s, commit);
if (gs.first) { if (gs.first) {
// remove superfluous proxies // remove superfluous proxies

View File

@ -398,17 +398,19 @@ public:
* *
* @return true, if PCells have been updated, indicating that our selection is no longer valid * @return true, if PCells have been updated, indicating that our selection is no longer valid
* *
* @param commit If true, changes are "final" (and PCells are updated also in lazy evaluation mode)
*
* This version assumes there is only one guiding shape selected and will update the selection. * This version assumes there is only one guiding shape selected and will update the selection.
* It will also call layout.cleanup() if required. * It will also call layout.cleanup() if required.
*/ */
bool handle_guiding_shape_changes (); bool handle_guiding_shape_changes (bool commit);
/** /**
* @brief Handle changes in a specific guiding shape, i.e. create new PCell variants if required * @brief Handle changes in a specific guiding shape, i.e. create new PCell variants if required
* *
* @return A pair of bool (indicating that the object path has changed) and the new guiding shape path * @return A pair of bool (indicating that the object path has changed) and the new guiding shape path
*/ */
std::pair<bool, lay::ObjectInstPath> handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const; std::pair<bool, lay::ObjectInstPath> handle_guiding_shape_changes (const lay::ObjectInstPath &obj, bool commit) const;
/** /**
* @brief Gets a value indicating whether a move operation is ongoing * @brief Gets a value indicating whether a move operation is ongoing
@ -672,9 +674,12 @@ private:
bool m_snap_to_objects; bool m_snap_to_objects;
bool m_snap_objects_to_grid; bool m_snap_objects_to_grid;
db::DVector m_global_grid; db::DVector m_global_grid;
// Other attributes
bool m_top_level_sel; bool m_top_level_sel;
bool m_show_shapes_of_instances; bool m_show_shapes_of_instances;
unsigned int m_max_shapes_of_instances; unsigned int m_max_shapes_of_instances;
int m_pcell_lazy_evaluation;
// Hierarchical copy mode (-1: ask, 0: shallow, 1: deep) // Hierarchical copy mode (-1: ask, 0: shallow, 1: deep)
int m_hier_copy_mode; int m_hier_copy_mode;

View File

@ -784,7 +784,7 @@ PropertiesPage::reverse_color_order ()
} }
void void
PropertiesPage::apply () PropertiesPage::apply (bool /*commit*/)
{ {
bool has_error = false; bool has_error = false;
@ -915,7 +915,7 @@ PropertiesPage::browse ()
{ {
BEGIN_PROTECTED BEGIN_PROTECTED
apply (); apply (true);
lay::FileDialog file_dialog (this, tl::to_string (QObject::tr ("Load Image File")), tl::to_string (QObject::tr ("All files (*)"))); lay::FileDialog file_dialog (this, tl::to_string (QObject::tr ("Load Image File")), tl::to_string (QObject::tr ("All files (*)")));
@ -941,7 +941,7 @@ PropertiesPage::save_pressed ()
{ {
BEGIN_PROTECTED BEGIN_PROTECTED
apply (); apply (true);
lay::FileDialog file_dialog (this, tl::to_string (QObject::tr ("Save As KLayout Image File")), tl::to_string (QObject::tr ("KLayout image files (*.lyimg);;All files (*)"))); lay::FileDialog file_dialog (this, tl::to_string (QObject::tr ("Save As KLayout Image File")), tl::to_string (QObject::tr ("KLayout image files (*.lyimg);;All files (*)")));

View File

@ -57,7 +57,7 @@ public:
virtual void update (); virtual void update ();
virtual void leave (); virtual void leave ();
virtual bool readonly (); virtual bool readonly ();
virtual void apply (); virtual void apply (bool commit);
void set_direct_image (img::Object *image); void set_direct_image (img::Object *image);

View File

@ -71,7 +71,7 @@ public:
BEGIN_PROTECTED BEGIN_PROTECTED
properties_frame->set_direct_image (mp_image_object); properties_frame->set_direct_image (mp_image_object);
properties_frame->apply (); properties_frame->apply (true);
if (mp_image_object->is_empty ()) { if (mp_image_object->is_empty ()) {
throw tl::Exception (tl::to_string (tr ("No data loaded for that image"))); throw tl::Exception (tl::to_string (tr ("No data loaded for that image")));

View File

@ -154,8 +154,10 @@ public:
* Apply any changes to the current objects. If nothing was * Apply any changes to the current objects. If nothing was
* changed, the object may be left untouched. * changed, the object may be left untouched.
* The dialog will start a transaction on the manager object. * The dialog will start a transaction on the manager object.
*
* @param commit Is true for the "final" changes (i.e. not during editing)
*/ */
virtual void apply () virtual void apply (bool /*commit*/)
{ {
// default implementation is empty. // default implementation is empty.
} }
@ -174,8 +176,11 @@ public:
* Apply any changes to the current object plus all other objects of the same kind. * Apply any changes to the current object plus all other objects of the same kind.
* If nothing was changed, the objects may be left untouched. * If nothing was changed, the objects may be left untouched.
* The dialog will start a transaction on the manager object. * The dialog will start a transaction on the manager object.
*
* @param relative Is true if relative mode is selected
* @param commit Is true for the "final" changes (i.e. not during editing)
*/ */
virtual void apply_to_all (bool /*relative*/) virtual void apply_to_all (bool /*relative*/, bool /*commit*/)
{ {
// default implementation is empty. // default implementation is empty.
} }

View File

@ -197,7 +197,7 @@ PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager,
} }
for (size_t i = 0; i < mp_properties_pages.size (); ++i) { for (size_t i = 0; i < mp_properties_pages.size (); ++i) {
mp_stack->addWidget (mp_properties_pages [i]); mp_stack->addWidget (mp_properties_pages [i]);
connect (mp_properties_pages [i], SIGNAL (edited ()), this, SLOT (apply ())); connect (mp_properties_pages [i], SIGNAL (edited ()), this, SLOT (properties_edited ()));
} }
// Necessary to maintain the page order for UI regression testing of 0.18 vs. 0.19 (because tl::Collection has changed to order) .. // Necessary to maintain the page order for UI regression testing of 0.18 vs. 0.19 (because tl::Collection has changed to order) ..
@ -314,7 +314,7 @@ PropertiesDialog::current_index_changed (const QModelIndex &index, const QModelI
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id); db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id);
mp_properties_pages [m_index]->apply (); mp_properties_pages [m_index]->apply (true);
if (! t.is_empty ()) { if (! t.is_empty ()) {
m_transaction_id = t.id (); m_transaction_id = t.id ();
@ -437,7 +437,7 @@ BEGIN_PROTECTED
if (! mp_properties_pages [m_index]->readonly ()) { if (! mp_properties_pages [m_index]->readonly ()) {
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id); db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id);
mp_properties_pages [m_index]->apply (); mp_properties_pages [m_index]->apply (true);
if (! t.is_empty ()) { if (! t.is_empty ()) {
m_transaction_id = t.id (); m_transaction_id = t.id ();
} }
@ -485,7 +485,7 @@ BEGIN_PROTECTED
if (! mp_properties_pages [m_index]->readonly ()) { if (! mp_properties_pages [m_index]->readonly ()) {
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id); db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id);
mp_properties_pages [m_index]->apply (); mp_properties_pages [m_index]->apply (true);
if (! t.is_empty ()) { if (! t.is_empty ()) {
m_transaction_id = t.id (); m_transaction_id = t.id ();
} }
@ -567,7 +567,7 @@ PropertiesDialog::any_prev () const
} }
void void
PropertiesDialog::apply () PropertiesDialog::properties_edited ()
{ {
BEGIN_PROTECTED BEGIN_PROTECTED
@ -580,9 +580,9 @@ BEGIN_PROTECTED
try { try {
if (mp_ui->apply_to_all_cbx->isChecked () && mp_properties_pages [m_index]->can_apply_to_all ()) { if (mp_ui->apply_to_all_cbx->isChecked () && mp_properties_pages [m_index]->can_apply_to_all ()) {
mp_properties_pages [m_index]->apply_to_all (mp_ui->relative_cbx->isChecked ()); mp_properties_pages [m_index]->apply_to_all (mp_ui->relative_cbx->isChecked (), false);
} else { } else {
mp_properties_pages [m_index]->apply (); mp_properties_pages [m_index]->apply (false);
} }
mp_properties_pages [m_index]->update (); mp_properties_pages [m_index]->update ();
@ -632,7 +632,7 @@ BEGIN_PROTECTED
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id); db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id);
mp_properties_pages [m_index]->apply (); mp_properties_pages [m_index]->apply (true);
mp_properties_pages [m_index]->update (); mp_properties_pages [m_index]->update ();
if (! t.is_empty ()) { if (! t.is_empty ()) {

View File

@ -105,7 +105,7 @@ private:
void update_controls (); void update_controls ();
public slots: public slots:
void apply (); void properties_edited ();
void next_pressed (); void next_pressed ();
void prev_pressed (); void prev_pressed ();
void cancel_pressed (); void cancel_pressed ();