]> Shamusworld >> Repos - architektonas/blob - src/base/rs_entitycontainer.cpp
In the middle of major refactoring...
[architektonas] / src / base / rs_entitycontainer.cpp
1 // rs_entitycontainer.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -----------------------------------------------------------
12 // JLH  05/28/2010  Added this text. :-)
13 //
14
15 #include "rs_entitycontainer.h"
16
17 #include "rs_debug.h"
18 #include "rs_dimension.h"
19 #include "rs_math.h"
20 #include "rs_layer.h"
21 #include "rs_line.h"
22 #include "rs_polyline.h"
23 #include "rs_text.h"
24 #include "rs_insert.h"
25 #include "rs_spline.h"
26 #include "rs_information.h"
27 #include "graphicview.h"
28 #include "paintinterface.h"
29
30 bool RS_EntityContainer::autoUpdateBorders = true;
31
32 /**
33  * Default constructor.
34  *
35  * @param owner True if we own and also delete the entities.
36  */
37 RS_EntityContainer::RS_EntityContainer(RS_EntityContainer * parent/*= NULL*/, bool owner/*= true*/):
38         RS_Entity(parent), entityIterator(entities)
39 //NOTE: This constructor may not be explicitly OR implicitly called, meaning that
40 //      entityIterator will not get initialized!
41 {
42 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
43 //    entities.setAutoDelete(owner);
44         RS_DEBUG->print("RS_EntityContainer::RS_EntityContainer: owner: %d", (int)owner);
45     subContainer = NULL;
46     //autoUpdateBorders = true;
47 }
48
49 /**
50  * Copy constructor. Makes a deep copy of all entities.
51  */
52 /*
53 RS_EntityContainer::RS_EntityContainer(const RS_EntityContainer& ec)
54  : RS_Entity(ec)
55 {
56 }
57 */
58
59 /**
60  * Destructor.
61  */
62 RS_EntityContainer::~RS_EntityContainer()
63 {
64         clear();
65 }
66
67 RS_Entity * RS_EntityContainer::clone()
68 {
69 //      RS_DEBUG->print("RS_EntityContainer::clone: ori autoDel: %d", entities.autoDelete());
70         RS_EntityContainer * ec = new RS_EntityContainer(*this);
71 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
72 //      ec->entities.setAutoDelete(entities.autoDelete());
73 //      RS_DEBUG->print("RS_EntityContainer::clone: clone autoDel: %d", ec->entities.autoDelete());
74         ec->detach();
75         ec->initId();
76
77         return ec;
78 }
79
80 /**
81  * Detaches shallow copies and creates deep copies of all subentities.
82  * This is called after cloning entity containers.
83  */
84 void RS_EntityContainer::detach()
85 {
86 //    Q3PtrList<RS_Entity> tmp;
87         QList<RS_Entity *> tmp;
88 #warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!"
89 //      bool autoDel = entities.autoDelete();
90 //      RS_DEBUG->print("RS_EntityContainer::detach: autoDel: %d", (int)autoDel);
91 //      entities.setAutoDelete(false);
92
93         // make deep copies of all entities:
94         for(RS_Entity * e=firstEntity(); e!=NULL; e=nextEntity())
95         {
96                 if (!e->getFlag(RS2::FlagTemp))
97                 {
98                         tmp.append(e->clone());
99                 }
100         }
101
102         // clear shared pointers:
103         entities.clear();
104 //      entities.setAutoDelete(autoDel);
105
106         // point to new deep copies:
107 //      for(RS_Entity * e=tmp.first(); e!=NULL; e=tmp.next())
108         for(int i=0; i<tmp.size(); i++)
109         {
110                 RS_Entity * e = tmp[i];
111                 entities.append(e);
112                 e->reparent(this);
113         }
114 }
115
116 /** @return RS2::EntityContainer */
117 /*virtual*/ RS2::EntityType RS_EntityContainer::rtti() const
118 {
119         return RS2::EntityContainer;
120 }
121
122 void RS_EntityContainer::reparent(RS_EntityContainer * parent)
123 {
124     RS_Entity::reparent(parent);
125
126     // All sub-entities:
127     for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
128         {
129         e->reparent(parent);
130     }
131 }
132
133 /**
134  * @return true: because entities made from this class
135  *         and subclasses are containers for other entities.
136  */
137 /*virtual*/ bool RS_EntityContainer::isContainer() const
138 {
139         return true;
140 }
141
142 /**
143  * @return false: because entities made from this class
144  *         and subclasses are containers for other entities.
145  */
146 /*virtual*/ bool RS_EntityContainer::isAtomic() const
147 {
148         return false;
149 }
150
151 /**
152  * Called when the undo state changed. Forwards the event to all sub-entities.
153  *
154  * @param undone true: entity has become invisible.
155  *               false: entity has become visible.
156  */
157 void RS_EntityContainer::undoStateChanged(bool undone)
158 {
159     RS_Entity::undoStateChanged(undone);
160
161     // ! don't pass on to subentities. undo list handles them
162     // All sub-entities:
163     /*for (RS_Entity* e=firstEntity(RS2::ResolveNone);
164             e!=NULL;
165             e=nextEntity(RS2::ResolveNone)) {
166         e->setUndoState(undone);
167 }*/
168 }
169
170 void RS_EntityContainer::setVisible(bool v)
171 {
172     RS_DEBUG->print("RS_EntityContainer::setVisible: %d", v);
173     RS_Entity::setVisible(v);
174
175     // All sub-entities:
176     for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
177         {
178         RS_DEBUG->print("RS_EntityContainer::setVisible: subentity: %d", v);
179         e->setVisible(v);
180     }
181 }
182
183 /**
184  * @return Total length of all entities in this container.
185  */
186 double RS_EntityContainer::getLength()
187 {
188         double ret = 0.0;
189
190         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
191         {
192                 if (e->isVisible())
193                 {
194                         double l = e->getLength();
195
196                         if (l < 0.0)
197                         {
198                                 ret = -1.0;
199                                 break;
200                         }
201                         else
202                         {
203                                 ret += l;
204                         }
205                 }
206         }
207
208         return ret;
209 }
210
211 /**
212  * Selects this entity.
213  */
214 bool RS_EntityContainer::setSelected(bool select)
215 {
216         // This entity's select:
217         if (RS_Entity::setSelected(select))
218         {
219                 // All sub-entity's select:
220                 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
221                 {
222                         if (e->isVisible())
223                         {
224                                 e->setSelected(select);
225                         }
226                 }
227
228                 return true;
229         }
230         else
231         {
232                 return false;
233         }
234 }
235
236 /**
237  * Toggles select on this entity.
238  */
239 bool RS_EntityContainer::toggleSelected()
240 {
241         // Toggle this entity's select:
242         if (RS_Entity::toggleSelected())
243         {
244
245                 // Toggle all sub-entity's select:
246                 /*for (RS_Entity* e=firstEntity(RS2::ResolveNone);
247                                 e!=NULL;
248                                 e=nextEntity(RS2::ResolveNone)) {
249                         e->toggleSelected();
250         }*/
251                 return true;
252         }
253         else
254         {
255                 return false;
256         }
257 }
258
259 /**
260  * Selects all entities within the given area.
261  *
262  * @param select True to select, False to deselect the entities.
263  */
264 void RS_EntityContainer::selectWindow(Vector v1, Vector v2, bool select, bool cross)
265 {
266         bool included;
267
268         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
269         {
270                 included = false;
271
272                 if (e->isVisible())
273                 {
274                         if (e->isInWindow(v1, v2))
275                         {
276                                 //e->setSelected(select);
277                                 included = true;
278                         }
279                         else if (cross == true)
280                         {
281                                 RS_Line l[] =
282                                         {
283                                                 RS_Line(NULL, RS_LineData(v1, Vector(v2.x, v1.y))),
284                                                 RS_Line(NULL, RS_LineData(Vector(v2.x, v1.y), v2)),
285                                                 RS_Line(NULL, RS_LineData(v2, Vector(v1.x, v2.y))),
286                                                 RS_Line(NULL, RS_LineData(Vector(v1.x, v2.y), v1))
287                                         };
288                                 VectorSolutions sol;
289
290                                 if (e->isContainer())
291                                 {
292                                         RS_EntityContainer * ec = (RS_EntityContainer *)e;
293
294                                         for(RS_Entity * se=ec->firstEntity(RS2::ResolveAll); se!=NULL && included==false;
295                                                 se=ec->nextEntity(RS2::ResolveAll))
296                                         {
297                                                 for(int i=0; i<4; ++i)
298                                                 {
299                                                         sol = RS_Information::getIntersection(se, &l[i], true);
300
301                                                         if (sol.hasValid())
302                                                         {
303                                                                 included = true;
304                                                                 break;
305                                                         }
306                                                 }
307                                         }
308                                 }
309                                 else
310                                 {
311                                         for(int i=0; i<4; ++i)
312                                         {
313                                                 sol = RS_Information::getIntersection(e, &l[i], true);
314
315                                                 if (sol.hasValid())
316                                                 {
317                                                         included = true;
318                                                         break;
319                                                 }
320                                         }
321                                 }
322                         }
323                 }
324
325                 if (included)
326                 {
327                         e->setSelected(select);
328                 }
329         }
330 }
331
332 /**
333  * Adds a entity to this container and updates the borders of this
334  * entity-container if autoUpdateBorders is true.
335  */
336 void RS_EntityContainer::addEntity(RS_Entity * entity)
337 {
338         /*
339                 if (isDocument()) {
340                         RS_LayerList* lst = getDocument()->getLayerList();
341                         if (lst!=NULL) {
342                                 RS_Layer* l = lst->getActive();
343                                 if (l!=NULL && l->isLocked()) {
344                                         return;
345                                 }
346                         }
347                 }
348         */
349 //printf("RS_EntityContainer::addEntity(): entity=%08X\n", entity);
350
351         if (!entity)
352                 return;
353
354         if (entity->rtti() == RS2::EntityImage || entity->rtti() == RS2::EntityHatch)
355                 entities.prepend(entity);
356         else
357                 entities.append(entity);
358
359         if (autoUpdateBorders)
360                 adjustBorders(entity);
361 //printf("                                 # of entities=%d\n", entities.size());
362 }
363
364 /**
365  * Inserts a entity to this container at the given position and updates
366  * the borders of this entity-container if autoUpdateBorders is true.
367  */
368 void RS_EntityContainer::insertEntity(int index, RS_Entity * entity)
369 {
370         if (entity == NULL)
371                 return;
372
373         entities.insert(index, entity);
374
375         if (autoUpdateBorders)
376                 adjustBorders(entity);
377 }
378
379 /**
380  * Replaces the entity at the given index with the given entity
381  * and updates the borders of this entity-container if autoUpdateBorders is true.
382  */
383 void RS_EntityContainer::replaceEntity(int index, RS_Entity * entity)
384 {
385         if (entity == NULL)
386                 return;
387
388         entities.replace(index, entity);
389
390         if (autoUpdateBorders)
391                 adjustBorders(entity);
392 }
393
394 /**
395  * Removes an entity from this container and updates the borders of
396  * this entity-container if autoUpdateBorders is true.
397  */
398 bool RS_EntityContainer::removeEntity(RS_Entity * entity)
399 {
400 //      bool ret = entities.remove(entity);
401         bool ret = (bool)entities.removeAll(entity);
402
403         if (autoUpdateBorders)
404                 calculateBorders();
405
406         return ret;
407 }
408
409 /**
410  * Erases all entities in this container and resets the borders..
411  */
412 void RS_EntityContainer::clear()
413 {
414         entities.clear();
415         resetBorders();
416 }
417
418 /**
419  * Counts all entities (branches of the tree).
420  */
421 unsigned long int RS_EntityContainer::count()
422 {
423         return entities.count();
424 }
425
426 /**
427  * Counts all entities (leaves of the tree).
428  */
429 unsigned long int RS_EntityContainer::countDeep()
430 {
431         unsigned long int c = 0;
432
433         for(RS_Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
434         {
435                 c += t->countDeep();
436         }
437
438         return c;
439 }
440
441 /**
442  * Counts the selected entities in this container.
443  */
444 unsigned long int RS_EntityContainer::countSelected()
445 {
446         unsigned long int c = 0;
447
448         for(RS_Entity * t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone))
449         {
450                 if (t->isSelected())
451                 {
452                         c++;
453                 }
454         }
455
456         return c;
457 }
458
459 /**
460  * Enables / disables automatic update of borders on entity removals
461  * and additions. By default this is turned on.
462  */
463 /*virtual*/ void RS_EntityContainer::setAutoUpdateBorders(bool enable)
464 {
465         autoUpdateBorders = enable;
466 }
467
468 /**
469  * Adjusts the borders of this graphic (max/min values)
470  */
471 void RS_EntityContainer::adjustBorders(RS_Entity * entity)
472 {
473         //RS_DEBUG->print("RS_EntityContainer::adjustBorders");
474         //resetBorders();
475
476         if (entity != NULL)
477         {
478                 // make sure a container is not empty (otherwise the border
479                 //   would get extended to 0/0):
480                 if (!entity->isContainer() || entity->count() > 0)
481                 {
482                         minV = Vector::minimum(entity->getMin(), minV);
483                         maxV = Vector::maximum(entity->getMax(), maxV);
484                 }
485
486                 // Notify parents. The border for the parent might
487                 // also change TODO: Check for efficiency
488                 //if(parent!=NULL) {
489                 //parent->adjustBorders(this);
490                 //}
491         }
492 }
493
494 /**
495  * Recalculates the borders of this entity container.
496  */
497 void RS_EntityContainer::calculateBorders()
498 {
499         RS_DEBUG->print("RS_EntityContainer::calculateBorders");
500
501         resetBorders();
502
503         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
504         {
505                 RS_Layer * layer = e->getLayer();
506
507                 RS_DEBUG->print("RS_EntityContainer::calculateBorders: isVisible: %d", (int)e->isVisible());
508
509                 if (e->isVisible() && (layer == NULL || !layer->isFrozen()))
510                 {
511                         e->calculateBorders();
512                         adjustBorders(e);
513                 }
514         }
515
516         RS_DEBUG->print("RS_EntityContainer::calculateBorders: size 1: %f,%f", getSize().x, getSize().y);
517
518         // needed for correcting corrupt data (PLANS.dxf)
519         if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
520                 || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
521         {
522                 minV.x = 0.0;
523                 maxV.x = 0.0;
524         }
525
526         if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
527                 || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
528         {
529                 minV.y = 0.0;
530                 maxV.y = 0.0;
531         }
532
533         RS_DEBUG->print("RS_EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y);
534
535         //RS_DEBUG->print("  borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
536
537         //printf("borders: %lf/%lf  %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
538         //RS_Entity::calculateBorders();
539 }
540
541 /**
542  * Recalculates the borders of this entity container including
543  * invisible entities.
544  */
545 void RS_EntityContainer::forcedCalculateBorders()
546 {
547         //RS_DEBUG->print("RS_EntityContainer::calculateBorders");
548
549         resetBorders();
550
551         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
552         {
553                 //RS_Layer* layer = e->getLayer();
554
555                 if (e->isContainer())
556                 {
557                         ((RS_EntityContainer *)e)->forcedCalculateBorders();
558                 }
559                 else
560                 {
561                         e->calculateBorders();
562                 }
563
564                 adjustBorders(e);
565         }
566
567         // needed for correcting corrupt data (PLANS.dxf)
568         if (minV.x > maxV.x || minV.x > RS_MAXDOUBLE || maxV.x > RS_MAXDOUBLE
569                 || minV.x < RS_MINDOUBLE || maxV.x < RS_MINDOUBLE)
570         {
571                 minV.x = 0.0;
572                 maxV.x = 0.0;
573         }
574
575         if (minV.y > maxV.y || minV.y > RS_MAXDOUBLE || maxV.y > RS_MAXDOUBLE
576                 || minV.y < RS_MINDOUBLE || maxV.y < RS_MINDOUBLE)
577         {
578                 minV.y = 0.0;
579                 maxV.y = 0.0;
580         }
581
582         //RS_DEBUG->print("  borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y);
583
584         //printf("borders: %lf/%lf  %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y);
585         //RS_Entity::calculateBorders();
586 }
587
588 /**
589  * Updates all Dimension entities in this container and
590  * reposition their labels.
591  */
592 void RS_EntityContainer::updateDimensions()
593 {
594         RS_DEBUG->print("RS_EntityContainer::updateDimensions()");
595
596         //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
597         //        e!=NULL;
598         //        e=nextEntity(RS2::ResolveNone)) {
599
600 #if 0
601 //      Q3PtrListIterator<RS_Entity> it = createIterator();
602         QListIterator<RS_Entity *> it = createIterator();
603 //      return QListIterator<RS_Entity *>(entities);
604
605         RS_Entity * e;
606
607         while ((e = it.current()) != NULL)
608         {
609                 ++it;
610
611                 if (RS_Information::isDimension(e->rtti()))
612                 {
613                         // update and reposition label:
614                         ((RS_Dimension *)e)->update(true);
615                 }
616                 else if (e->isContainer())
617                 {
618                         ((RS_EntityContainer *)e)->updateDimensions();
619                 }
620         }
621 #else
622         for(int i=0; i<entities.size(); i++)
623         {
624                 RS_Entity * e = entities[i];
625
626                 if (RS_Information::isDimension(e->rtti()))
627                         // update and reposition label:
628                         ((RS_Dimension *)e)->update(true);
629                 else if (e->isContainer())
630                         ((RS_EntityContainer *)e)->updateDimensions();
631         }
632 #endif
633
634         RS_DEBUG->print("RS_EntityContainer::updateDimensions() OK");
635 }
636
637 /**
638  * Updates all Insert entities in this container.
639  */
640 void RS_EntityContainer::updateInserts()
641 {
642         RS_DEBUG->print("RS_EntityContainer::updateInserts()");
643
644         //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
645         //        e!=NULL;
646         //        e=nextEntity(RS2::ResolveNone)) {
647 #if 0
648         Q3PtrListIterator<RS_Entity> it = createIterator();
649         RS_Entity * e;
650
651         while ((e = it.current()) != NULL)
652         {
653                 ++it;
654                 //// Only update our own inserts and not inserts of inserts
655                 if (e->rtti() == RS2::EntityInsert  /*&& e->getParent()==this*/)
656                 {
657                         ((RS_Insert *)e)->update();
658                 }
659                 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
660                 {
661                         ((RS_EntityContainer *)e)->updateInserts();
662                 }
663         }
664 #else
665         for(int i=0; i<entities.size(); i++)
666         {
667                 RS_Entity * e = entities[i];
668
669                 //// Only update our own inserts and not inserts of inserts
670                 if (e->rtti() == RS2::EntityInsert  /*&& e->getParent()==this*/)
671                         ((RS_Insert *)e)->update();
672                 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
673                         ((RS_EntityContainer *)e)->updateInserts();
674         }
675 #endif
676
677         RS_DEBUG->print("RS_EntityContainer::updateInserts() OK");
678 }
679
680 /**
681  * Renames all inserts with name 'oldName' to 'newName'. This is
682  *   called after a block was rename to update the inserts.
683  */
684 void RS_EntityContainer::renameInserts(const QString& oldName, const QString& newName)
685 {
686     RS_DEBUG->print("RS_EntityContainer::renameInserts()");
687
688     //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
689     //        e!=NULL;
690     //        e=nextEntity(RS2::ResolveNone)) {
691
692 #if 0
693     Q3PtrListIterator<RS_Entity> it = createIterator();
694     RS_Entity* e;
695     while ( (e = it.current()) != NULL ) {
696         ++it;
697
698         if (e->rtti()==RS2::EntityInsert) {
699             RS_Insert* i = ((RS_Insert*)e);
700             if (i->getName()==oldName) {
701                 i->setName(newName);
702             }
703         } else if (e->isContainer()) {
704             ((RS_EntityContainer*)e)->renameInserts(oldName, newName);
705         }
706     }
707 #else
708         for(int i=0; i<entities.size(); i++)
709         {
710                 RS_Entity * e = entities[i];
711
712         if (e->rtti() == RS2::EntityInsert)
713                 {
714             RS_Insert * i = ((RS_Insert *)e);
715
716                         if (i->getName() == oldName)
717                 i->setName(newName);
718         }
719         else if (e->isContainer())
720             ((RS_EntityContainer *)e)->renameInserts(oldName, newName);
721         }
722 #endif
723
724     RS_DEBUG->print("RS_EntityContainer::renameInserts() OK");
725
726 }
727
728 /**
729  * Updates all Spline entities in this container.
730  */
731 void RS_EntityContainer::updateSplines()
732 {
733     RS_DEBUG->print("RS_EntityContainer::updateSplines()");
734
735     //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
736     //        e!=NULL;
737     //        e=nextEntity(RS2::ResolveNone)) {
738 #if 0
739     Q3PtrListIterator<RS_Entity> it = createIterator();
740     RS_Entity* e;
741     while ( (e = it.current()) != NULL ) {
742         ++it;
743         //// Only update our own inserts and not inserts of inserts
744         if (e->rtti()==RS2::EntitySpline  /*&& e->getParent()==this*/) {
745             ((RS_Spline*)e)->update();
746         } else if (e->isContainer() && e->rtti()!=RS2::EntityHatch) {
747             ((RS_EntityContainer*)e)->updateSplines();
748         }
749     }
750 #else
751         for(int i=0; i<entities.size(); i++)
752         {
753                 RS_Entity * e = entities[i];
754
755                 //// Only update our own inserts and not inserts of inserts
756                 if (e->rtti() == RS2::EntitySpline  /*&& e->getParent()==this*/)
757                         ((RS_Spline *)e)->update();
758                 else if (e->isContainer() && e->rtti() != RS2::EntityHatch)
759                         ((RS_EntityContainer *)e)->updateSplines();
760         }
761 #endif
762
763     RS_DEBUG->print("RS_EntityContainer::updateSplines() OK");
764 }
765
766 /**
767  * Updates the sub entities of this container.
768  */
769 void RS_EntityContainer::update()
770 {
771     //for (RS_Entity* e=firstEntity(RS2::ResolveNone);
772     //        e!=NULL;
773     //        e=nextEntity(RS2::ResolveNone)) {
774 #if 0
775     Q3PtrListIterator<RS_Entity> it = createIterator();
776     RS_Entity* e;
777     while ( (e = it.current()) != NULL ) {
778         ++it;
779         e->update();
780     }
781 #else
782         for(int i=0; i<entities.size(); i++)
783         {
784 //              RS_Entity * e = entities[i];
785 //              e->update();
786                 entities[i]->update();
787         }
788 #endif
789 }
790
791 /**
792  * Returns the first entity or NULL if this graphic is empty.
793  * @param level
794  */
795 RS_Entity * RS_EntityContainer::firstEntity(RS2::ResolveLevel level)
796 {
797         switch (level)
798         {
799         case RS2::ResolveNone:
800 //              return entities.first();
801 //              entityIterator.toFront();
802                 entityIterator = entities;
803                 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
804                 break;
805
806         case RS2::ResolveAllButInserts:
807         {
808                 subContainer = NULL;
809 //              RS_Entity * e = entities.first();
810 //              entityIterator.toFront();
811                 entityIterator = entities;
812                 RS_Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
813
814                 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
815                 {
816                         subContainer = (RS_EntityContainer *)e;
817                         e = ((RS_EntityContainer *)e)->firstEntity(level);
818
819                         // emtpy container:
820                         if (e == NULL)
821                         {
822                                 subContainer = NULL;
823                                 e = nextEntity(level);
824                         }
825                 }
826
827                 return e;
828         }
829                 break;
830
831         case RS2::ResolveAll:
832         {
833                 subContainer = NULL;
834 //              RS_Entity * e = entities.first();
835 //              entityIterator.toFront();
836                 entityIterator = entities;
837                 RS_Entity * e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
838
839                 if (e != NULL && e->isContainer())
840                 {
841                         subContainer = (RS_EntityContainer *)e;
842                         e = ((RS_EntityContainer *)e)->firstEntity(level);
843
844                         // emtpy container:
845                         if (e == NULL)
846                         {
847                                 subContainer = NULL;
848                                 e = nextEntity(level);
849                         }
850                 }
851
852                 return e;
853         }
854                 break;
855         }
856
857         return NULL;
858 }
859
860 /**
861  * Returns the last entity or \p NULL if this graphic is empty.
862  *
863  * @param level \li \p 0 Groups are not resolved
864  *              \li \p 1 (default) only Groups are resolved
865  *              \li \p 2 all Entity Containers are resolved
866  */
867 RS_Entity * RS_EntityContainer::lastEntity(RS2::ResolveLevel level)
868 {
869         switch (level)
870         {
871         case RS2::ResolveNone:
872 //              return entities.last();
873                 entityIterator = entities;
874                 entityIterator.toBack();
875                 return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
876                 break;
877
878         case RS2::ResolveAllButInserts:
879         {
880 //              RS_Entity * e = entities.last();
881                 entityIterator = entities;
882                 entityIterator.toBack();
883                 RS_Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
884                 subContainer = NULL;
885
886                 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
887                 {
888                         subContainer = (RS_EntityContainer *)e;
889                         e = ((RS_EntityContainer *)e)->lastEntity(level);
890                 }
891
892                 return e;
893         }
894                 break;
895
896         case RS2::ResolveAll:
897         {
898 //              RS_Entity * e = entities.last();
899                 entityIterator = entities;
900                 entityIterator.toBack();
901                 RS_Entity * e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
902                 subContainer = NULL;
903
904                 if (e != NULL && e->isContainer())
905                 {
906                         subContainer = (RS_EntityContainer *)e;
907                         e = ((RS_EntityContainer *)e)->lastEntity(level);
908                 }
909
910                 return e;
911         }
912                 break;
913         }
914
915         return NULL;
916 }
917
918 /**
919  * Returns the next entity or container or \p NULL if the last entity
920  * returned by \p next() was the last entity in the container.
921  */
922 RS_Entity * RS_EntityContainer::nextEntity(RS2::ResolveLevel level)
923 {
924         switch (level)
925         {
926         case RS2::ResolveNone:
927 //              return entities.next();
928                 return (entityIterator.hasNext() ? entityIterator.next() : NULL);
929                 break;
930
931         case RS2::ResolveAllButInserts:
932         {
933                 RS_Entity * e = NULL;
934
935                 if (subContainer != NULL)
936                 {
937                         e = subContainer->nextEntity(level);
938
939                         if (e != NULL)
940                         {
941                                 return e;
942                         }
943                         else
944                         {
945 //                              e = entities.next();
946                                 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
947                         }
948                 }
949                 else
950                 {
951 //                      e = entities.next();
952                         e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
953                 }
954
955                 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
956                 {
957                         subContainer = (RS_EntityContainer *)e;
958                         e = ((RS_EntityContainer *)e)->firstEntity(level);
959
960                         // emtpy container:
961                         if (e == NULL)
962                         {
963                                 subContainer = NULL;
964                                 e = nextEntity(level);
965                         }
966                 }
967
968                 return e;
969         }
970                 break;
971
972         case RS2::ResolveAll:
973         {
974                 RS_Entity * e = NULL;
975
976                 if (subContainer != NULL)
977                 {
978                         e = subContainer->nextEntity(level);
979
980                         if (e != NULL)
981                                 return e;
982                         else
983 //                              e = entities.next();
984                                 e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
985                 }
986                 else
987                 {
988 //                      e = entities.next();
989                         e = (entityIterator.hasNext() ? entityIterator.next() : NULL);
990                 }
991
992                 if (e != NULL && e->isContainer())
993                 {
994                         subContainer = (RS_EntityContainer *)e;
995                         e = ((RS_EntityContainer *)e)->firstEntity(level);
996
997                         // emtpy container:
998                         if (e == NULL)
999                         {
1000                                 subContainer = NULL;
1001                                 e = nextEntity(level);
1002                         }
1003                 }
1004
1005                 return e;
1006         }
1007                 break;
1008         }
1009         return NULL;
1010 }
1011
1012 /**
1013  * Returns the prev entity or container or \p NULL if the last entity
1014  * returned by \p prev() was the first entity in the container.
1015  */
1016 RS_Entity * RS_EntityContainer::prevEntity(RS2::ResolveLevel level)
1017 {
1018         RS_Entity * e = NULL;
1019
1020         switch (level)
1021         {
1022         case RS2::ResolveNone:
1023 //              return entities.prev();
1024                 return (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1025                 break;
1026
1027         case RS2::ResolveAllButInserts:
1028                 e = NULL;
1029
1030                 if (subContainer != NULL)
1031                 {
1032                         e = subContainer->prevEntity(level);
1033
1034                         if (e != NULL)
1035                                 return e;
1036                         else
1037 //                              e = entities.prev();
1038                                 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1039                 }
1040                 else
1041                 {
1042 //                      e = entities.prev();
1043                         e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1044                 }
1045
1046                 if (e != NULL && e->isContainer() && e->rtti() != RS2::EntityInsert)
1047                 {
1048                         subContainer = (RS_EntityContainer *)e;
1049                         e = ((RS_EntityContainer *)e)->lastEntity(level);
1050
1051                         // emtpy container:
1052                         if (e == NULL)
1053                         {
1054                                 subContainer = NULL;
1055                                 e = prevEntity(level);
1056                         }
1057                 }
1058
1059                 return e;
1060
1061         case RS2::ResolveAll:
1062                 e = NULL;
1063
1064                 if (subContainer != NULL)
1065                 {
1066                         e = subContainer->prevEntity(level);
1067
1068                         if (e != NULL)
1069                                 return e;
1070                         else
1071 //                              e = entities.prev();
1072                                 e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1073                 }
1074                 else
1075                 {
1076 //                      e = entities.prev();
1077                         e = (entityIterator.hasPrevious() ? entityIterator.previous() : NULL);
1078                 }
1079
1080                 if (e != NULL && e->isContainer())
1081                 {
1082                         subContainer = (RS_EntityContainer *)e;
1083                         e = ((RS_EntityContainer *)e)->lastEntity(level);
1084
1085                         // emtpy container:
1086                         if (e == NULL)
1087                         {
1088                                 subContainer = NULL;
1089                                 e = prevEntity(level);
1090                         }
1091                 }
1092
1093                 return e;
1094         }
1095
1096         return NULL;
1097 }
1098
1099 /**
1100  * @return Entity at the given index or NULL if the index is out of range.
1101  */
1102 RS_Entity * RS_EntityContainer::entityAt(uint index)
1103 {
1104         return entities.at(index);
1105 }
1106
1107 /**
1108  * @return Current index.
1109  */
1110 int RS_EntityContainer::entityAt()
1111 {
1112 #warning "!!! Not sure how to convert this from Qt3 -> Qt4 !!! (it seems we can ignore this for now as nothing calls it)"
1113 //      return entities.at();
1114         return 0;
1115 }
1116
1117 /**
1118  * Finds the given entity and makes it the current entity if found.
1119  */
1120 int RS_EntityContainer::findEntity(RS_Entity * entity)
1121 {
1122 //      return entities.find(entity);
1123
1124         entityIterator.toFront();
1125         entityIterator.findNext(entity);
1126
1127         return entities.indexOf(entity);
1128 }
1129
1130 /**
1131  * @return The current entity.
1132  */
1133 RS_Entity * RS_EntityContainer::currentEntity()
1134 {
1135 //      return entities.current();
1136
1137 // We really need to refactor this crap, this is the way it is now to support
1138 // the old broken way of doing things
1139         return entityIterator.peekNext();
1140 }
1141
1142 #if 0
1143 #warning "!!! Not needed anymore !!!"
1144 /**
1145  * Returns the copy to a new iterator for traversing the entities.
1146  */
1147 //Q3PtrListIterator<RS_Entity> RS_EntityContainer::createIterator()
1148 QListIterator<RS_Entity *> RS_EntityContainer::createIterator()
1149 {
1150 //      return Q3PtrListIterator<RS_Entity>(entities);
1151         return QListIterator<RS_Entity *>(entities);
1152 }
1153 #endif
1154
1155 /*virtual*/ bool RS_EntityContainer::isEmpty()
1156 {
1157         return (count() == 0);
1158 }
1159
1160 /**
1161  * @return The point which is closest to 'coord'
1162  * (one of the vertexes)
1163  */
1164 Vector RS_EntityContainer::getNearestEndpoint(const Vector & coord, double * dist)
1165 {
1166     double minDist = RS_MAXDOUBLE;  // minimum measured distance
1167     double curDist;                 // currently measured distance
1168     Vector closestPoint(false);  // closest found endpoint
1169     Vector point;                // endpoint found
1170
1171     //Q3PtrListIterator<RS_Entity> it = createIterator();
1172     //RS_Entity* en;
1173     //while ( (en = it.current()) != NULL ) {
1174     //    ++it;
1175     for (RS_Entity* en = firstEntity();
1176             en != NULL;
1177             en = nextEntity()) {
1178
1179         if (en->isVisible()) {
1180             point = en->getNearestEndpoint(coord, &curDist);
1181             if (point.valid && curDist<minDist) {
1182                 closestPoint = point;
1183                 minDist = curDist;
1184                 if (dist!=NULL) {
1185                     *dist = curDist;
1186                 }
1187             }
1188         }
1189     }
1190
1191     return closestPoint;
1192 }
1193
1194
1195
1196 Vector RS_EntityContainer::getNearestPointOnEntity(const Vector& coord,
1197         bool onEntity, double* dist, RS_Entity** entity) {
1198
1199     Vector point(false);
1200
1201     RS_Entity* e = getNearestEntity(coord, dist, RS2::ResolveNone);
1202
1203     if (e!=NULL && e->isVisible()) {
1204         point = e->getNearestPointOnEntity(coord, onEntity, dist, entity);
1205     }
1206
1207     return point;
1208 }
1209
1210
1211
1212 Vector RS_EntityContainer::getNearestCenter(const Vector& coord,
1213         double* dist) {
1214
1215     Vector point(false);
1216     RS_Entity* closestEntity;
1217
1218     //closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
1219     closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1220
1221     if (closestEntity!=NULL) {
1222         point = closestEntity->getNearestCenter(coord, dist);
1223     }
1224
1225     return point;
1226 }
1227
1228
1229
1230 Vector RS_EntityContainer::getNearestMiddle(const Vector& coord,
1231         double* dist) {
1232
1233     Vector point(false);
1234     RS_Entity* closestEntity;
1235
1236     closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1237
1238     if (closestEntity!=NULL) {
1239         point = closestEntity->getNearestMiddle(coord, dist);
1240     }
1241
1242     return point;
1243
1244
1245     /*
1246        double minDist = RS_MAXDOUBLE;  // minimum measured distance
1247        double curDist;                 // currently measured distance
1248        Vector closestPoint;         // closest found endpoint
1249        Vector point;                // endpoint found
1250
1251        for (RS_Entity* en = firstEntity();
1252                en != NULL;
1253                en = nextEntity()) {
1254
1255            if (en->isVisible()) {
1256                point = en->getNearestMiddle(coord, &curDist);
1257                if (curDist<minDist) {
1258                    closestPoint = point;
1259                    minDist = curDist;
1260                    if (dist!=NULL) {
1261                        *dist = curDist;
1262                    }
1263                }
1264            }
1265        }
1266
1267        return closestPoint;
1268     */
1269 }
1270
1271
1272
1273 Vector RS_EntityContainer::getNearestDist(double distance,
1274         const Vector& coord,
1275         double* dist) {
1276
1277     Vector point(false);
1278     RS_Entity* closestEntity;
1279
1280     closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1281
1282     if (closestEntity!=NULL) {
1283         point = closestEntity->getNearestDist(distance, coord, dist);
1284     }
1285
1286     return point;
1287 }
1288
1289
1290
1291 /**
1292  * @return The intersection which is closest to 'coord'
1293  */
1294 Vector RS_EntityContainer::getNearestIntersection(const Vector& coord,
1295         double* dist) {
1296
1297     double minDist = RS_MAXDOUBLE;  // minimum measured distance
1298     double curDist;                 // currently measured distance
1299     Vector closestPoint(false); // closest found endpoint
1300     Vector point;                // endpoint found
1301     VectorSolutions sol;
1302     RS_Entity* closestEntity;
1303
1304     closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
1305
1306     if (closestEntity!=NULL) {
1307         for (RS_Entity* en = firstEntity(RS2::ResolveAll);
1308                 en != NULL;
1309                 en = nextEntity(RS2::ResolveAll)) {
1310
1311             if (en->isVisible() && en!=closestEntity) {
1312                 sol = RS_Information::getIntersection(closestEntity,
1313                                                       en,
1314                                                       true);
1315
1316                 for (int i=0; i<4; i++) {
1317                     point = sol.get(i);
1318                     if (point.valid) {
1319                         curDist = coord.distanceTo(point);
1320
1321                         if (curDist<minDist) {
1322                             closestPoint = point;
1323                             minDist = curDist;
1324                             if (dist!=NULL) {
1325                                 *dist = curDist;
1326                             }
1327                         }
1328                     }
1329                 }
1330             }
1331         }
1332         //}
1333     }
1334
1335     return closestPoint;
1336 }
1337
1338
1339
1340 Vector RS_EntityContainer::getNearestRef(const Vector& coord,
1341         double* dist) {
1342
1343     double minDist = RS_MAXDOUBLE;  // minimum measured distance
1344     double curDist;                 // currently measured distance
1345     Vector closestPoint(false);  // closest found endpoint
1346     Vector point;                // endpoint found
1347
1348     for (RS_Entity* en = firstEntity();
1349             en != NULL;
1350             en = nextEntity()) {
1351
1352         if (en->isVisible()) {
1353             point = en->getNearestRef(coord, &curDist);
1354             if (point.valid && curDist<minDist) {
1355                 closestPoint = point;
1356                 minDist = curDist;
1357                 if (dist!=NULL) {
1358                     *dist = curDist;
1359                 }
1360             }
1361         }
1362     }
1363
1364     return closestPoint;
1365 }
1366
1367
1368 Vector RS_EntityContainer::getNearestSelectedRef(const Vector& coord,
1369         double* dist) {
1370
1371     double minDist = RS_MAXDOUBLE;  // minimum measured distance
1372     double curDist;                 // currently measured distance
1373     Vector closestPoint(false);  // closest found endpoint
1374     Vector point;                // endpoint found
1375
1376     for (RS_Entity* en = firstEntity();
1377             en != NULL;
1378             en = nextEntity()) {
1379
1380         if (en->isVisible() && en->isSelected() && !en->isParentSelected()) {
1381             point = en->getNearestSelectedRef(coord, &curDist);
1382             if (point.valid && curDist<minDist) {
1383                 closestPoint = point;
1384                 minDist = curDist;
1385                 if (dist!=NULL) {
1386                     *dist = curDist;
1387                 }
1388             }
1389         }
1390     }
1391
1392     return closestPoint;
1393 }
1394
1395
1396 double RS_EntityContainer::getDistanceToPoint(const Vector& coord,
1397         RS_Entity** entity,
1398         RS2::ResolveLevel level,
1399         double solidDist) {
1400
1401     RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint");
1402
1403     double minDist = RS_MAXDOUBLE;      // minimum measured distance
1404     double curDist;                     // currently measured distance
1405     RS_Entity* closestEntity = NULL;    // closest entity found
1406     RS_Entity* subEntity = NULL;
1407
1408     //int k=0;
1409     for (RS_Entity* e = firstEntity(level);
1410             e != NULL;
1411             e = nextEntity(level)) {
1412
1413         if (e->isVisible()) {
1414             RS_DEBUG->print("entity: getDistanceToPoint");
1415             RS_DEBUG->print("entity: %d", e->rtti());
1416             curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist);
1417
1418             RS_DEBUG->print("entity: getDistanceToPoint: OK");
1419
1420             if (curDist<minDist) {
1421                 if (level!=RS2::ResolveAll) {
1422                     closestEntity = e;
1423                 } else {
1424                     closestEntity = subEntity;
1425                 }
1426                 minDist = curDist;
1427             }
1428         }
1429     }
1430
1431     if (entity!=NULL) {
1432         *entity = closestEntity;
1433     }
1434     RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint: OK");
1435
1436     return minDist;
1437 }
1438
1439
1440
1441 RS_Entity* RS_EntityContainer::getNearestEntity(const Vector& coord,
1442         double* dist,
1443         RS2::ResolveLevel level) {
1444
1445     RS_DEBUG->print("RS_EntityContainer::getNearestEntity");
1446
1447     RS_Entity* e = NULL;
1448
1449     // distance for points inside solids:
1450     double solidDist = RS_MAXDOUBLE;
1451     if (dist!=NULL) {
1452         solidDist = *dist;
1453     }
1454
1455     double d = getDistanceToPoint(coord, &e, level, solidDist);
1456
1457     if (e!=NULL && e->isVisible()==false) {
1458         e = NULL;
1459     }
1460
1461     // if d is negative, use the default distance (used for points inside solids)
1462     if (dist!=NULL) {
1463         *dist = d;
1464     }
1465     RS_DEBUG->print("RS_EntityContainer::getNearestEntity: OK");
1466
1467     return e;
1468 }
1469
1470
1471
1472 /**
1473  * Rearranges the atomic entities in this container in a way that connected
1474  * entities are stored in the right order and direction.
1475  * Non-recoursive. Only affects atomic entities in this container.
1476  *
1477  * @retval true all contours were closed
1478  * @retval false at least one contour is not closed
1479  */
1480 bool RS_EntityContainer::optimizeContours() {
1481
1482     RS_DEBUG->print("RS_EntityContainer::optimizeContours");
1483
1484     Vector current(false);
1485     Vector start(false);
1486     RS_EntityContainer tmp;
1487
1488     bool changed = false;
1489     bool closed = true;
1490
1491     for (uint ci=0; ci<count(); ++ci) {
1492         RS_Entity* e1=entityAt(ci);
1493
1494         if (e1!=NULL && e1->isEdge() && !e1->isContainer() &&
1495                 !e1->isProcessed()) {
1496
1497             RS_AtomicEntity* ce = (RS_AtomicEntity*)e1;
1498
1499             // next contour start:
1500             ce->setProcessed(true);
1501             tmp.addEntity(ce->clone());
1502             current = ce->getEndpoint();
1503             start = ce->getStartpoint();
1504
1505             // find all connected entities:
1506             bool done;
1507             do {
1508                 done = true;
1509                 for (uint ei=0; ei<count(); ++ei) {
1510                     RS_Entity* e2=entityAt(ei);
1511
1512                     if (e2!=NULL && e2->isEdge() && !e2->isContainer() &&
1513                             !e2->isProcessed()) {
1514
1515                         RS_AtomicEntity* e = (RS_AtomicEntity*)e2;
1516
1517                         if (e->getStartpoint().distanceTo(current) <
1518                                 1.0e-4) {
1519
1520                             e->setProcessed(true);
1521                             tmp.addEntity(e->clone());
1522                             current = e->getEndpoint();
1523
1524                             done=false;
1525                         } else if (e->getEndpoint().distanceTo(current) <
1526                                    1.0e-4) {
1527
1528                             e->setProcessed(true);
1529                             RS_AtomicEntity* cl = (RS_AtomicEntity*)e->clone();
1530                             cl->reverse();
1531                             tmp.addEntity(cl);
1532                             current = cl->getEndpoint();
1533
1534                             changed = true;
1535                             done=false;
1536                         }
1537                     }
1538                 }
1539                 if (!done) {
1540                     changed = true;
1541                 }
1542             } while (!done);
1543
1544             if (current.distanceTo(start)>1.0e-4) {
1545                 closed = false;
1546             }
1547         }
1548     }
1549
1550     // remove all atomic entities:
1551     bool done;
1552     do {
1553         done = true;
1554         for (RS_Entity* en=firstEntity(); en!=NULL; en=nextEntity()) {
1555             if (!en->isContainer()) {
1556                 removeEntity(en);
1557                 done = false;
1558                 break;
1559             }
1560         }
1561     } while (!done);
1562
1563     // add new sorted entities:
1564     for (RS_Entity* en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity()) {
1565         en->setProcessed(false);
1566         addEntity(en->clone());
1567     }
1568
1569     RS_DEBUG->print("RS_EntityContainer::optimizeContours: OK");
1570     return closed;
1571 }
1572
1573
1574 bool RS_EntityContainer::hasEndpointsWithinWindow(Vector v1, Vector v2) {
1575     for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1576             e!=NULL;
1577             e=nextEntity(RS2::ResolveNone)) {
1578         if (e->hasEndpointsWithinWindow(v1, v2))  {
1579             return true;
1580         }
1581     }
1582
1583     return false;
1584 }
1585
1586
1587 void RS_EntityContainer::move(Vector offset) {
1588     for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1589             e!=NULL;
1590             e=nextEntity(RS2::ResolveNone)) {
1591         e->move(offset);
1592     }
1593     if (autoUpdateBorders) {
1594         calculateBorders();
1595     }
1596 }
1597
1598
1599
1600 void RS_EntityContainer::rotate(Vector center, double angle) {
1601     for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1602             e!=NULL;
1603             e=nextEntity(RS2::ResolveNone)) {
1604         e->rotate(center, angle);
1605     }
1606     if (autoUpdateBorders) {
1607         calculateBorders();
1608     }
1609 }
1610
1611
1612
1613 void RS_EntityContainer::scale(Vector center, Vector factor) {
1614     if (fabs(factor.x)>RS_TOLERANCE && fabs(factor.y)>RS_TOLERANCE) {
1615         for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1616                 e!=NULL;
1617                 e=nextEntity(RS2::ResolveNone)) {
1618             e->scale(center, factor);
1619         }
1620     }
1621     if (autoUpdateBorders) {
1622         calculateBorders();
1623     }
1624 }
1625
1626
1627
1628 void RS_EntityContainer::mirror(Vector axisPoint1, Vector axisPoint2) {
1629     if (axisPoint1.distanceTo(axisPoint2)>1.0e-6) {
1630         for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1631                 e!=NULL;
1632                 e=nextEntity(RS2::ResolveNone)) {
1633             e->mirror(axisPoint1, axisPoint2);
1634         }
1635     }
1636 }
1637
1638
1639 void RS_EntityContainer::stretch(Vector firstCorner,
1640                                  Vector secondCorner,
1641                                  Vector offset) {
1642
1643     if (getMin().isInWindow(firstCorner, secondCorner) &&
1644             getMax().isInWindow(firstCorner, secondCorner)) {
1645
1646         move(offset);
1647     } else {
1648         for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1649                 e!=NULL;
1650                 e=nextEntity(RS2::ResolveNone)) {
1651             e->stretch(firstCorner, secondCorner, offset);
1652         }
1653     }
1654
1655     // some entitiycontainers might need an update (e.g. RS_Leader):
1656     update();
1657 }
1658
1659
1660
1661 void RS_EntityContainer::moveRef(const Vector& ref,
1662                                  const Vector& offset) {
1663
1664     for (RS_Entity* e=firstEntity(RS2::ResolveNone);
1665             e!=NULL;
1666             e=nextEntity(RS2::ResolveNone)) {
1667         e->moveRef(ref, offset);
1668     }
1669     if (autoUpdateBorders) {
1670         calculateBorders();
1671     }
1672 }
1673
1674 void RS_EntityContainer::moveSelectedRef(const Vector & ref, const Vector & offset)
1675 {
1676     for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1677         e->moveSelectedRef(ref, offset);
1678
1679         if (autoUpdateBorders)
1680         calculateBorders();
1681 }
1682
1683 void RS_EntityContainer::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
1684 {
1685         if (painter == NULL || view == NULL)
1686                 return;
1687
1688         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e = nextEntity(RS2::ResolveNone))
1689                 view->drawEntity(e);
1690 }
1691
1692 /**
1693  * Dumps the entities to stdout.
1694  */
1695 std::ostream & operator<<(std::ostream & os, RS_EntityContainer & ec)
1696 {
1697         static int indent = 0;
1698
1699         char * tab = new char[indent * 2 + 1];
1700
1701         for(int i=0; i<indent*2; ++i)
1702                 tab[i] = ' ';
1703
1704         tab[indent * 2] = '\0';
1705
1706         ++indent;
1707
1708         unsigned long int id = ec.getId();
1709
1710         os << tab << "EntityContainer[" << id << "]: \n";
1711         os << tab << "Borders[" << id << "]: "
1712         << ec.minV << " - " << ec.maxV << "\n";
1713         //os << tab << "Unit[" << id << "]: "
1714         //<< RS_Units::unit2string (ec.unit) << "\n";
1715         if (ec.getLayer() != NULL)
1716         {
1717                 os << tab << "Layer[" << id << "]: "
1718                 << ec.getLayer()->getName().toLatin1().data() << "\n";
1719         }
1720         else
1721         {
1722                 os << tab << "Layer[" << id << "]: <NULL>\n";
1723         }
1724         //os << ec.layerList << "\n";
1725
1726         os << tab << " Flags[" << id << "]: "
1727                 << (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1728         os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1729         os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1730         os << "\n";
1731
1732         os << tab << "Entities[" << id << "]: \n";
1733
1734 QString s;
1735 os << "(# of entities in this = " << ec.entities.size() << ")\n";
1736 for(int i=0; i<ec.entities.size(); i++)
1737 {
1738         RS_Entity * t = ec.entities[i];
1739         s.sprintf("(Entity = $%08X, rtti = %d\n", t, t->rtti());
1740         os << s.toAscii().data();
1741 }
1742 s.sprintf("(firstEntity = $%08X)\n", ec.firstEntity());
1743 os << s.toAscii().data();
1744
1745         for(RS_Entity * t=ec.firstEntity(); t!=NULL; t=ec.nextEntity())
1746         {
1747                 switch (t->rtti())
1748                 {
1749                 case RS2::EntityInsert:
1750                         os << tab << *((RS_Insert *)t);
1751                         os << tab << *((RS_Entity *)t);
1752                         os << tab << *((RS_EntityContainer *)t);
1753                         break;
1754                 default:
1755                         if (t->isContainer())
1756                                 os << tab << *((RS_EntityContainer *)t);
1757                         else
1758                                 os << tab << *t;
1759
1760                         break;
1761                 }
1762         }
1763
1764         os << tab << "\n\n";
1765         --indent;
1766
1767         delete[] tab;
1768         return os;
1769 }
1770