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
PropertiesPage::apply ()
PropertiesPage::apply (bool /*commit*/)
{
ant::Object obj;
get_object (obj);

View File

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

View File

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

View File

@ -66,8 +66,8 @@ protected:
edt::PCellParametersPage *mp_pcell_parameters;
virtual bool readonly ();
virtual void apply ();
virtual void apply_to_all (bool relative);
virtual void apply (bool commit);
virtual void apply_to_all (bool relative, bool commit);
virtual bool can_apply_to_all () const;
void do_apply (bool current_only, bool relative);
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
ShapePropertiesPage::do_apply (bool current_only, bool relative)
ShapePropertiesPage::do_apply (bool current_only, bool relative, bool commit)
{
if (m_indexes.empty ()) {
return;
@ -321,7 +321,7 @@ ShapePropertiesPage::do_apply (bool current_only, bool relative)
}
// 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) {
new_sel[index] = gs.second;
@ -350,9 +350,9 @@ ShapePropertiesPage::do_apply (bool current_only, bool relative)
}
void
ShapePropertiesPage::apply ()
ShapePropertiesPage::apply (bool commit)
{
do_apply (true, false);
do_apply (true, false, commit);
}
bool
@ -362,9 +362,9 @@ ShapePropertiesPage::can_apply_to_all () const
}
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

View File

@ -63,10 +63,10 @@ protected:
private:
virtual void update ();
virtual void apply ();
virtual void apply_to_all (bool relative);
virtual void apply (bool commit);
virtual void apply_to_all (bool relative, bool commit);
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);
protected:

View File

@ -76,6 +76,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIter
m_snap_to_objects (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_pcell_lazy_evaluation (0),
m_hier_copy_mode (-1),
m_indicate_secondary_selection (false),
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);
service_configuration_changed ();
} else if (name == cfg_edit_pcell_lazy_eval_mode) {
tl::from_string (value, m_pcell_lazy_evaluation);
} else {
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));
move_cancel (); // formally this functionality fits here
// accept changes to guiding shapes
handle_guiding_shape_changes ();
handle_guiding_shape_changes (true);
}
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 ();
}
@ -1860,7 +1865,7 @@ Service::add_selection (const lay::ObjectInstPath &sel)
}
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 ();
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 ());
}
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 ());
}
// 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 parent_cell = std::numeric_limits<db::cell_index_type>::max ();
db::Instance parent_inst;
@ -1944,7 +1961,7 @@ Service::handle_guiding_shape_changes (const lay::ObjectInstPath &obj) const
}
bool
Service::handle_guiding_shape_changes ()
Service::handle_guiding_shape_changes (bool commit)
{
EditableSelectionIterator s = begin_selection ();
@ -1953,7 +1970,7 @@ Service::handle_guiding_shape_changes ()
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) {
// 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
*
* @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.
* 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
*
* @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
@ -672,9 +674,12 @@ private:
bool m_snap_to_objects;
bool m_snap_objects_to_grid;
db::DVector m_global_grid;
// Other attributes
bool m_top_level_sel;
bool m_show_shapes_of_instances;
unsigned int m_max_shapes_of_instances;
int m_pcell_lazy_evaluation;
// Hierarchical copy mode (-1: ask, 0: shallow, 1: deep)
int m_hier_copy_mode;

View File

@ -784,7 +784,7 @@ PropertiesPage::reverse_color_order ()
}
void
PropertiesPage::apply ()
PropertiesPage::apply (bool /*commit*/)
{
bool has_error = false;
@ -915,7 +915,7 @@ PropertiesPage::browse ()
{
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 (*)")));
@ -941,7 +941,7 @@ PropertiesPage::save_pressed ()
{
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 (*)")));

View File

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

View File

@ -71,7 +71,7 @@ public:
BEGIN_PROTECTED
properties_frame->set_direct_image (mp_image_object);
properties_frame->apply ();
properties_frame->apply (true);
if (mp_image_object->is_empty ()) {
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
* changed, the object may be left untouched.
* 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.
}
@ -174,8 +176,11 @@ public:
* 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.
* 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.
}

View File

@ -197,7 +197,7 @@ PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager,
}
for (size_t i = 0; i < mp_properties_pages.size (); ++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) ..
@ -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);
mp_properties_pages [m_index]->apply ();
mp_properties_pages [m_index]->apply (true);
if (! t.is_empty ()) {
m_transaction_id = t.id ();
@ -437,7 +437,7 @@ BEGIN_PROTECTED
if (! mp_properties_pages [m_index]->readonly ()) {
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 ()) {
m_transaction_id = t.id ();
}
@ -485,7 +485,7 @@ BEGIN_PROTECTED
if (! mp_properties_pages [m_index]->readonly ()) {
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 ()) {
m_transaction_id = t.id ();
}
@ -567,7 +567,7 @@ PropertiesDialog::any_prev () const
}
void
PropertiesDialog::apply ()
PropertiesDialog::properties_edited ()
{
BEGIN_PROTECTED
@ -580,9 +580,9 @@ BEGIN_PROTECTED
try {
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 {
mp_properties_pages [m_index]->apply ();
mp_properties_pages [m_index]->apply (false);
}
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);
mp_properties_pages [m_index]->apply ();
mp_properties_pages [m_index]->apply (true);
mp_properties_pages [m_index]->update ();
if (! t.is_empty ()) {

View File

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