1 // container.cpp: Container object
3 // Part of the Architektonas Project
4 // (C) 2011 Underground Software
5 // See the README and GPLv3 files for licensing and warranty information
7 // JLH = James Hammons <jlhamm@acm.org>
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
16 #include "container.h"
19 #include "dimension.h"
22 Container::Container(Vector p1, Object * p/*= NULL*/): Object(p1, p),
23 dragging(false), draggingHandle1(false), draggingHandle2(false)//, needUpdate(false)
29 Container::Container(const Container & copy): Object(copy.position, copy.parent)
31 // Use overloaded assignment operator
36 Container::~Container()
42 // Assignment operator
43 Container & Container::operator=(const Container & from)
45 // Take care of self-assignment
51 // Small problem with this approach: if the copied object goes out of scope,
52 // all of the objects we copied in here will be deleted. D'oh!
53 for(uint i=0; i<from.objects.size(); i++)
55 Object * object = from.objects[i];
57 // Need to copy the object here...
59 objects.push_back(object);
66 /*virtual*/ void Container::Draw(Painter * painter)
68 for(int i=0; i<(int)objects.size(); i++)
70 printf("Container: About to draw (object = $%X)\n", objects[i]);
71 objects[i]->Draw(painter);
76 /*virtual*/ Vector Container::Center(void)
82 We need at least *three* handles for this object:
87 We need to think about the intuitive way (if there is any) to grab and
88 manipulate a complex object like this... Need to think, "What should happen when
89 I click here and drag there?"
91 Also: should put the snap logic into the Object base class (as a static method)...
95 /*virtual*/ bool Container::Collided(Vector point)
97 objectWasDragged = false;
98 Vector v1 = position - point;
101 if (state == OSInactive)
103 //printf("Circle: pp = %lf, length = %lf, distance = %lf\n", parameterizedPoint, lineSegment.Magnitude(), distance);
104 //printf(" v1.Magnitude = %lf, v2.Magnitude = %lf\n", v1.Magnitude(), v2.Magnitude());
105 //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);
107 //How to translate this into pixels from Document space???
108 //Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
109 //the caller knows about the zoom factor and all that good kinda crap
110 if (v1.Magnitude() < 10.0)
114 oldPoint = position; //maybe "position"?
115 draggingHandle1 = true;
118 else if ((v1.Magnitude() < radius + 2.0) && (v1.Magnitude() > radius - 2.0))
127 else if (state == OSSelected)
129 // Here we test for collision with handles as well! (SOON!)
132 if (v1.Magnitude() < 2.0) // Handle #1
133 else if (v2.Magnitude() < 2.0) // Handle #2
135 if ((v1.Magnitude() < radius + 2.0) && (v1.Magnitude() > radius - 2.0))
138 // state = OSInactive;
145 bool collision = false;
147 // NOTE that this deletes the object on mouse down instead of mouse up. Have to
148 // check to see how it feels to do it that way...
151 for(int i=0; i<(int)objects.size(); i++)
153 if (objects[i]->Collided(point))
155 Dimension * dimension = objects[i]->GetAttachedDimension();
157 Object * objectToDelete = objects[i];
158 objects.erase(objects.begin() + i); // Calls the destructor, (deletes the object, I presume... O_o) [NOPE! SURE DOESN'T!]
159 delete objectToDelete;
161 // If this object had an attached dimension, reattach it to another object, if any...
162 // The only problem with that approach is if the object it gets attached to is deleted,
163 // it will call the dimension to use a NULL pointer and BLAMMO
166 Vector p1 = dimension->GetPoint1();
167 Vector p2 = dimension->GetPoint2();
168 for(int j=0; j<(int)objects.size(); j++)
170 Vector * objectP1 = objects[i]->GetPointAt(p1);
171 Vector * objectP2 = objects[i]->GetPointAt(p2);
174 dimension->SetPoint1(objectP1);
177 dimension->SetPoint2(objectP2);
181 // This only allows deleting objects one at a time...
183 // however, this way of doing things could be problematic if we don't
184 // delete one at a time... Need to come up with a better approach.
190 for(int i=0; i<(int)objects.size(); i++)
192 if (objects[i]->Collided(point))
198 // Do we decouple the state of the generic container from the objects inside??? Mebbe.
205 // The TLC is passing all mouse movement here, so we're doing the same here.
206 // Need to adjust all other objects to handle things correctly.
208 // One optimization that will need to be done eventually is to subdivide the screen
209 // into parts and keep subdividing until an acceptable number of objects lie within
210 // the slice. This way, the GUI will still be responsive and *not* have to test
211 // every object for collision.
212 /*virtual*/ void Container::PointerMoved(Vector point)
214 // objectWasDragged = true;
215 //printf("CONTAINER: PointerMoved()\n");
217 for(int i=0; i<(int)objects.size(); i++)
219 // if (objects[i]->GetState() == OSSelected)
220 objects[i]->PointerMoved(point);
223 // Generic container doesn't need this???
224 // needUpdate = false;
228 /*virtual*/ void Container::PointerReleased(void)
231 draggingHandle1 = false;
232 draggingHandle2 = false;
234 // Here we check for just a click: If object was clicked and dragged, then
235 // revert to the old state (OSInactive). Otherwise, keep the new state that
237 /*Maybe it would be better to just check for "object was dragged" state and not have to worry
238 about keeping track of old states...
240 if (objectWasDragged)
242 //Note that the preceeding is unnecessary for a generic container!
244 for(int i=0; i<(int)objects.size(); i++)
245 objects[i]->PointerReleased();
249 /*virtual*/ bool Container::NeedsUpdate(void)
253 for(uint i=0; i<objects.size(); i++)
255 if (objects[i]->NeedsUpdate())
263 /*virtual*/ void Container::Add(Object * object)
265 objects.push_back(object);
266 printf("Container: Added object (=$%X). size = %li\n", object, objects.size());
270 void Container::Clear(void)
273 while (objects.size() > 0)
275 printf("Container: Deleting object ($%X)...\n", objects[0]);
277 objects.erase(objects.begin());
282 /*virtual*/ void Container::Enumerate(FILE * file)
284 // Only put "CONTAINER" markers if *not* the top level container
286 fprintf(file, "CONTAINER\n");
288 for(uint i=0; i<objects.size(); i++)
289 objects[i]->Enumerate(file);
292 fprintf(file, "ENDCONTAINER\n");