]> Shamusworld >> Repos - architektonas/blob - src/base/rs_entitycontainer.cpp
Fixed problem with dimensions not showing up.
[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 Vector RS_EntityContainer::getNearestPointOnEntity(const Vector & coord,
1195         bool onEntity, double * dist, RS_Entity ** entity)
1196 {
1197         Vector point(false);
1198
1199         RS_Entity * e = getNearestEntity(coord, dist, RS2::ResolveNone);
1200
1201         if (e && e->isVisible())
1202                 point = e->getNearestPointOnEntity(coord, onEntity, dist, entity);
1203
1204         return point;
1205 }
1206
1207 Vector RS_EntityContainer::getNearestCenter(const Vector & coord, double * dist)
1208 {
1209         Vector point(false);
1210         RS_Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1211
1212         if (closestEntity)
1213                 point = closestEntity->getNearestCenter(coord, dist);
1214
1215         return point;
1216 }
1217
1218 Vector RS_EntityContainer::getNearestMiddle(const Vector & coord, double * dist)
1219 {
1220         Vector point(false);
1221         RS_Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1222
1223         if (closestEntity)
1224                 point = closestEntity->getNearestMiddle(coord, dist);
1225
1226         return point;
1227 }
1228
1229 Vector RS_EntityContainer::getNearestDist(double distance, const Vector & coord,
1230         double * dist)
1231 {
1232         Vector point(false);
1233         RS_Entity * closestEntity = getNearestEntity(coord, NULL, RS2::ResolveNone);
1234
1235         if (closestEntity)
1236                 point = closestEntity->getNearestDist(distance, coord, dist);
1237
1238         return point;
1239 }
1240
1241 /**
1242  * @return The intersection which is closest to 'coord'
1243  */
1244 Vector RS_EntityContainer::getNearestIntersection(const Vector & coord,
1245         double * dist)
1246 {
1247         double minDist = RS_MAXDOUBLE;                          // minimum measured distance
1248         double curDist;                                                         // currently measured distance
1249         Vector closestPoint(false);                                     // closest found endpoint
1250         Vector point;                                                           // endpoint found
1251         VectorSolutions sol;
1252         RS_Entity * closestEntity;
1253
1254         closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll);
1255
1256         if (closestEntity)
1257         {
1258                 for(RS_Entity * en=firstEntity(RS2::ResolveAll); en!=NULL;
1259                         en = nextEntity(RS2::ResolveAll))
1260                 {
1261                         if (en->isVisible() && en!=closestEntity)
1262                         {
1263                                 sol = RS_Information::getIntersection(closestEntity, en, true);
1264
1265                                 for(int i=0; i<4; i++)
1266                                 {
1267                                         point = sol.get(i);
1268
1269                                         if (point.valid)
1270                                         {
1271                                                 curDist = coord.distanceTo(point);
1272
1273                                                 if (curDist < minDist)
1274                                                 {
1275                                                         closestPoint = point;
1276                                                         minDist = curDist;
1277
1278                                                         if (dist)
1279                                                                 *dist = curDist;
1280                                                 }
1281                                         }
1282                                 }
1283                         }
1284                 }
1285         }
1286
1287         return closestPoint;
1288 }
1289
1290 Vector RS_EntityContainer::getNearestRef(const Vector & coord, double * dist)
1291 {
1292         double minDist = RS_MAXDOUBLE;  // minimum measured distance
1293         double curDist;                 // currently measured distance
1294         Vector closestPoint(false);  // closest found endpoint
1295         Vector point;                // endpoint found
1296
1297         for(RS_Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1298         {
1299                 if (en->isVisible())
1300                 {
1301                         point = en->getNearestRef(coord, &curDist);
1302
1303                         if (point.valid && curDist < minDist)
1304                         {
1305                                 closestPoint = point;
1306                                 minDist = curDist;
1307
1308                                 if (dist)
1309                                         *dist = curDist;
1310                         }
1311                 }
1312         }
1313
1314         return closestPoint;
1315 }
1316
1317 Vector RS_EntityContainer::getNearestSelectedRef(const Vector & coord,
1318         double * dist)
1319 {
1320         double minDist = RS_MAXDOUBLE;                          // minimum measured distance
1321         double curDist;                                                         // currently measured distance
1322         Vector closestPoint(false);                                     // closest found endpoint
1323         Vector point;                                                           // endpoint found
1324
1325         for(RS_Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1326         {
1327                 if (en->isVisible() && en->isSelected() && !en->isParentSelected())
1328                 {
1329                         point = en->getNearestSelectedRef(coord, &curDist);
1330
1331                         if (point.valid && curDist < minDist)
1332                         {
1333                                 closestPoint = point;
1334                                 minDist = curDist;
1335
1336                                 if (dist)
1337                                         *dist = curDist;
1338                         }
1339                 }
1340         }
1341
1342         return closestPoint;
1343 }
1344
1345 double RS_EntityContainer::getDistanceToPoint(const Vector & coord,
1346         RS_Entity ** entity, RS2::ResolveLevel level, double solidDist)
1347 {
1348         RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint");
1349
1350         double minDist = RS_MAXDOUBLE;      // minimum measured distance
1351         double curDist;                     // currently measured distance
1352         RS_Entity * closestEntity = NULL;    // closest entity found
1353         RS_Entity * subEntity = NULL;
1354
1355         //int k=0;
1356         for(RS_Entity * e=firstEntity(level); e!=NULL; e=nextEntity(level))
1357         {
1358                 if (e->isVisible())
1359                 {
1360                         RS_DEBUG->print("entity: getDistanceToPoint");
1361                         RS_DEBUG->print("entity: %d", e->rtti());
1362                         curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist);
1363                         RS_DEBUG->print("entity: getDistanceToPoint: OK");
1364
1365                         if (curDist<minDist)
1366                         {
1367                                 if (level != RS2::ResolveAll)
1368                                         closestEntity = e;
1369                                 else
1370                                         closestEntity = subEntity;
1371
1372                                 minDist = curDist;
1373                         }
1374                 }
1375         }
1376
1377         if (entity)
1378                 *entity = closestEntity;
1379
1380         RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint: OK");
1381         return minDist;
1382 }
1383
1384 RS_Entity * RS_EntityContainer::getNearestEntity(const Vector & coord,
1385         double * dist, RS2::ResolveLevel level)
1386 {
1387         RS_DEBUG->print("RS_EntityContainer::getNearestEntity");
1388         RS_Entity * e = NULL;
1389
1390         // distance for points inside solids:
1391         double solidDist = RS_MAXDOUBLE;
1392
1393         if (dist)
1394                 solidDist = *dist;
1395
1396         double d = getDistanceToPoint(coord, &e, level, solidDist);
1397
1398         if (e && e->isVisible() == false)
1399                 e = NULL;
1400
1401         // if d is negative, use the default distance (used for points inside solids)
1402         if (dist)
1403                 *dist = d;
1404
1405         RS_DEBUG->print("RS_EntityContainer::getNearestEntity: OK");
1406         return e;
1407 }
1408
1409 /**
1410  * Rearranges the atomic entities in this container in a way that connected
1411  * entities are stored in the right order and direction.
1412  * Non-recoursive. Only affects atomic entities in this container.
1413  *
1414  * @retval true all contours were closed
1415  * @retval false at least one contour is not closed
1416  */
1417 bool RS_EntityContainer::optimizeContours()
1418 {
1419         RS_DEBUG->print("RS_EntityContainer::optimizeContours");
1420
1421         Vector current(false);
1422         Vector start(false);
1423         RS_EntityContainer tmp;
1424
1425         bool changed = false;
1426         bool closed = true;
1427
1428         for(uint ci=0; ci<count(); ++ci)
1429         {
1430                 RS_Entity * e1=entityAt(ci);
1431
1432                 if (e1 && e1->isEdge() && !e1->isContainer() && !e1->isProcessed())
1433                 {
1434                         RS_AtomicEntity * ce = (RS_AtomicEntity *)e1;
1435
1436                         // next contour start:
1437                         ce->setProcessed(true);
1438                         tmp.addEntity(ce->clone());
1439                         current = ce->getEndpoint();
1440                         start = ce->getStartpoint();
1441
1442                         // find all connected entities:
1443                         bool done;
1444
1445                         do
1446                         {
1447                                 done = true;
1448                                 for(uint ei=0; ei<count(); ++ei)
1449                                 {
1450                                         RS_Entity * e2=entityAt(ei);
1451
1452                                         if (e2 != NULL && e2->isEdge() && !e2->isContainer() &&
1453                                                 !e2->isProcessed())
1454                                         {
1455                                                 RS_AtomicEntity * e = (RS_AtomicEntity *)e2;
1456
1457                                                 if (e->getStartpoint().distanceTo(current) < 1.0e-4)
1458                                                 {
1459                                                         e->setProcessed(true);
1460                                                         tmp.addEntity(e->clone());
1461                                                         current = e->getEndpoint();
1462                                                         done = false;
1463                                                 }
1464                                                 else if (e->getEndpoint().distanceTo(current) < 1.0e-4)
1465                                                 {
1466                                                         e->setProcessed(true);
1467                                                         RS_AtomicEntity * cl = (RS_AtomicEntity *)e->clone();
1468                                                         cl->reverse();
1469                                                         tmp.addEntity(cl);
1470                                                         current = cl->getEndpoint();
1471                                                         changed = true;
1472                                                         done = false;
1473                                                 }
1474                                         }
1475                                 }
1476
1477                                 if (!done)
1478                                         changed = true;
1479                         }
1480                         while (!done);
1481
1482                         if (current.distanceTo(start) > 1.0e-4)
1483                                 closed = false;
1484                 }
1485         }
1486
1487         // remove all atomic entities:
1488         bool done;
1489
1490         do
1491         {
1492                 done = true;
1493
1494                 for(RS_Entity * en=firstEntity(); en!=NULL; en=nextEntity())
1495                 {
1496                         if (!en->isContainer())
1497                         {
1498                                 removeEntity(en);
1499                                 done = false;
1500                                 break;
1501                         }
1502                 }
1503         }
1504         while (!done);
1505
1506         // add new sorted entities:
1507         for(RS_Entity * en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity())
1508         {
1509                 en->setProcessed(false);
1510                 addEntity(en->clone());
1511         }
1512
1513         RS_DEBUG->print("RS_EntityContainer::optimizeContours: OK");
1514         return closed;
1515 }
1516
1517 bool RS_EntityContainer::hasEndpointsWithinWindow(Vector v1, Vector v2)
1518 {
1519         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1520         {
1521                 if (e->hasEndpointsWithinWindow(v1, v2))
1522                         return true;
1523         }
1524
1525         return false;
1526 }
1527
1528 void RS_EntityContainer::move(Vector offset)
1529 {
1530         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1531                 e->move(offset);
1532
1533         if (autoUpdateBorders)
1534                 calculateBorders();
1535 }
1536
1537 void RS_EntityContainer::rotate(Vector center, double angle)
1538 {
1539         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1540                 e->rotate(center, angle);
1541
1542         if (autoUpdateBorders)
1543                 calculateBorders();
1544 }
1545
1546 void RS_EntityContainer::scale(Vector center, Vector factor)
1547 {
1548         if (fabs(factor.x) > RS_TOLERANCE && fabs(factor.y) > RS_TOLERANCE)
1549         {
1550                 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1551                         e->scale(center, factor);
1552         }
1553
1554         if (autoUpdateBorders)
1555                 calculateBorders();
1556 }
1557
1558 void RS_EntityContainer::mirror(Vector axisPoint1, Vector axisPoint2)
1559 {
1560         if (axisPoint1.distanceTo(axisPoint2) > 1.0e-6)
1561         {
1562                 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1563                         e->mirror(axisPoint1, axisPoint2);
1564         }
1565 }
1566
1567 void RS_EntityContainer::stretch(Vector firstCorner, Vector secondCorner,
1568         Vector offset)
1569 {
1570         if (getMin().isInWindow(firstCorner, secondCorner) &&
1571                 getMax().isInWindow(firstCorner, secondCorner))
1572         {
1573                 move(offset);
1574         }
1575         else
1576         {
1577                 for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1578                         e->stretch(firstCorner, secondCorner, offset);
1579         }
1580
1581         // some entitiycontainers might need an update (e.g. RS_Leader):
1582         update();
1583 }
1584
1585 void RS_EntityContainer::moveRef(const Vector & ref, const Vector & offset)
1586 {
1587         for(RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1588                 e->moveRef(ref, offset);
1589
1590         if (autoUpdateBorders)
1591                 calculateBorders();
1592 }
1593
1594 void RS_EntityContainer::moveSelectedRef(const Vector & ref, const Vector & offset)
1595 {
1596         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1597                 e->moveSelectedRef(ref, offset);
1598
1599         if (autoUpdateBorders)
1600                 calculateBorders();
1601 }
1602
1603 void RS_EntityContainer::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
1604 {
1605         if (!painter || !view)
1606                 return;
1607
1608         for(RS_Entity * e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone))
1609 #if 0
1610 {
1611 if (e->rtti() == RS2::EntityText)
1612 {
1613         std::cout << "About to draw TEXT entity... "
1614                 << "TEXT=\"" << ((RS_Text *)e)->getText().toAscii().data() << "\"" << std::endl;
1615 }
1616 //OK, we have text, but no insert entities at least none that are drawn...
1617 //Ah! But with a standard text entity, it DOES have them!
1618 else if (e->rtti() == RS2::EntityInsert)
1619 {
1620         std::cout << "About to draw INSERT entity... "
1621                 << "INSERT=\"" << ((RS_Insert *)e)->getData().name.toAscii().data() << "\"" << std::endl;
1622 }
1623 #endif
1624                 view->drawEntity(e);
1625 #if 0
1626 }
1627 #endif
1628 }
1629
1630 /**
1631  * Dumps the entities to stdout.
1632  */
1633 std::ostream & operator<<(std::ostream & os, RS_EntityContainer & ec)
1634 {
1635         static int indent = 0;
1636         char * tab = new char[indent * 2 + 1];
1637
1638         for(int i=0; i<indent*2; i++)
1639                 tab[i] = ' ';
1640
1641         tab[indent * 2] = '\0';
1642         indent++;
1643         unsigned long int id = ec.getId();
1644
1645         os << tab << "EntityContainer[" << id << "]: \n";
1646         os << tab << "Borders[" << id << "]: "
1647         << ec.minV << " - " << ec.maxV << "\n";
1648         //os << tab << "Unit[" << id << "]: "
1649         //<< RS_Units::unit2string (ec.unit) << "\n";
1650         if (ec.getLayer())
1651         {
1652                 os << tab << "Layer[" << id << "]: "
1653                         << ec.getLayer()->getName().toLatin1().data() << "\n";
1654         }
1655         else
1656         {
1657                 os << tab << "Layer[" << id << "]: <NULL>\n";
1658         }
1659         //os << ec.layerList << "\n";
1660
1661         os << tab << " Flags[" << id << "]: "
1662                 << (ec.getFlag(RS2::FlagVisible) ? "RS2::FlagVisible" : "");
1663         os << (ec.getFlag(RS2::FlagUndone) ? " RS2::FlagUndone" : "");
1664         os << (ec.getFlag(RS2::FlagSelected) ? " RS2::FlagSelected" : "");
1665         os << "\n";
1666
1667         os << tab << "Entities[" << id << "]: \n";
1668
1669 QString s;
1670 os << "(# of entities in this = " << ec.entities.size() << ")\n";
1671 for(int i=0; i<ec.entities.size(); i++)
1672 {
1673         RS_Entity * t = ec.entities[i];
1674         s.sprintf("(Entity = $%08X, rtti = %d\n", t, t->rtti());
1675         os << s.toAscii().data();
1676 }
1677 s.sprintf("(firstEntity = $%08X)\n", ec.firstEntity());
1678 os << s.toAscii().data();
1679
1680         for(RS_Entity * t=ec.firstEntity(); t!=NULL; t=ec.nextEntity())
1681         {
1682                 switch (t->rtti())
1683                 {
1684                 case RS2::EntityInsert:
1685                         os << tab << *((RS_Insert *)t);
1686                         os << tab << *((RS_Entity *)t);
1687                         os << tab << *((RS_EntityContainer *)t);
1688                         break;
1689                 default:
1690                         if (t->isContainer())
1691                                 os << tab << *((RS_EntityContainer *)t);
1692                         else
1693                                 os << tab << *t;
1694
1695                         break;
1696                 }
1697         }
1698
1699         os << tab << "\n\n";
1700         indent--;
1701
1702         delete[] tab;
1703         return os;
1704 }