/* KLayout Layout Viewer Copyright (C) 2006-2016 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "layAnnotationShapes.h" namespace lay { // --------------------------------------------------------------------------------------- // layer_op implementation void AnnotationLayerOp::insert (AnnotationShapes *shapes) { shapes->insert (m_shapes.begin (), m_shapes.end ()); } void AnnotationLayerOp::erase (AnnotationShapes *shapes) { if (size_t (std::distance (shapes->begin (), shapes->end ())) <= m_shapes.size ()) { // If all shapes are to be removed, just clear the list shapes->clear (); } else { // look up the shapes to delete and collect them in a sorted list. Then pass this to // the erase_positions method of the shapes object std::vector done; done.resize (m_shapes.size (), false); std::sort (m_shapes.begin (), m_shapes.end ()); std::vector::const_iterator s_begin = m_shapes.begin (); std::vector::const_iterator s_end = m_shapes.end (); std::vector to_erase; to_erase.reserve (m_shapes.size ()); // This is not quite effective but seems to be the simpliest way // of implementing this: search for each element and erase these. for (AnnotationShapes::layer_type::iterator lsh = shapes->begin (); lsh != shapes->end (); ++lsh) { std::vector::const_iterator s = std::lower_bound (s_begin, s_end, *lsh); while (s != s_end && *s == *lsh && done [std::distance(s_begin, s)]) { ++s; } if (s != s_end && *s == *lsh) { done [std::distance(s_begin, s)] = true; to_erase.push_back (lsh); } } shapes->erase_positions (to_erase.begin (), to_erase.end ()); } } // --------------------------------------------------------------------------------------- // Shapes implementation AnnotationShapes::AnnotationShapes (db::Manager *manager) : db::LayoutStateModel (true /*busy*/), db::Object (manager) { // .. nothing yet .. } AnnotationShapes::AnnotationShapes (const AnnotationShapes &d) : db::LayoutStateModel (true /*busy*/), db::Object (d) { operator= (d); } AnnotationShapes::~AnnotationShapes () { clear (); } AnnotationShapes & AnnotationShapes::operator= (const AnnotationShapes &d) { if (&d != this) { clear (); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new AnnotationLayerOp (true /*insert*/, d.m_layer.begin (), d.m_layer.end ())); } m_layer = d.m_layer; } return *this; } void AnnotationShapes::clear () { if (manager () && manager ()->transacting ()) { manager ()->queue (this, new AnnotationLayerOp (false /*not insert*/, m_layer.begin (), m_layer.end ())); } invalidate_state (); // HINT: must come before the change is done! m_layer.clear (); } const AnnotationShapes::shape_type & AnnotationShapes::insert (const shape_type &sh) { if (manager () && manager ()->transacting ()) { manager ()->queue (this, new AnnotationLayerOp (true /*insert*/, sh)); } invalidate_state (); // HINT: must come before the change is done! return *m_layer.insert (sh); } void AnnotationShapes::reserve (size_t n) { m_layer.reserve (n); } void AnnotationShapes::erase (layer_type::iterator pos) { if (manager () && manager ()->transacting ()) { manager ()->queue (this, new AnnotationLayerOp (false /*not insert*/, *pos)); } invalidate_state (); // HINT: must come before the change is done! m_layer.erase (pos); } const AnnotationShapes::shape_type & AnnotationShapes::replace (iterator pos, const shape_type &sh) { if (&*pos != &sh && *pos != sh) { if (manager () && manager ()->transacting ()) { manager ()->queue (this, new AnnotationLayerOp (false /*not insert*/, *pos)); manager ()->queue (this, new AnnotationLayerOp (true /*insert*/, sh)); } invalidate_state (); // HINT: must come before the change is done! m_layer.replace (pos, sh); } return *pos; } void AnnotationShapes::redo (db::Op *op) { AnnotationLayerOp *layop = dynamic_cast (op); if (layop) { layop->redo (this); } } void AnnotationShapes::undo (db::Op *op) { AnnotationLayerOp *layop = dynamic_cast (op); if (layop) { layop->undo (this); } } void AnnotationShapes::collect_mem_stat (db::MemStatistics &m) const { m_layer.collect_mem_stat (m); } void AnnotationShapes::do_update () { m_layer.sort (); } }