diff --git a/src/db/db/dbCell.cc b/src/db/db/dbCell.cc index c4a81f4f5..346f3d8ab 100644 --- a/src/db/db/dbCell.cc +++ b/src/db/db/dbCell.cc @@ -333,21 +333,13 @@ void Cell::copy (unsigned int src, unsigned int dest) { if (src != dest) { - db::Shapes &dest_shapes = shapes (dest); - db::Cell::shape_iterator src_shape = begin (src, db::Shapes::shape_iterator::All); - while (! src_shape.at_end ()) { - dest_shapes.insert (*src_shape); - ++src_shape; - } + shapes (dest).insert (shapes (src)); } else { // When duplicating the layer, first create a copy to avoid problems with non-stable containers // Hint: using the assignment and not the copy ctor does not copy the db::Manager association. db::Shapes shape_copy; shape_copy = shapes (src); - db::Shapes &dest_shapes = shapes (dest); - for (db::Cell::shape_iterator src_shape = shape_copy.begin (db::Shapes::shape_iterator::All); ! src_shape.at_end (); ++src_shape) { - dest_shapes.insert (*src_shape); - } + shapes (dest).insert (shape_copy); } } diff --git a/src/db/db/dbShapes.cc b/src/db/db/dbShapes.cc index f905f66ed..9a1fdcfbc 100644 --- a/src/db/db/dbShapes.cc +++ b/src/db/db/dbShapes.cc @@ -138,11 +138,25 @@ void FullLayerOp::insert (Shapes *shapes) { for (tl::vector::iterator l = shapes->get_layers ().end (); l != shapes->get_layers ().begin (); ) { + --l; + if (*l == mp_layer) { + return; + + } else if ((*l)->is_same_type (mp_layer)) { + + delete (*l); + *l = mp_layer; + m_owns_layer = false; + shapes->invalidate_state (); + return; + } + } + shapes->get_layers ().push_back (mp_layer); shapes->invalidate_state (); m_owns_layer = false; @@ -984,7 +998,10 @@ Shapes::clear () { if (!m_layers.empty ()) { - for (tl::vector::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { + for (tl::vector::const_iterator l = m_layers.end (); l != m_layers.begin (); ) { + // because the undo stack will do a push, we need to remove layers from the back (this is the last undo + // element to be executed) + --l; if (manager () && manager ()->transacting ()) { check_is_editable_for_undo_redo (); manager ()->queue (this, new FullLayerOp (false, (*l))); diff --git a/src/db/db/dbShapes.h b/src/db/db/dbShapes.h index 234d42e1d..96cd0f41a 100644 --- a/src/db/db/dbShapes.h +++ b/src/db/db/dbShapes.h @@ -487,6 +487,7 @@ public: virtual bool empty () const = 0; virtual void sort () = 0; virtual LayerBase *clone () const = 0; + virtual bool is_same_type (const LayerBase *other) const = 0; virtual void translate_into (Shapes *target, GenericRepository &rep, ArrayRepository &array_rep) const = 0; virtual void translate_into (Shapes *target, GenericRepository &rep, ArrayRepository &array_rep, pm_delegate_type &pm) const = 0; virtual void transform_into (Shapes *target, const Trans &trans, GenericRepository &rep, ArrayRepository &array_rep) const = 0; diff --git a/src/db/db/dbShapes2.h b/src/db/db/dbShapes2.h index 1e86aa4e9..9f66bf33b 100644 --- a/src/db/db/dbShapes2.h +++ b/src/db/db/dbShapes2.h @@ -141,6 +141,11 @@ public: m_layer.sort (); } + virtual bool is_same_type (const LayerBase *other) const + { + return dynamic_cast *> (other); + } + virtual LayerBase *clone () const; virtual void translate_into (Shapes *target, GenericRepository &rep, ArrayRepository &array_rep) const; virtual void translate_into (Shapes *target, GenericRepository &rep, ArrayRepository &array_rep, pm_delegate_type &pm) const; diff --git a/src/db/unit_tests/dbLayoutTests.cc b/src/db/unit_tests/dbLayoutTests.cc index 2a431739a..c4630e5ae 100644 --- a/src/db/unit_tests/dbLayoutTests.cc +++ b/src/db/unit_tests/dbLayoutTests.cc @@ -557,9 +557,13 @@ TEST(5) EXPECT_EQ (l2s (l), "begin_lib 0.001\nbegin_cell {LIBCELL}\nbox 1 0 {0 0} {100 200}\nend_cell\nend_lib\n"); // switch to another LIBCELL, this time using layer 2/0 - m.transaction ("switch_to_b"); - l.set_technology_name ("B"); - m.commit (); + if (l.is_editable ()) { + m.transaction ("switch_to_b"); + l.set_technology_name ("B"); + m.commit (); + } else { + l.set_technology_name ("B"); + } EXPECT_EQ (l.technology_name (), "B"); cell = &l.cell (l.cell_by_name ("LIBCELL").second); @@ -609,9 +613,13 @@ TEST(6) info.pcell_parameters ["npoints"] = tl::Variant (8); info.pcell_parameters ["layer"] = tl::Variant (db::LayerProperties (1, 0)); - m.transaction ("import"); + if (l.is_editable ()) { + m.transaction ("import"); + } cell = l.recover_proxy (info); - m.commit (); + if (l.is_editable ()) { + m.commit (); + } EXPECT_EQ (cell->get_qualified_name (), "Basic.CIRCLE"); EXPECT_EQ (cell->get_basic_name (), "CIRCLE"); EXPECT_EQ (cell->get_display_name (), "Basic.CIRCLE(l=1/0,r=10,n=8)"); @@ -622,10 +630,14 @@ TEST(6) l.get_context_info (cell->cell_index (), info2); info2.pcell_parameters ["actual_radius"] = tl::Variant (5.0); - m.transaction ("modify"); + if (l.is_editable ()) { + m.transaction ("modify"); + } db::cell_index_type ci = cell->cell_index (); l.recover_proxy_as (ci, info2); - m.commit (); + if (l.is_editable ()) { + m.commit (); + } cell = &l.cell (ci); EXPECT_EQ (cell->get_qualified_name (), "Basic.CIRCLE"); EXPECT_EQ (cell->get_basic_name (), "CIRCLE"); diff --git a/testdata/ruby/dbLayout.rb b/testdata/ruby/dbLayout.rb index b9723def0..9479f4f84 100644 --- a/testdata/ruby/dbLayout.rb +++ b/testdata/ruby/dbLayout.rb @@ -901,103 +901,98 @@ class DBLayout_TestClass < TestBase assert_equal(dump_layer(lll, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (1200,0;2200,1100); (-1200,0;-100,1000); (-1200,0;-100,1000)") assert_equal(dump_layer(lll, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") - # TODO: undo tests crashes in non-editable mode! Should be checked properly. - if lll.is_editable? + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, false) + assert_equal(m.transaction_for_undo, "9") - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, false) - assert_equal(m.transaction_for_undo, "9") + m.undo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_undo, "8") - m.undo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_undo, "8") + assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (1200,0;2200,1100); (-1200,0;-100,1000); (-1200,0;-100,1000)") + assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") - assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (1200,0;2200,1100); (-1200,0;-100,1000); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") + m.undo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_undo, "7") - m.undo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_undo, "7") + assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (-1200,0;-100,1000)") + assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") - assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") + m.undo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_undo, "6") - m.undo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_undo, "6") + assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (1200,0;2200,1100); (-1200,0;-100,1000)") + assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100)") - assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100)") + m.undo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_undo, "5") - m.undo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_undo, "5") + assert_equal(dump_layer(l, 0, "c0"), "(1200,0;2200,1100); (-1200,0;-100,1000)") + assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100)") - assert_equal(dump_layer(l, 0, "c0"), "(1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100)") + m.undo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_undo, "4") - m.undo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_undo, "4") + assert_equal(dump_layer(l, 0, "c0"), "") + assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 0, "c0"), "") - assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") + m.undo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_undo, "3") - m.undo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_undo, "3") + assert_equal(dump_layer(l, 1, "c0"), "") + assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 1, "c0"), "") - assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") + m.undo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_undo, "2") - m.undo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_undo, "2") + assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") + assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") + m.undo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_undo, "1") - m.undo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_undo, "1") + assert_equal(dump_layer(l, 0, "c0"), "") + assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 0, "c0"), "") - assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") + m.undo + assert_equal(m.has_undo?, false) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_redo, "1") - m.undo - assert_equal(m.has_undo?, false) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_redo, "1") + assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") + assert_equal(dump_layer(l, 1, "c0"), "") - assert_equal(dump_layer(l, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 1, "c0"), "") + m.redo + assert_equal(m.has_undo?, true) + assert_equal(m.has_redo?, true) + assert_equal(m.transaction_for_redo, "2") - m.redo - assert_equal(m.has_undo?, true) - assert_equal(m.has_redo?, true) - assert_equal(m.transaction_for_redo, "2") + assert_equal(dump_layer(l, 0, "c0"), "") + assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") - assert_equal(dump_layer(l, 0, "c0"), "") - assert_equal(dump_layer(l, 1, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (100,0;1100,1100); (1200,0;2200,1100); (-1200,0;-100,1000)") + assert_equal(dump_layer(ll, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (1200,0;2200,1100); (-1200,0;-100,1000); (-1200,0;-100,1000)") + assert_equal(dump_layer(ll, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") - assert_equal(dump_layer(ll, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (1200,0;2200,1100); (-1200,0;-100,1000); (-1200,0;-100,1000)") - assert_equal(dump_layer(ll, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") + l.destroy + m.destroy - l.destroy - m.destroy - - assert_equal(dump_layer(lll, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (1200,0;2200,1100); (-1200,0;-100,1000); (-1200,0;-100,1000)") - assert_equal(dump_layer(lll, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") - - end + assert_equal(dump_layer(lll, 0, "c0"), "(0,100;1000,1200); (0,100;1000,1200); (1200,0;2200,1100); (1200,0;2200,1100); (-1200,0;-100,1000); (-1200,0;-100,1000)") + assert_equal(dump_layer(lll, 1, "c0"), "(0,100;1000,1200); (100,0;1100,1100)") end