X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fcontainer.cpp;h=e8a66e4d3ba040a178c7eadefc6a5c855adc6aa2;hb=67fbc130b4b6b4d253f69a9c32980d3d3306def5;hp=cd9b4f5ef5880772601dcff6606cc7728e76eb1b;hpb=f3110724be7ad4d4e8c6b97d350ff8af7fbf3799;p=architektonas diff --git a/src/container.cpp b/src/container.cpp index cd9b4f5..e8a66e4 100644 --- a/src/container.cpp +++ b/src/container.cpp @@ -21,9 +21,12 @@ Container::Container(Vector p1, Object * p/*= NULL*/): Object(p1, p), - dragging(false), draggingHandle1(false), draggingHandle2(false)//, needUpdate(false) + isTopLevelContainer(false), + dragging(false), draggingHandle1(false), draggingHandle2(false), + hit(false)//, needUpdate(false) { type = OTContainer; + state = OSInactive; } @@ -33,6 +36,7 @@ Container::Container(const Container & copy): Object(copy.position, copy.parent) // Use overloaded assignment operator *this = copy; type = OTContainer; + state = OSInactive; } @@ -53,11 +57,18 @@ Container & Container::operator=(const Container & from) // Small problem with this approach: if the copied object goes out of scope, // all of the objects we copied in here will be deleted. D'oh! - for(uint i=0; i::const_iterator i; + +// for(uint i=0; iCopy(); - // Need to copy the object here... + // Need to actually COPY the object here, not copy the pointer only!! + // (which we do now, above :-P) objects.push_back(object); } @@ -70,24 +81,23 @@ Container & Container::operator=(const Container & from) { QRectF boundary; +//int a=1; for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) -// for(int i=0; i<(int)objects.size(); i++) { -#if 0 -//printf("Container: About to draw (object = $%X)\n", objects[i]); - objects[i]->Draw(painter); - bounds = bounds.united(objects[i].RectangularExtents()); -#else +//printf("Containter::Draw item #%i [%X]...\n", a++, *i); (*i)->Draw(painter); boundary = boundary.united((*i)->Extents()); -#endif } - if (state == OSSelected) + if ((state == OSSelected) || hit) { - painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DashLine)); + if (hit) + painter->SetPen(QPen(Qt::magenta, 1.0, Qt::DashLine)); + else + painter->SetPen(QPen(Qt::blue, 2.0, Qt::DashLine)); + painter->SetBrush(QBrush(Qt::NoBrush)); - painter->DrawRect(boundary); + painter->DrawPaddedRect(boundary); } } @@ -97,6 +107,7 @@ Container & Container::operator=(const Container & from) return position; } + /* We need at least *three* handles for this object: - one for moving @@ -111,6 +122,14 @@ Also: should put the snap logic into the Object base class (as a static method). */ +// Need to add checking here for clicking on a member of a group (Container), +// and checking for if it's a top level container (the DrawingView's document). +/* +One approach is to check for the parent of the container: If it's NULL, then it's +the DrawingView's document. It might be better, though, to set a boolean like +isTopLevelContainer so that we can do things like edit members of a group without +having to ungroup them first (like Inkscape). +*/ /*virtual*/ bool Container::Collided(Vector point) { objectWasDragged = false; @@ -144,11 +163,41 @@ printf("Container::Collided: Deleting object ($%X)\n", *i); } } - // Do we decouple the state of the generic container from the objects inside??? Mebbe. - state = OSInactive; + if (snapToGrid) + point = SnapPointToGrid(point); + + // We check to see if the container we're trying to access is the + // DrawingView's document. If so, we ignore the state of the container. + // Otherwise, we care about the state of the container. :-) + if (isTopLevelContainer) + state = OSInactive; + else + { + state = (collision ? OSSelected : OSInactive); + + if (state == OSSelected) + { + DeselectAll(); + dragging = true; + oldPoint = point; + } + } + return collision; } +/* +What we need to do is check for whether or not we're a top level container, +and override the passing of stuff into the objects held. So here, if we're *NOT* +a top level container, instead of passing PointerMoved to our contained objects, +we check to see if our bounds are met (for selection rectangle, e.g.). + +Also, for things like being able to split point's hot spots we need to be able +to check for that crap in the top level container. Which means that objects can +still know how to move themselves, but they can also defer to their container +as well. Which also means that things like HitTest() need to be in the Object +class so that we can leverage that stuff here as well. +*/ // The TLC is passing all mouse movement here, so we're doing the same here. // Need to adjust all other objects to handle things correctly. @@ -159,13 +208,63 @@ printf("Container::Collided: Deleting object ($%X)\n", *i); // every object for collision. /*virtual*/ void Container::PointerMoved(Vector point) { -// objectWasDragged = true; -//printf("CONTAINER: PointerMoved()\n"); + std::vector::iterator i; - for(int i=0; i<(int)objects.size(); i++) + if (!isTopLevelContainer) + { + // check for selection rectangle too + if (selectionInProgress) + { + if (selection.contains(Extents())) + state = OSSelected; + else + state = OSInactive; + + return; + } + + // No need to do any checking if we're already selected... +// if (state == OSSelected) +// return; + +// oldState = state; +// needUpdate = true; +// if (dragging && + bool oldHit = hit; + hit = false; + + for(i=objects.begin(); i!=objects.end(); i++) + { + if ((*i)->HitTest(point)) + { +// state = OSSelected; +// return; + hit = true; + break; + } + } + + needUpdate = (oldHit != hit ? true : false); +// state = oldState; + + if (dragging) + { + Vector delta = point - oldPoint; + + for(i=objects.begin(); i!=objects.end(); i++) + (*i)->Translate(delta); + + oldPoint = point; + needUpdate = true; + } + + return; + } + + for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) { // if (objects[i]->GetState() == OSSelected) - objects[i]->PointerMoved(point); + (*i)->PointerMoved(point); } // Generic container doesn't need this??? @@ -175,6 +274,12 @@ printf("Container::Collided: Deleting object ($%X)\n", *i); /*virtual*/ void Container::PointerReleased(void) { + if (!isTopLevelContainer) + { + dragging = false; + return; + } +#if 0 dragging = false; draggingHandle1 = false; draggingHandle2 = false; @@ -182,29 +287,40 @@ printf("Container::Collided: Deleting object ($%X)\n", *i); // Here we check for just a click: If object was clicked and dragged, then // revert to the old state (OSInactive). Otherwise, keep the new state that // we set. -/*Maybe it would be better to just check for "object was dragged" state and not have to worry -about keeping track of old states... +/* +Maybe it would be better to just check for "object was dragged" state and not +have to worry about keeping track of old states... */ if (objectWasDragged) state = oldState; //Note that the preceeding is unnecessary for a generic container! +#endif - for(int i=0; i<(int)objects.size(); i++) - objects[i]->PointerReleased(); +// for(int i=0; i<(int)objects.size(); i++) +// objects[i]->PointerReleased(); + for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) + (*i)->PointerReleased(); } /*virtual*/ bool Container::NeedsUpdate(void) { - needUpdate = false; + // If this is *not* a top level container, then we treat it as an + // aggregate object. + if (!isTopLevelContainer) + { + return needUpdate; + } - for(uint i=0; i::iterator i=objects.begin(); i!=objects.end(); i++) { - if (objects[i]->NeedsUpdate()) - needUpdate = true; + if ((*i)->NeedsUpdate()) + return true; } - return needUpdate; + return false; } @@ -215,12 +331,15 @@ printf("Container: Added object (=$%X). size = %li\n", object, objects.size()); } -#if 0 -/*virtual*/ ObjectType Container::Type(void) +/*virtual*/ QRectF Container::Extents(void) { - return OTContainer; + QRectF bounds; + + for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) + bounds = bounds.united((*i)->Extents()); + + return bounds; } -#endif void Container::Delete(Object * objectToDelete) @@ -260,15 +379,6 @@ void Container::DeleteSelectedItems(void) void Container::Clear(void) { -#if 0 - // No memory leaks! - while (objects.size() > 0) - { -printf("Container: Deleting object ($%X)...\n", objects[0]); - delete objects[0]; - objects.erase(objects.begin()); - } -#else std::vector::iterator i = objects.begin(); while (i != objects.end()) @@ -277,7 +387,6 @@ printf("Container: Deleting object ($%X)...\n", *i); delete (*i); objects.erase(i); } -#endif } @@ -333,8 +442,12 @@ void Container::MoveContentsTo(Container * newContainer) return; // Shuffle the contents of this container to the new one - for(unsigned int i=0; iAdd(objects[i]); +// for(unsigned int i=0; i::iterator i=objects.begin(); i!=objects.end(); i++) + { + newContainer->Add(*i); + (*i)->Reparent(newContainer); + } // & clear our vector objects.clear(); @@ -357,21 +470,94 @@ void Container::MoveSelectedContentsTo(Container * newContainer) } newContainer->Add(*i); + (*i)->Reparent(newContainer); objects.erase(i); } } +void Container::CopySelectedContentsTo(Container * newContainer) +{ + // Sanity check + if (newContainer == NULL) + return; + + // Shuffle the contents of this container to the new one + for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) + { + if ((*i)->state == OSSelected) + newContainer->Add((*i)->Copy()); + } +} + + +void Container::ResizeAllDimensions(double newSize) +{ + for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) + { + if ((*i)->type == OTDimension) + ((Dimension *)(*i))->size = newSize; + if ((*i)->type == OTContainer) + ((Container *)(*i))->ResizeAllDimensions(newSize); + } +} + + /*virtual*/ void Container::Enumerate(FILE * file) { // Only put "CONTAINER" markers if *not* the top level container - if (parent != NULL) - fprintf(file, "CONTAINER\n"); +// if (parent != NULL) + if (!isTopLevelContainer) + fprintf(file, "CONTAINER %i\n", layer); for(uint i=0; iEnumerate(file); - if (parent != NULL) +// if (parent != NULL) + if (!isTopLevelContainer) fprintf(file, "ENDCONTAINER\n"); } + +/*virtual*/ Object * Container::Copy(void) +{ +#warning "!!! This doesn't take care of attached Dimensions !!!" +/* +This is a real problem. While having a pointer in the Dimension to this line's points +is fast & easy, it creates a huge problem when trying to replicate an object like this. + +Maybe a way to fix that then, is to have reference numbers instead of pointers. That +way, if you copy them, ... you might still have problems. Because you can't be sure if +a copy will be persistant or not, you then *definitely* do not want them to have the +same reference number. +*/ + Container * c = new Container(position, parent); + *c = *this; + return c; +} + + +/*virtual*/ void Container::Mirror(Point p1, Point p2) +{ + for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) + (*i)->Mirror(p1, p2); +} + + +/*virtual*/ void Container::Save(void) +{ + Object::Save(); + + for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) + (*i)->Save(); +} + + +/*virtual*/ void Container::Restore(void) +{ + Object::Restore(); + + for(std::vector::iterator i=objects.begin(); i!=objects.end(); i++) + (*i)->Restore(); +} +