mirror of https://github.com/KLayout/klayout.git
Merge pull request #865 from KLayout/issue-864
Fixed #864 (Shapes#copy_shapes does not support undo/redo)
This commit is contained in:
commit
054bfa3be4
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -837,6 +837,14 @@ Instance::bbox () const
|
|||
// -------------------------------------------------------------------------------------
|
||||
// Instances implementation
|
||||
|
||||
static void
|
||||
check_is_editable_for_undo_redo (const Instances *instances)
|
||||
{
|
||||
if (! instances->is_editable ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("No undo/redo support on non-editable instance lists")));
|
||||
}
|
||||
}
|
||||
|
||||
Instances::Instances (cell_type *cell)
|
||||
: mp_cell (cell)
|
||||
{
|
||||
|
|
@ -957,6 +965,10 @@ Instances::erase_positions (Tag tag, ET editable_tag, I first, I last)
|
|||
if (mp_cell) {
|
||||
mp_cell->invalidate_insts (); // HINT: must come before the change is done!
|
||||
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo (this);
|
||||
if (! is_editable ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("No undo/redo support for non-editable instance lists in 'erase_positions'")));
|
||||
}
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, first, last, true /*dummy*/));
|
||||
}
|
||||
}
|
||||
|
|
@ -973,6 +985,7 @@ Instances::insert (const InstArray &inst)
|
|||
|
||||
if (mp_cell) {
|
||||
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo (this);
|
||||
if (editable) {
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesEditableTag> (true /*insert*/, inst));
|
||||
} else {
|
||||
|
|
@ -999,6 +1012,7 @@ Instances::insert (I from, I to)
|
|||
|
||||
if (mp_cell) {
|
||||
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo (this);
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<typename it_traits::value_type, ET> (true /*insert*/, from, to));
|
||||
}
|
||||
mp_cell->invalidate_insts ();
|
||||
|
|
@ -1049,6 +1063,7 @@ Instances::replace (const InstArray *replace, const InstArray &with)
|
|||
{
|
||||
if (mp_cell) {
|
||||
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo (this);
|
||||
if (is_editable ()) {
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesEditableTag> (false /*not insert*/, *replace));
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<InstArray, InstancesEditableTag> (true /*insert*/, with));
|
||||
|
|
@ -1138,6 +1153,7 @@ Instances::erase_inst_by_iter (Tag tag, ET editable_tag, I iter)
|
|||
if (mp_cell) {
|
||||
mp_cell->invalidate_insts ();
|
||||
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo (this);
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, *iter));
|
||||
}
|
||||
}
|
||||
|
|
@ -1152,6 +1168,7 @@ Instances::erase_inst_by_tag (Tag tag, ET editable_tag, const typename Tag::obje
|
|||
if (mp_cell) {
|
||||
mp_cell->invalidate_insts ();
|
||||
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo (this);
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<typename Tag::object_type, ET> (false /*not insert*/, obj));
|
||||
}
|
||||
}
|
||||
|
|
@ -1183,6 +1200,7 @@ Instances::clear_insts (ET editable_tag)
|
|||
if (mp_cell) {
|
||||
mp_cell->invalidate_insts ();
|
||||
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo (this);
|
||||
const Instances *const_this = this;
|
||||
if (! const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).empty ()) {
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<cell_inst_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).end ()));
|
||||
|
|
@ -1588,6 +1606,7 @@ void Instances::apply_op (const Op &op, ET editable_tag)
|
|||
if (mp_cell) {
|
||||
mp_cell->invalidate_insts ();
|
||||
if (mp_cell->manager () && mp_cell->manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo (this);
|
||||
transacting = true;
|
||||
if (has_insts) {
|
||||
mp_cell->manager ()->queue (mp_cell, new db::InstOp<cell_inst_array_type, ET> (false /*not insert*/, const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).begin (), const_this->inst_tree (cell_inst_array_type::tag (), editable_tag).end ()));
|
||||
|
|
|
|||
|
|
@ -131,6 +131,50 @@ layer_op<Sh, StableTag>::erase (Shapes *shapes)
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// FullLayerOp implementation
|
||||
|
||||
void
|
||||
FullLayerOp::insert (Shapes *shapes)
|
||||
{
|
||||
for (tl::vector<LayerBase *>::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;
|
||||
}
|
||||
|
||||
void
|
||||
FullLayerOp::erase (Shapes *shapes)
|
||||
{
|
||||
for (tl::vector<LayerBase *>::iterator l = shapes->get_layers ().begin (); l != shapes->get_layers ().end (); ++l) {
|
||||
if (*l == mp_layer) {
|
||||
shapes->get_layers ().erase (l);
|
||||
shapes->invalidate_state ();
|
||||
m_owns_layer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// Shapes implementation
|
||||
|
||||
|
|
@ -155,11 +199,17 @@ Shapes::layout () const
|
|||
return c ? c->layout () : 0;
|
||||
}
|
||||
|
||||
void
|
||||
Shapes::check_is_editable_for_undo_redo () const
|
||||
{
|
||||
if (! is_editable ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("No undo/redo support on non-editable shape lists")));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Shapes::insert (const Shapes &d)
|
||||
{
|
||||
// no undo support for this currently
|
||||
tl_assert (! manager () || ! manager ()->transacting ());
|
||||
do_insert (d);
|
||||
}
|
||||
|
||||
|
|
@ -175,10 +225,18 @@ Shapes::do_insert (const Shapes &d)
|
|||
|
||||
// both shape containers reside in the same repository space - simply copy
|
||||
if (m_layers.empty ()) {
|
||||
|
||||
m_layers.reserve (d.m_layers.size ());
|
||||
for (tl::vector<LayerBase *>::const_iterator l = d.m_layers.begin (); l != d.m_layers.end (); ++l) {
|
||||
m_layers.push_back ((*l)->clone (this, manager ()));
|
||||
m_layers.push_back ((*l)->clone ());
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
manager ()->queue (this, new FullLayerOp (true, m_layers.back ()));
|
||||
}
|
||||
}
|
||||
|
||||
invalidate_state ();
|
||||
|
||||
} else {
|
||||
for (tl::vector<LayerBase *>::const_iterator l = d.m_layers.begin (); l != d.m_layers.end (); ++l) {
|
||||
(*l)->insert_into (this);
|
||||
|
|
@ -939,12 +997,22 @@ void
|
|||
Shapes::clear ()
|
||||
{
|
||||
if (!m_layers.empty ()) {
|
||||
for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
||||
(*l)->clear (this, manager ());
|
||||
delete *l;
|
||||
|
||||
for (tl::vector<LayerBase *>::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)));
|
||||
} else {
|
||||
delete *l;
|
||||
}
|
||||
}
|
||||
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
m_layers.clear ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1104,6 +1172,7 @@ Shapes::replace_prop_id (const Sh *pos, db::properties_id_type prop_id)
|
|||
throw tl::Exception (tl::to_string (tr ("Function 'replace' is permitted only in editable mode")));
|
||||
}
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<Sh, db::stable_layer_tag>::queue_or_append (manager (), this, false /*not insert*/, *pos);
|
||||
}
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
|
@ -1123,6 +1192,7 @@ Shapes::replace_prop_id_iter (typename db::object_tag<Sh>, const Iter &iter, db:
|
|||
}
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<Sh, db::stable_layer_tag>::queue_or_append (manager (), this, false /*not insert*/, *iter);
|
||||
}
|
||||
db::object_with_properties <Sh> wp (*iter, prop_id);
|
||||
|
|
@ -1190,6 +1260,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh> tag, const shape_
|
|||
// simple replace case
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<Sh, db::stable_layer_tag>::queue_or_append (manager (), this, false /*not insert*/, *ref.basic_ptr (tag));
|
||||
}
|
||||
|
||||
|
|
@ -1214,6 +1285,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh> tag, const shape_
|
|||
if (! ref.with_props ()) {
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<Sh, db::stable_layer_tag>::queue_or_append (manager (), this, false /*not insert*/, *ref.basic_ptr (tag));
|
||||
}
|
||||
|
||||
|
|
@ -1234,6 +1306,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh> tag, const shape_
|
|||
get_layer<Sh, db::stable_layer_tag> ().replace (ref.basic_iter (tag), sh);
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<Sh, db::stable_layer_tag>::queue_or_append (manager (), this, true /*insert*/, sh);
|
||||
}
|
||||
|
||||
|
|
@ -1242,6 +1315,7 @@ Shapes::replace_member_with_props (typename db::object_tag<Sh> tag, const shape_
|
|||
} else {
|
||||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<db::object_with_properties<Sh>, db::stable_layer_tag>::queue_or_append (manager (), this, false /*not insert*/, *ref.basic_ptr (typename db::object_with_properties<Sh>::tag ()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -486,8 +486,8 @@ public:
|
|||
virtual size_t size () const = 0;
|
||||
virtual bool empty () const = 0;
|
||||
virtual void sort () = 0;
|
||||
virtual void clear (Shapes *target, db::Manager *manager) = 0;
|
||||
virtual LayerBase *clone (Shapes *target, db::Manager *manager) const = 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;
|
||||
|
|
@ -682,6 +682,8 @@ public:
|
|||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
|
||||
check_is_editable_for_undo_redo ();
|
||||
|
||||
tl::ident_map<db::properties_id_type> pm;
|
||||
|
||||
// for undo support iterate over the elements
|
||||
|
|
@ -721,6 +723,8 @@ public:
|
|||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
|
||||
check_is_editable_for_undo_redo ();
|
||||
|
||||
// for undo support iterate over the elements
|
||||
for (ShapeIterator s = d.begin (ShapeIterator::All); ! s.at_end (); ++s) {
|
||||
insert (*s, trans, pm);
|
||||
|
|
@ -760,6 +764,8 @@ public:
|
|||
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
|
||||
check_is_editable_for_undo_redo ();
|
||||
|
||||
// for undo support iterate over the elements
|
||||
for (ShapeIterator s = d.begin (ShapeIterator::All); ! s.at_end (); ++s) {
|
||||
insert (*s, pm);
|
||||
|
|
@ -806,6 +812,7 @@ public:
|
|||
shape_type insert (const Sh &sh)
|
||||
{
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
if (is_editable ()) {
|
||||
db::layer_op<Sh, db::stable_layer_tag>::queue_or_append (manager (), this, true /*insert*/, sh);
|
||||
} else {
|
||||
|
|
@ -849,6 +856,7 @@ public:
|
|||
|
||||
// insert the array as a whole in non-editable mode
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<db::array<Obj, Trans>, db::unstable_layer_tag>::queue_or_append (manager (), this, true /*insert*/, arr);
|
||||
}
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
|
@ -886,6 +894,7 @@ public:
|
|||
|
||||
// insert the array as a whole in non-editable mode
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op< db::object_with_properties< db::array<Obj, Trans> >, db::unstable_layer_tag>::queue_or_append (manager (), this, true /*insert*/, arr);
|
||||
}
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
|
@ -906,6 +915,7 @@ public:
|
|||
{
|
||||
typedef typename std::iterator_traits <Iter>::value_type value_type;
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
if (is_editable ()) {
|
||||
db::layer_op<value_type, db::stable_layer_tag>::queue_or_append (manager (), this, true /*insert*/, from, to);
|
||||
} else {
|
||||
|
|
@ -1001,6 +1011,7 @@ public:
|
|||
throw tl::Exception (tl::to_string (tr ("Function 'erase' is permitted only in editable mode")));
|
||||
}
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<typename Tag::object_type, StableTag>::queue_or_append (manager (), this, false /*not insert*/, *pos);
|
||||
}
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
|
@ -1064,6 +1075,7 @@ public:
|
|||
throw tl::Exception (tl::to_string (tr ("Function 'erase' is permitted only in editable mode")));
|
||||
}
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<typename Tag::object_type, StableTag>::queue_or_append (manager (), this, false /*not insert*/, from, to);
|
||||
}
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
|
@ -1090,6 +1102,7 @@ public:
|
|||
throw tl::Exception (tl::to_string (tr ("Function 'erase' is permitted only in editable mode")));
|
||||
}
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<typename Tag::object_type, StableTag>::queue_or_append (manager (), this, false /*not insert*/, first, last, true /*dummy*/);
|
||||
}
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
|
@ -1480,12 +1493,20 @@ public:
|
|||
|
||||
private:
|
||||
friend class ShapeIterator;
|
||||
friend class FullLayerOp;
|
||||
|
||||
tl::vector<LayerBase *> m_layers;
|
||||
db::Cell *mp_cell; // HINT: contains "dirty" in bit 0 and "editable" in bit 1
|
||||
|
||||
void invalidate_state ();
|
||||
void do_insert (const Shapes &d);
|
||||
void check_is_editable_for_undo_redo () const;
|
||||
|
||||
// gets the layers array
|
||||
tl::vector<LayerBase *> &get_layers ()
|
||||
{
|
||||
return m_layers;
|
||||
}
|
||||
|
||||
// extract dirty flag from mp_cell
|
||||
bool is_dirty () const
|
||||
|
|
@ -1604,6 +1625,7 @@ private:
|
|||
for (typename Array::iterator a = arr.begin (); ! a.at_end (); ++a) {
|
||||
res_wp_type obj_wp (*a * arr.object (), arr.properties_id ());
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<res_wp_type, db::stable_layer_tag>::queue_or_append (manager (), this, true /*insert*/, obj_wp);
|
||||
}
|
||||
l.insert (obj_wp);
|
||||
|
|
@ -1618,6 +1640,7 @@ private:
|
|||
db::layer<ResType, db::stable_layer_tag> &l = get_layer<ResType, db::stable_layer_tag> ();
|
||||
for (typename Array::iterator a = arr.begin (); ! a.at_end (); ++a) {
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<ResType, db::stable_layer_tag>::queue_or_append (manager (), this, true /*insert*/, *a * arr.object ());
|
||||
}
|
||||
l.insert (*a * arr.object ());
|
||||
|
|
@ -1743,6 +1766,51 @@ private:
|
|||
void erase (Shapes *shapes);
|
||||
};
|
||||
|
||||
class FullLayerOp
|
||||
: public LayerOpBase
|
||||
{
|
||||
public:
|
||||
FullLayerOp (bool insert, LayerBase *layer)
|
||||
: m_insert (insert), mp_layer (layer), m_owns_layer (! insert)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
~FullLayerOp ()
|
||||
{
|
||||
if (m_owns_layer) {
|
||||
delete mp_layer;
|
||||
mp_layer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo (Shapes *shapes)
|
||||
{
|
||||
if (m_insert) {
|
||||
erase (shapes);
|
||||
} else {
|
||||
insert (shapes);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void redo (Shapes *shapes)
|
||||
{
|
||||
if (m_insert) {
|
||||
insert (shapes);
|
||||
} else {
|
||||
erase (shapes);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_insert;
|
||||
LayerBase *mp_layer;
|
||||
bool m_owns_layer;
|
||||
|
||||
void insert (Shapes *shapes);
|
||||
void erase (Shapes *shapes);
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -752,24 +752,11 @@ inline unsigned int iterator_type_mask (db::object_tag< db::object_with_properti
|
|||
return iterator_type_mask (typename Sh::tag ());
|
||||
}
|
||||
|
||||
template <class Sh, class StableTag>
|
||||
void
|
||||
layer_class<Sh, StableTag>::clear (Shapes *target, db::Manager *manager)
|
||||
{
|
||||
if (manager && manager->transacting ()) {
|
||||
manager->queue (target, new db::layer_op<Sh, StableTag> (false /*not insert*/, m_layer.begin (), m_layer.end ()));
|
||||
}
|
||||
m_layer.clear ();
|
||||
}
|
||||
|
||||
template <class Sh, class StableTag>
|
||||
LayerBase *
|
||||
layer_class<Sh, StableTag>::clone (Shapes *target, db::Manager *manager) const
|
||||
layer_class<Sh, StableTag>::clone () const
|
||||
{
|
||||
layer_class<Sh, StableTag> *r = new layer_class<Sh, StableTag> ();
|
||||
if (manager && manager->transacting ()) {
|
||||
manager->queue (target, new db::layer_op<Sh, StableTag> (true /*insert*/, m_layer.begin (), m_layer.end ()));
|
||||
}
|
||||
r->m_layer = m_layer;
|
||||
return r;
|
||||
}
|
||||
|
|
@ -877,7 +864,6 @@ layer_class<Sh, StableTag>::deref_and_transform_into (Shapes *target, const Tran
|
|||
{
|
||||
deref_and_transform_into_shapes deref_op (target);
|
||||
for (typename layer_type::iterator s = m_layer.begin (); s != m_layer.end (); ++s) {
|
||||
|
||||
deref_op (*s, trans, pm);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,12 @@ public:
|
|||
m_layer.sort ();
|
||||
}
|
||||
|
||||
virtual void clear (Shapes *target, db::Manager *manager);
|
||||
virtual LayerBase *clone (Shapes *target, db::Manager *manager) const;
|
||||
virtual bool is_same_type (const LayerBase *other) const
|
||||
{
|
||||
return dynamic_cast<const layer_class<Sh, StableTag> *> (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;
|
||||
virtual void transform_into (Shapes *target, const Trans &trans, GenericRepository &rep, ArrayRepository &array_rep) const;
|
||||
|
|
|
|||
|
|
@ -344,6 +344,7 @@ Shapes::erase_shape_by_tag_ws (Tag /*tag*/, StableTag /*stable_tag*/, const shap
|
|||
db::layer<typename Tag::object_type, StableTag> &l = get_layer<typename Tag::object_type, StableTag> ();
|
||||
typename db::layer<typename Tag::object_type, StableTag>::iterator i = iterator_from_shape (l, shape);
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<typename Tag::object_type, StableTag>::queue_or_append (manager (), this, false /*not insert*/, *i);
|
||||
}
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
|
@ -356,6 +357,7 @@ Shapes::erase_shape_by_tag_ws (Tag /*tag*/, StableTag /*stable_tag*/, const shap
|
|||
db::layer<swp_type, StableTag> &l = get_layer<swp_type, StableTag> ();
|
||||
typename db::layer<swp_type, StableTag>::iterator i = iterator_from_shape (l, shape);
|
||||
if (manager () && manager ()->transacting ()) {
|
||||
check_is_editable_for_undo_redo ();
|
||||
db::layer_op<swp_type, StableTag>::queue_or_append (manager (), this, false /*not insert*/, *i);
|
||||
}
|
||||
invalidate_state (); // HINT: must come before the change is done!
|
||||
|
|
|
|||
|
|
@ -246,12 +246,7 @@ static void insert_iter_with_trans (db::Shapes *sh, const db::RecursiveShapeIter
|
|||
|
||||
static void insert_shapes (db::Shapes *sh, const db::Shapes &s)
|
||||
{
|
||||
// NOTE: if the source (r) is from the same layout than the shapes live in, we better
|
||||
// lock the layout against updates while inserting
|
||||
db::LayoutLocker locker (sh->layout ());
|
||||
for (db::Shapes::shape_iterator i = s.begin (db::ShapeIterator::All); !i.at_end(); ++i) {
|
||||
sh->insert (*i);
|
||||
}
|
||||
sh->insert (s);
|
||||
}
|
||||
|
||||
static void insert_shapes_with_flags (db::Shapes *sh, const db::Shapes &s, unsigned int flags)
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -3235,6 +3235,193 @@ TEST(23)
|
|||
EXPECT_EQ (shapes_to_string_norm (_this, s2), "edge_pair (0,0;1,1)/(10,10;11,11) #17\n");
|
||||
}
|
||||
|
||||
// Shape insert and clear and undo/redo
|
||||
TEST(24a)
|
||||
{
|
||||
db::Manager m;
|
||||
db::Shapes s1 (&m, 0, true), s2;
|
||||
|
||||
s2.insert (db::Edge (db::Point (0, 0), db::Point (100, 200)));
|
||||
s2.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
s1.insert (s2);
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nedge (0,0;100,200) #0\n");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.undo ();
|
||||
s1.insert (db::Box (db::Point (1, 1), db::Point (101, 201)));
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
s1.insert (s2);
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
s1.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
}
|
||||
|
||||
// Shape insert and clear and undo/redo - different layers, same layout
|
||||
TEST(24b)
|
||||
{
|
||||
db::Manager m;
|
||||
db::Layout l (true, &m);
|
||||
db::Cell &cell = l.cell (l.add_cell ("top"));
|
||||
l.insert_layer (1);
|
||||
l.insert_layer (2);
|
||||
db::Shapes &s1 = cell.shapes (1);
|
||||
db::Shapes &s2 = cell.shapes (2);
|
||||
|
||||
s2.insert (db::Edge (db::Point (0, 0), db::Point (100, 200)));
|
||||
s2.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
s1.insert (s2);
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nedge (0,0;100,200) #0\n");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.undo ();
|
||||
s1.insert (db::Box (db::Point (1, 1), db::Point (101, 201)));
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
s1.insert (s2);
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
s1.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
}
|
||||
|
||||
// Shape insert and clear and undo/redo - no layout on target
|
||||
TEST(24c)
|
||||
{
|
||||
db::Manager m;
|
||||
db::Layout l;
|
||||
db::Cell &cell = l.cell (l.add_cell ("top"));
|
||||
l.insert_layer (1);
|
||||
l.insert_layer (2);
|
||||
db::Shapes s1 (&m, 0, true);
|
||||
db::Shapes &s2 = cell.shapes (2);
|
||||
|
||||
s2.insert (db::Edge (db::Point (0, 0), db::Point (100, 200)));
|
||||
s2.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
s1.insert (s2);
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nedge (0,0;100,200) #0\n");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.undo ();
|
||||
s1.insert (db::Box (db::Point (1, 1), db::Point (101, 201)));
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
s1.insert (s2);
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
s1.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
}
|
||||
|
||||
// Bug #107
|
||||
TEST(100)
|
||||
{
|
||||
|
|
@ -3262,6 +3449,72 @@ TEST(100)
|
|||
);
|
||||
}
|
||||
|
||||
// Shape insert and clear and undo/redo - different layouts
|
||||
TEST(24d)
|
||||
{
|
||||
db::Manager m;
|
||||
db::Layout l1 (true, &m);
|
||||
db::Cell &cell1 = l1.cell (l1.add_cell ("top"));
|
||||
l1.insert_layer (1);
|
||||
db::Layout l2 (true, &m);
|
||||
db::Cell &cell2 = l2.cell (l2.add_cell ("top"));
|
||||
l2.insert_layer (2);
|
||||
db::Shapes &s1 = cell1.shapes (1);
|
||||
db::Shapes &s2 = cell2.shapes (2);
|
||||
|
||||
s2.insert (db::Edge (db::Point (0, 0), db::Point (100, 200)));
|
||||
s2.insert (db::Box (db::Point (0, 0), db::Point (100, 200)));
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
s1.insert (s2);
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nedge (0,0;100,200) #0\n");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.undo ();
|
||||
s1.insert (db::Box (db::Point (1, 1), db::Point (101, 201)));
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
s1.insert (s2);
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (1,1;101,201) #0\n");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.transaction ("test");
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
s1.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
m.commit ();
|
||||
|
||||
m.undo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "box (0,0;100,200) #0\nbox (1,1;101,201) #0\nedge (0,0;100,200) #0\n");
|
||||
|
||||
m.redo ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
|
||||
m.clear ();
|
||||
EXPECT_EQ (shapes_to_string_norm (_this, s1), "");
|
||||
}
|
||||
|
||||
// Bug #835
|
||||
TEST(101)
|
||||
{
|
||||
|
|
@ -3322,3 +3575,4 @@ TEST(101)
|
|||
const db::Path &qr2_obj = *b.shape_repository ().repository (db::Path::tag ()).begin ();
|
||||
EXPECT_EQ (& qr2.obj () == &qr2_obj, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue