]> Shamusworld >> Repos - architektonas/blob - src/base/rs_selection.cpp
60863ca1fc36e5ca0aa86ccae747311abdddb603
[architektonas] / src / base / rs_selection.cpp
1 // rs_selection.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 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  06/02/2010  Added this text. :-)
15 //
16
17 #include "rs_selection.h"
18
19 #include "drawing.h"
20 #include "rs_entity.h"
21 #include "graphicview.h"
22 #include "rs_information.h"
23 #include "rs_polyline.h"
24
25 /**
26  * Default constructor.
27  *
28  * @param container The container to which we will add
29  *        entities. Usually that's an Drawing entity but
30  *        it can also be a polyline, text, ...
31  */
32 RS_Selection::RS_Selection(RS_EntityContainer & container, GraphicView * graphicView)
33 {
34         this->container = &container;
35         this->graphicView = graphicView;
36         graphic = container.getGraphic();
37 }
38
39 /**
40  * Selects or deselects the given entitiy.
41  */
42 void RS_Selection::selectSingle(RS_Entity * e)
43 {
44         if (e && (e->getLayer() == NULL || e->getLayer()->isLocked() == false))
45         {
46 // Same problem as below...
47 //[WAS]#warning "!!! This is causing a segfault in the draw code !!!"
48 //              if (graphicView != NULL)
49 //                      graphicView->deleteEntity(e);
50
51                 e->toggleSelected();
52
53 //Most likely because while the painter is valid, the QPainter is not...
54 //[WAS]#warning "!!! This is causing a segfault in the draw code !!!"
55                 if (graphicView != NULL)
56 //                      graphicView->drawEntity(e);
57                         graphicView->redraw();
58         }
59 }
60
61 /**
62  * Selects all entities on visible layers.
63  */
64 void RS_Selection::selectAll(bool select)
65 {
66         if (graphicView != NULL)
67         {
68                 //graphicView->deleteEntity(container);
69         }
70
71         //container->setSelected(select);
72         for(RS_Entity * e=container->firstEntity(); e!=NULL; e=container->nextEntity())
73         {
74         //for (uint i=0; i<container->count(); ++i) {
75                 //RS_Entity* e = container->entityAt(i);
76
77                 if (e != NULL && e->isVisible())
78                         e->setSelected(select);
79         }
80
81         if (graphicView!=NULL)
82                 //graphicView->drawEntity(container);
83                 graphicView->redraw();
84 }
85
86 void RS_Selection::deselectAll()
87 {
88         selectAll(false);
89 }
90
91 /**
92  * Selects all entities on visible layers.
93  */
94 void RS_Selection::invertSelection()
95 {
96         if (graphicView != NULL)
97         {
98                 //graphicView->deleteEntity(container);
99         }
100
101         for(RS_Entity * e=container->firstEntity(); e!=NULL; e=container->nextEntity())
102         {
103         //for (uint i=0; i<container->count(); ++i) {
104                 //RS_Entity* e = container->entityAt(i);
105
106                 if (e != NULL && e->isVisible())
107                         e->toggleSelected();
108         }
109
110         if (graphicView != NULL)
111                 //graphicView->drawEntity(container);
112                 graphicView->redraw();
113 }
114
115 /**
116  * Selects all entities that are completely in the given window.
117  *
118  * @param v1 First corner of the window to select.
119  * @param v2 Second corner of the window to select.
120  * @param select true: select, false: deselect
121  */
122 void RS_Selection::selectWindow(const Vector & v1, const Vector & v2, bool select, bool cross)
123 {
124         //if (graphicView!=NULL) {
125         //    graphicView->drawWindow(v1, v2, true);
126         //}
127
128         container->selectWindow(v1, v2, select, cross);
129
130         if (graphicView != NULL)
131                 //graphicView->drawWindow(v1, v2);
132                 graphicView->redraw();
133 }
134
135 void RS_Selection::deselectWindow(const Vector & v1, const Vector & v2)
136 {
137         selectWindow(v1, v2, false);
138 }
139
140 /**
141  * Selects all entities that are intersected by the given line.
142  *
143  * @param v1 Startpoint of line.
144  * @param v2 Endpoint of line.
145  * @param select true: select, false: deselect
146  */
147 void RS_Selection::selectIntersected(const Vector & v1, const Vector & v2, bool select)
148 {
149         RS_Line line(NULL, RS_LineData(v1, v2));
150         bool inters;
151
152         for (RS_Entity* e=container->firstEntity(); e!=NULL;
153                         e=container->nextEntity()) {
154         //for (uint i=0; i<container->count(); ++i) {
155                 //RS_Entity* e = container->entityAt(i);
156
157                 if (e!=NULL && e->isVisible()) {
158
159                         inters = false;
160
161                         // select containers / groups:
162                         if (e->isContainer()) {
163                                 RS_EntityContainer* ec = (RS_EntityContainer*)e;
164
165                                 for (RS_Entity* e2=ec->firstEntity(RS2::ResolveAll); e2!=NULL;
166                                                 e2=ec->nextEntity(RS2::ResolveAll)) {
167
168                                         VectorSolutions sol =
169                                                 RS_Information::getIntersection(&line, e2, true);
170
171                                         if (sol.hasValid()) {
172                                                 inters = true;
173                                         }
174                                 }
175                         } else {
176
177                                 VectorSolutions sol =
178                                         RS_Information::getIntersection(&line, e, true);
179
180                                 if (sol.hasValid()) {
181                                         inters = true;
182                                 }
183                         }
184
185                         if (inters) {
186                                 if (graphicView!=NULL) {
187                                         graphicView->deleteEntity(e);
188                                 }
189
190                                 e->setSelected(select);
191
192                                 if (graphicView!=NULL) {
193                                         graphicView->drawEntity(e);
194                                 }
195                         }
196                 }
197         }
198 }
199
200 void RS_Selection::deselectIntersected(const Vector & v1, const Vector & v2)
201 {
202         selectIntersected(v1, v2, false);
203 }
204
205 /**
206  * Selects all entities that are connected to the given entity.
207  *
208  * @param e The entity where the algorithm starts. Must be an atomic entity.
209  */
210 void RS_Selection::selectContour(RS_Entity * e)
211 {
212         if (e == NULL || !e->isAtomic())
213                 return;
214
215         bool select = !e->isSelected();
216         RS_AtomicEntity* ae = (RS_AtomicEntity*)e;
217         Vector p1 = ae->getStartpoint();
218         Vector p2 = ae->getEndpoint();
219         bool found = false;
220
221         // (de)select 1st entity:
222         if (graphicView!=NULL) {
223                 graphicView->deleteEntity(e);
224         }
225         e->setSelected(select);
226         if (graphicView!=NULL) {
227                 graphicView->drawEntity(e);
228         }
229
230         do {
231                 found = false;
232
233                 for (RS_Entity* en=container->firstEntity(); en!=NULL;
234                                 en=container->nextEntity()) {
235                 //for (uint i=0; i<container->count(); ++i) {
236                         //RS_Entity* en = container->entityAt(i);
237
238                         if (en!=NULL && en->isVisible() &&
239                                 en->isAtomic() && en->isSelected()!=select &&
240                                 (en->getLayer()==NULL || en->getLayer()->isLocked()==false)) {
241
242                                 ae = (RS_AtomicEntity*)en;
243                                 bool doit = false;
244
245                                 // startpoint connects to 1st point
246                                 if (ae->getStartpoint().distanceTo(p1)<1.0e-4) {
247                                         doit = true;
248                                         p1 = ae->getEndpoint();
249                                 }
250
251                                 // endpoint connects to 1st point
252                                 else if (ae->getEndpoint().distanceTo(p1)<1.0e-4) {
253                                         doit = true;
254                                         p1 = ae->getStartpoint();
255                                 }
256
257                                 // startpoint connects to 2nd point
258                                 else if (ae->getStartpoint().distanceTo(p2)<1.0e-4) {
259                                         doit = true;
260                                         p2 = ae->getEndpoint();
261                                 }
262
263                                 // endpoint connects to 1st point
264                                 else if (ae->getEndpoint().distanceTo(p2)<1.0e-4) {
265                                         doit = true;
266                                         p2 = ae->getStartpoint();
267                                 }
268
269                                 if (doit) {
270                                         if (graphicView!=NULL) {
271                                                 graphicView->deleteEntity(ae);
272                                         }
273                                         ae->setSelected(select);
274                                         if (graphicView!=NULL) {
275                                                 graphicView->drawEntity(ae);
276                                         }
277                                         found = true;
278                                 }
279                         }
280                 }
281         } while(found);
282 }
283
284 /**
285  * Selects all entities on the given layer.
286  */
287 void RS_Selection::selectLayer(RS_Entity * e)
288 {
289         if (e == NULL)
290                 return;
291
292         bool select = !e->isSelected();
293
294         RS_Layer * layer = e->getLayer(true);
295
296         if (layer == NULL)
297                 return;
298
299         QString layerName = layer->getName();
300         selectLayer(layerName, select);
301 }
302
303 /**
304  * Selects all entities on the given layer.
305  */
306 void RS_Selection::selectLayer(const QString & layerName, bool select)
307 {
308         for(RS_Entity * en=container->firstEntity(); en!=NULL; en=container->nextEntity())
309         {
310                 if (en != NULL && en->isVisible() && en->isSelected() != select
311                         && (en->getLayer() == NULL || en->getLayer()->isLocked() == false))
312                 {
313                         RS_Layer * l = en->getLayer(true);
314
315                         if (l != NULL && l->getName() == layerName)
316                         {
317                                 if (graphicView != NULL)
318                                         graphicView->deleteEntity(en);
319
320                                 en->setSelected(select);
321
322                                 if (graphicView != NULL)
323                                         graphicView->drawEntity(en);
324                         }
325                 }
326         }
327 }
328
329 void RS_Selection::deselectLayer(QString & layerName)
330 {
331         selectLayer(layerName, false);
332 }