]> Shamusworld >> Repos - architektonas/blob - src/container.cpp
Fix for missing ampersand in QApplication.
[architektonas] / src / container.cpp
1 // container.cpp: Container object
2 //
3 // Part of the Architektonas Project
4 // (C) 2011 Underground Software
5 // See the README and GPLv3 files for licensing and warranty information
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  03/30/2011  Created this file
12 // JLH  06/02/2011  Added code to delete objects in this container when they go
13 //                  out of scope
14 //
15
16 #include "container.h"
17
18 #include <QtGui>
19 #include "dimension.h"
20
21
22 Container::Container(Vector p1, Object * p/*= NULL*/): Object(p1, p),
23         dragging(false), draggingHandle1(false), draggingHandle2(false)//, needUpdate(false)
24 {
25 }
26
27 Container::~Container()
28 {
29         // No memory leaks!
30         while (objects.size() > 0)
31         {
32                 delete objects[0];
33                 objects.erase(objects.begin());
34         }
35 }
36
37 /*virtual*/ void Container::Draw(Painter * painter)
38 {
39         for(int i=0; i<(int)objects.size(); i++)
40                 objects[i]->Draw(painter);
41 }
42
43 /*virtual*/ Vector Container::Center(void)
44 {
45         return position;
46 }
47
48 /*
49  We need at least *three* handles for this object:
50  - one for moving
51  - one for resizing
52  - one for rotation
53
54 We need to think about the intuitive way (if there is any) to grab and
55 manipulate a complex object like this... Need to think, "What should happen when
56 I click here and drag there?"
57
58 Also: should put the snap logic into the Object base class (as a static method)...
59 */
60
61 /*virtual*/ bool Container::Collided(Vector point)
62 {
63         objectWasDragged = false;
64         Vector v1 = position - point;
65
66 #if 0
67         if (state == OSInactive)
68         {
69 //printf("Circle: pp = %lf, length = %lf, distance = %lf\n", parameterizedPoint, lineSegment.Magnitude(), distance);
70 //printf("      v1.Magnitude = %lf, v2.Magnitude = %lf\n", v1.Magnitude(), v2.Magnitude());
71 //printf("      point = %lf,%lf,%lf; p1 = %lf,%lf,%lf; p2 = %lf,%lf,%lf\n", point.x, point.y, point.z, position.x, position.y, position.z, endpoint.x, endpoint.y, endpoint.z);
72 //printf("      \n", );
73 //How to translate this into pixels from Document space???
74 //Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
75 //the caller knows about the zoom factor and all that good kinda crap
76                 if (v1.Magnitude() < 10.0)
77                 {
78                         oldState = state;
79                         state = OSSelected;
80                         oldPoint = position; //maybe "position"?
81                         draggingHandle1 = true;
82                         return true;
83                 }
84                 else if ((v1.Magnitude() < radius + 2.0) && (v1.Magnitude() > radius - 2.0))
85                 {
86                         oldState = state;
87                         state = OSSelected;
88                         oldPoint = point;
89                         dragging = true;
90                         return true;
91                 }
92         }
93         else if (state == OSSelected)
94         {
95                 // Here we test for collision with handles as well! (SOON!)
96 /*
97 Like so:
98                 if (v1.Magnitude() < 2.0) // Handle #1
99                 else if (v2.Magnitude() < 2.0) // Handle #2
100 */
101                 if ((v1.Magnitude() < radius + 2.0) && (v1.Magnitude() > radius - 2.0))
102                 {
103                         oldState = state;
104 //                      state = OSInactive;
105                         oldPoint = point;
106                         dragging = true;
107                         return true;
108                 }
109         }
110 #else
111         bool collision = false;
112
113         // NOTE that this deletes the object on mouse down instead of mouse up. Have to
114         // check to see how it feels to do it that way...
115         if (deleteActive)
116         {
117                 for(int i=0; i<(int)objects.size(); i++)
118                 {
119                         if (objects[i]->Collided(point))
120                         {
121 Dimension * dimension = objects[i]->GetAttachedDimension();
122
123                                 objects.erase(objects.begin() + i);     // Calls the destructor, (deletes the object, I presume... O_o)
124
125 // If this object had an attached dimension, reattach it to another object, if any...
126 // The only problem with that approach is if the object it gets attached to is deleted,
127 // it will call the dimension to use a NULL pointer and BLAMMO
128 if (dimension)
129 {
130         Vector p1 = dimension->GetPoint1();
131         Vector p2 = dimension->GetPoint2();
132         for(int j=0; j<(int)objects.size(); j++)
133         {
134                 Vector * objectP1 = objects[i]->GetPointAt(p1);
135                 Vector * objectP2 = objects[i]->GetPointAt(p2);
136
137                 if (objectP1)
138                         dimension->SetPoint1(objectP1);
139
140                 if (objectP2)
141                         dimension->SetPoint2(objectP2);
142         }
143 }
144
145                                 // This only allows deleting objects one at a time...
146                                 break;
147                                 // however, this way of doing things could be problematic if we don't
148                                 // delete one at a time... Need to come up with a better approach.
149                         }
150                 }
151         }
152         else
153         {
154                 for(int i=0; i<(int)objects.size(); i++)
155                 {
156                         if (objects[i]->Collided(point))
157                                 collision = true;
158                 }
159         }
160 #endif
161
162         // Do we decouple the state of the generic container from the objects inside??? Mebbe.
163         state = OSInactive;
164 //      return false;
165         return collision;
166 }
167
168 // The TLC is passing all mouse movement here, so we're doing the same here.
169 // Need to adjust all other objects to handle things correctly.
170 // One optimization that will need to be done eventually is to subdivide the screen
171 // into parts and keep subdividing until an acceptable number of objects lie within
172 // the slice. This way, the GUI will still be responsive and *not* have to test
173 // every object for collision.
174 /*virtual*/ void Container::PointerMoved(Vector point)
175 {
176 //      objectWasDragged = true;
177 //printf("CONTAINER: PointerMoved()\n");
178
179         for(int i=0; i<(int)objects.size(); i++)
180         {
181 //              if (objects[i]->GetState() == OSSelected)
182                         objects[i]->PointerMoved(point);
183         }
184
185         // Generic container doesn't need this???
186 //      needUpdate = false;
187 }
188
189 /*virtual*/ void Container::PointerReleased(void)
190 {
191         dragging = false;
192         draggingHandle1 = false;
193         draggingHandle2 = false;
194
195         // Here we check for just a click: If object was clicked and dragged, then
196         // revert to the old state (OSInactive). Otherwise, keep the new state that
197         // we set.
198 /*Maybe it would be better to just check for "object was dragged" state and not have to worry
199 about keeping track of old states...
200 */
201         if (objectWasDragged)
202                 state = oldState;
203 //Note that the preceeding is unnecessary for a generic container!
204
205         for(int i=0; i<(int)objects.size(); i++)
206                 objects[i]->PointerReleased();
207 }
208
209 /*virtual*/ bool Container::NeedsUpdate(void)
210 {
211         needUpdate = false;
212
213         for(int i=0; i<(int)objects.size(); i++)
214         {
215                 if (objects[i]->NeedsUpdate())
216                         needUpdate = true;
217         }
218
219         return needUpdate;
220 }
221
222 /*virtual*/ void Container::Add(Object * object)
223 {
224         objects.push_back(object);
225 }