mirror of https://github.com/KLayout/klayout.git
191 lines
5.1 KiB
C++
191 lines
5.1 KiB
C++
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
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<bool> done;
|
||
|
|
done.resize (m_shapes.size (), false);
|
||
|
|
|
||
|
|
std::sort (m_shapes.begin (), m_shapes.end ());
|
||
|
|
|
||
|
|
std::vector<shape_type>::const_iterator s_begin = m_shapes.begin ();
|
||
|
|
std::vector<shape_type>::const_iterator s_end = m_shapes.end ();
|
||
|
|
|
||
|
|
std::vector<AnnotationShapes::layer_type::iterator> 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<shape_type>::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<AnnotationLayerOp *> (op);
|
||
|
|
if (layop) {
|
||
|
|
layop->redo (this);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
AnnotationShapes::undo (db::Op *op)
|
||
|
|
{
|
||
|
|
AnnotationLayerOp *layop = dynamic_cast<AnnotationLayerOp *> (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 ();
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|