]> Shamusworld >> Repos - architektonas/commitdiff
GUI functionality fixes.
authorShamus Hammons <jlhamm@acm.org>
Fri, 29 May 2020 01:22:57 +0000 (20:22 -0500)
committerShamus Hammons <jlhamm@acm.org>
Fri, 29 May 2020 01:22:57 +0000 (20:22 -0500)
 - Dimension offsets work well now.
 - Add pen stamp button, to stamp pen attributes on selected items.
 - Fix std::vector references to use a typedef (VPVector for
   std::vector<void *>, etc.) in order to make the code easier to read &
   understand; vector iterators too.
 - Add ability to select all objects.
 - Adding to selection while holding down CTRL with selection rectangle
   works, deselect objects with single clicks as well.

18 files changed:
TODO
res/architektonas.qrc
res/pen-stamp.png [new file with mode: 0644]
src/applicationwindow.cpp
src/applicationwindow.h
src/drawingview.cpp
src/drawingview.h
src/geometry.cpp
src/geometry.h
src/global.cpp
src/global.h
src/painter.cpp
src/penwidget.cpp
src/penwidget.h
src/structs.h
src/utils.cpp
src/utils.h
src/vector.cpp

diff --git a/TODO b/TODO
index d5ea1c7feafebab38dd487a50b449040ad7691ef..440943875dc5ed738d82c7bbc7ec5e293d704fc8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
+
 Stuff To Be Implemented/Fixed
 -----------------------------
 
@@ -6,10 +7,6 @@ Stuff To Be Implemented/Fixed
  - Add Spline
  - Add Text
  - Object connections (two types: flexible and rigid)
- - Group selection (kinda done, needs more work though)
- - Take movement code out of Objects and put it into top level Container
-   (actually I think this should be more of the state code handling. Have to
-   see.)
  - Add OSD to Object creation
  - Add blocks
  - Add page layout
@@ -31,6 +28,10 @@ Stuff To Be Implemented/Fixed
 Stuff That's Done
 -----------------
 
+ - Group selection (kinda done, needs more work though) [Shamus 2020]
+ - Take movement code out of Objects and put it into top level Container
+   (actually I think this should be more of the state code handling. Have to
+   see.) [Shamus 2015ish, whenever C++ OO was ditched]
  - Add layers [Shamus 2015ish]
  - Add pen color/style/width to Objects [Shamus 2017ish]
  - Fix loading and saving code [Shamus 2016ish]
@@ -45,4 +46,3 @@ Stuff That's Done
  - Mirror tool (started, needs actual mirroring implementation) (Rotate tool is
    also done :-D) [Shamus 2013-09-01]
 
-
index 16283e43573772affd46f94b843b91a693275a3b..a0ae553999d197cc6e6707c4b1d7f06ebbcd3c17 100644 (file)
@@ -43,5 +43,6 @@
                <file>editcut2.png</file>
                <file>editcopy2.png</file>
                <file>editpaste2.png</file>
+               <file>pen-stamp.png</file>
        </qresource>
 </RCC>
diff --git a/res/pen-stamp.png b/res/pen-stamp.png
new file mode 100644 (file)
index 0000000..7afa68e
Binary files /dev/null and b/res/pen-stamp.png differ
index cbb96362521aff7e37a2da3851551026eedde5a7..9064595a5f5feba189e0139ba5e8c18026b9a92e 100644 (file)
@@ -702,7 +702,7 @@ void ApplicationWindow::HandleGridSizeInBaseUnits(QString text)
 void ApplicationWindow::HandleDimensionSize(QString text)
 {
 /*
-This is the third input on the view toolbar; not sure what it was supposed to do...
+This is the third input on the view toolbar; not sure what it was supposed to do... (resize all dimensions in the drawing?)
 */
        // Parse the text...
        bool ok;
@@ -721,7 +721,7 @@ void ApplicationWindow::EditCopy(void)
        if (drawing->select.size() > 0)
        {
                DeleteContents(clipboard);
-               CopySelectedObjectsTo(clipboard, drawing->document.objects);
+               clipboard = CopySelectedObjects(drawing->document.objects);
        }
 }
 
@@ -731,7 +731,7 @@ void ApplicationWindow::EditCut(void)
        if (drawing->select.size() > 0)
        {
                DeleteContents(clipboard);
-               MoveSelectedObjectsTo(clipboard, drawing->document.objects);
+               clipboard = MoveSelectedObjectsFrom(drawing->document.objects);
                drawing->update();
        }
 }
@@ -742,14 +742,26 @@ void ApplicationWindow::EditPaste(void)
        if (clipboard.size() > 0)
        {
                // We want to maybe make it so that the pasted objects are being moved in a "mouse drag" state...
-               // This only moves the cut/copied from the clipboard to the drawing.
-//             AddObjectsTo(drawing->document.objects, clipboard);
-               CopyObjects(clipboard, drawing->document.objects);
+               ClearSelected(drawing->document.objects);
+               SelectAll(clipboard);
+               drawing->document.Add(CopyObjects(clipboard));
                drawing->update();
        }
 }
 
 
+//
+// Select all *visible* objects.  If an object is on a layer that is not
+// visible, skip it.
+//
+void ApplicationWindow::SelectAllObjects(void)
+{
+       // Set object's state & update the drawing
+       SelectAll(drawing->document.objects);
+       drawing->update();
+}
+
+
 void ApplicationWindow::CreateActions(void)
 {
        exitAct = CreateAction(tr("&Quit"), tr("Quit"), tr("Exits the application."),
@@ -844,6 +856,9 @@ void ApplicationWindow::CreateActions(void)
        editPasteAct = CreateAction(tr("&Paste Objects"), tr("Paste Objects"), tr("Paste objects from the clipboard to the drawing."), QIcon(":/res/editpaste2.png"), QKeySequence(tr("Ctrl+v")));
        connect(editPasteAct, SIGNAL(triggered()), this, SLOT(EditPaste()));
 
+       selectAllAct = CreateAction(tr("Select &All"), tr("Select All Objects"), tr("Select all objects in the drawing."), QIcon(), QKeySequence(tr("Ctrl+a")));
+       connect(selectAllAct, SIGNAL(triggered()), this, SLOT(SelectAllObjects()));
+
 //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing...
 // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick.
 /*     QActionGroup * group = new QActionGroup(this);
@@ -919,6 +934,7 @@ void ApplicationWindow::CreateMenus(void)
        menu->addAction(connectAct);
        menu->addAction(disconnectAct);
        menu->addSeparator();
+       menu->addAction(selectAllAct);
        menu->addAction(editCutAct);
        menu->addAction(editCopyAct);
        menu->addAction(editPasteAct);
@@ -999,6 +1015,7 @@ void ApplicationWindow::CreateToolbars(void)
        connect(pw, SIGNAL(WidthSelected(float)), drawing, SLOT(HandlePenWidth(float)));
        connect(pw, SIGNAL(StyleSelected(int)), drawing, SLOT(HandlePenStyle(int)));
        connect(pw, SIGNAL(ColorSelected(uint32_t)), drawing, SLOT(HandlePenColor(uint32_t)));
+       connect(pw, SIGNAL(StampSelected(void)), drawing, SLOT(HandlePenStamp(void)));
 }
 
 
index d10e4dd6c791a1b9db83481912bf6d68e0c99516..0bd35816ea0232c4c11187df5dc8b5d8e67a8745 100644 (file)
@@ -53,6 +53,7 @@ class ApplicationWindow: public QMainWindow
                void EditCut(void);
                void EditCopy(void);
                void EditPaste(void);
+               void SelectAllObjects(void);
 
        signals:
                void ReloadLayers(void);
@@ -108,6 +109,7 @@ class ApplicationWindow: public QMainWindow
                QAction * editCutAct;
                QAction * editCopyAct;
                QAction * editPasteAct;
+               QAction * selectAllAct;
 
                std::vector<void *> clipboard;
 
index 842c5b382fefd3a88f9e2936550a2fc3bd7ce95a..de356d29ddb326a20b54a3ec6f52de56183ae42c 100644 (file)
@@ -48,7 +48,7 @@
 
 DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        // The value in the settings file will override this.
-       useAntialiasing(true), /*numSelected(0),*/ numHovered(0), shiftDown(false),
+       useAntialiasing(true), numHovered(0), shiftDown(false),
        ctrlDown(false), altDown(false),
        gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
        scale(1.0), offsetX(-10), offsetY(-10), document(true),
@@ -239,7 +239,7 @@ zero; so we do another modulus operation on the result to achieve this.
 void DrawingView::DeleteCurrentLayer(int layer)
 {
 //printf("DrawingView::DeleteCurrentLayer(): currentLayer = %i\n", layer);
-       std::vector<void *>::iterator i = document.objects.begin();
+       VPVectorIter i = document.objects.begin();
 
        while (i != document.objects.end())
        {
@@ -277,10 +277,9 @@ void DrawingView::HandleLayerToggle(void)
 //
 void DrawingView::HandleLayerSwap(int layer1, int layer2)
 {
+// !!! FIX !!! This doesn't properly handle container contents...
 //printf("DrawingView: Swapping layers %i and %i.\n", layer1, layer2);
-       std::vector<void *>::iterator i;
-
-       for(i=document.objects.begin(); i!=document.objects.end(); i++)
+       for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
        {
                Object * obj = (Object *)(*i);
 
@@ -294,9 +293,7 @@ void DrawingView::HandleLayerSwap(int layer1, int layer2)
 
 void DrawingView::HandlePenWidth(float width)
 {
-       std::vector<void *>::iterator i = select.begin();
-
-       for(; i!=select.end(); i++)
+       for(VPVectorIter i=select.begin(); i!=select.end(); i++)
        {
                Object * obj = (Object *)(*i);
                obj->thickness = width;
@@ -306,9 +303,7 @@ void DrawingView::HandlePenWidth(float width)
 
 void DrawingView::HandlePenStyle(int style)
 {
-       std::vector<void *>::iterator i = select.begin();
-
-       for(; i!=select.end(); i++)
+       for(VPVectorIter i=select.begin(); i!=select.end(); i++)
        {
                Object * obj = (Object *)(*i);
                obj->style = style;
@@ -318,9 +313,7 @@ void DrawingView::HandlePenStyle(int style)
 
 void DrawingView::HandlePenColor(uint32_t color)
 {
-       std::vector<void *>::iterator i = select.begin();
-
-       for(; i!=select.end(); i++)
+       for(VPVectorIter i=select.begin(); i!=select.end(); i++)
        {
                Object * obj = (Object *)(*i);
                obj->color = color;
@@ -328,6 +321,25 @@ void DrawingView::HandlePenColor(uint32_t color)
 }
 
 
+void DrawingView::HandlePenStamp(void)
+{
+       VPVector flat = Flatten(select);
+
+       for(VPVectorIter i=flat.begin(); i!=flat.end(); i++)
+       {
+               Object * obj = (Object *)(*i);
+
+               if (obj->type != OTText)
+                       obj->thickness = Global::penWidth;
+
+               obj->style = Global::penStyle;
+               obj->color = Global::penColor;
+       }
+
+       update();
+}
+
+
 QPoint DrawingView::GetAdjustedMousePosition(QMouseEvent * event)
 {
        // This is undoing the transform, e.g. going from client coords to local
@@ -416,11 +428,9 @@ N.B.: Since we have "hoverPointValid" drawing regular object handles above,
       !!! FIX !!!
       [Well, it seems to work OK *except* when you move one of the points, then you get to see nothing. Is it worth fixing there to get rid of problems here? Have to investigate...]
 */
-void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int layer, bool ignoreLayer/*= false*/)
+void DrawingView::RenderObjects(Painter * painter, VPVector & v, int layer, bool ignoreLayer/*= false*/)
 {
-       std::vector<void *>::iterator i;
-
-       for(i=v.begin(); i!=v.end(); i++)
+       for(VPVectorIter i=v.begin(); i!=v.end(); i++)
        {
                Object * obj = (Object *)(*i);
                float scaledThickness = Global::scale * obj->thickness;
@@ -541,10 +551,10 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int
 
                        unit = Vector(d->lp[0], d->lp[1]).Unit();
 
-                       Point p1 = d->lp[0] + (ortho * (10.0 + d->offset) * scaledThickness);
-                       Point p2 = d->lp[1] + (ortho * (10.0 + d->offset) * scaledThickness);
-                       Point p3 = d->lp[0] + (ortho * (16.0 + d->offset) * scaledThickness);
-                       Point p4 = d->lp[1] + (ortho * (16.0 + d->offset) * scaledThickness);
+                       Point p1 = d->lp[0] + (ortho * (d->offset + (10.0 * scaledThickness)));
+                       Point p2 = d->lp[1] + (ortho * (d->offset + (10.0 * scaledThickness)));
+                       Point p3 = d->lp[0] + (ortho * (d->offset + (16.0 * scaledThickness)));
+                       Point p4 = d->lp[1] + (ortho * (d->offset + (16.0 * scaledThickness)));
                        Point p5 = d->p[0] + (ortho * 4.0 * scaledThickness);
                        Point p6 = d->p[1] + (ortho * 4.0 * scaledThickness);
 
@@ -599,6 +609,9 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int
                                        dimText = QString("%1' %2\"").arg(feet).arg(inches);
                        }
 
+/*
+Where is the text offset?  It looks like it's drawing in the center, but obviously it isn't.  It isn't here, it's in Painter::DrawAngledText().
+*/
                        painter->DrawAngledText(ctr, angle, dimText, scaledThickness);
 
                        if (d->hitObject)
@@ -699,24 +712,25 @@ printf("About to render container: # objs=%i, layer=%i\n", (*c).objects.size(),
 }
 
 
+//
+// This toggles the selection being hovered (typically, only 1 object)
+//
 void DrawingView::AddHoveredToSelection(void)
 {
-       std::vector<void *>::iterator i;
-
-       for(i=document.objects.begin(); i!=document.objects.end(); i++)
+       for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
        {
                if (((Object *)(*i))->hovered)
-                       ((Object *)(*i))->selected = true;
+//                     ((Object *)(*i))->selected = true;
+                       ((Object *)(*i))->selected = !((Object *)(*i))->selected;
        }
 }
 
 
-void DrawingView::GetSelection(std::vector<void *> & v)
+void DrawingView::GetSelection(VPVector & v)
 {
        v.clear();
-       std::vector<void *>::iterator i;
 
-       for(i=document.objects.begin(); i!=document.objects.end(); i++)
+       for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
        {
                if (((Object *)(*i))->selected)
                        v.push_back(*i);
@@ -724,36 +738,28 @@ void DrawingView::GetSelection(std::vector<void *> & v)
 }
 
 
-#if 0
-void DrawingView::GetHovered(std::vector<void *> & v)
+VPVector DrawingView::GetSelection(void)
 {
-       v.clear();
-       std::vector<void *>::iterator i;
+       VPVector v;
 
-       for(i=document.objects.begin(); i!=document.objects.end(); i++)
+       for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
        {
-               if (((Object *)(*i))->hovered)
-//             {
-//printf("GetHovered: adding object (%X) to hover... hp1=%s, hp2=%s, hl=%s\n", (*i), (((Line *)(*i))->hitPoint[0] ? "true" : "false"), (((Line *)(*i))->hitPoint[1] ? "true" : "false"), (((Line *)(*i))->hitObject ? "true" : "false"));
+               if (((Object *)(*i))->selected)
                        v.push_back(*i);
-//             }
        }
+
+       return v;
 }
-#endif
 
 
-std::vector<void *> DrawingView::GetHovered(void)
+VPVector DrawingView::GetHovered(void)
 {
-       std::vector<void *> v;
-       std::vector<void *>::iterator i;
+       VPVector v;
 
-       for(i=document.objects.begin(); i!=document.objects.end(); i++)
+       for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
        {
                if (((Object *)(*i))->hovered)
-//             {
-//printf("GetHovered: adding object (%X) to hover... hp1=%s, hp2=%s, hl=%s\n", (*i), (((Line *)(*i))->hitPoint[0] ? "true" : "false"), (((Line *)(*i))->hitPoint[1] ? "true" : "false"), (((Line *)(*i))->hitObject ? "true" : "false"));
                        v.push_back(*i);
-//             }
        }
 
        return v;
@@ -1152,9 +1158,9 @@ void DrawingView::RotateHandler(int mode, Point p)
 
                        angleSnap = true;
                        double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
-                       std::vector<void *>::iterator j = select.begin();
+                       VPVectorIter j = select.begin();
 //                     std::vector<Object>::iterator i = toolScratch.begin();
-                       std::vector<void *>::iterator i = toolScratch2.begin();
+                       VPVectorIter i = toolScratch2.begin();
 
 //                     for(; i!=toolScratch.end(); i++, j++)
                        for(; i!=toolScratch2.end(); i++, j++)
@@ -1187,10 +1193,10 @@ void DrawingView::RotateHandler(int mode, Point p)
 //                                     Container * c = (Container *)&objT;
                                        Container * c = (Container *)objT;
                                        Container * c2 = (Container *)objS;
-                                       std::vector<void *>::iterator l = c->objects.begin();
+                                       VPVectorIter l = c->objects.begin();
                                        // TODO: Rotate items in the container
                                        // TODO: Make this recursive
-                                       for(std::vector<void *>::iterator k=c2->objects.begin(); k!=c2->objects.end(); k++, l++)
+                                       for(VPVectorIter k=c2->objects.begin(); k!=c2->objects.end(); k++, l++)
                                        {
                                                Object * obj3 = (Object *)(*k);
                                                Object * obj4 = (Object *)(*l);
@@ -1235,7 +1241,7 @@ void DrawingView::RotateHandler(int mode, Point p)
                        if (ctrlDown)
                        {
                                // Stamp a copy of the selection at the current rotation & bail
-                               std::vector<void *> temp;
+                               VPVector temp;
                                CopyObjects(select, temp);
                                ClearSelected(temp);
                                AddObjectsTo(document.objects, temp);
@@ -1306,7 +1312,7 @@ void DrawingView::MirrorHandler(int mode, Point p)
 
                        angleSnap = true;
                        double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
-                       std::vector<void *>::iterator j = select.begin();
+                       VPVectorIter j = select.begin();
                        std::vector<Object>::iterator i = toolScratch.begin();
 
                        for(; i!=toolScratch.end(); i++, j++)
@@ -1355,7 +1361,7 @@ N.B.: When mirroring an arc thru a horizontal axis, this causes the arc to have
                        if (ctrlDown)
                        {
                                // Stamp a copy of the selection at the current rotation & bail
-                               std::vector<void *> temp;
+                               VPVector temp;
                                CopyObjects(select, temp);
                                ClearSelected(temp);
                                AddObjectsTo(document.objects, temp);
@@ -1444,7 +1450,7 @@ void DrawingView::TriangulateHandler(int mode, Point/*p*/)
                if (numHovered != 1)
                        break;
 
-               std::vector<void *> hover = GetHovered();
+               VPVector hover = GetHovered();
                Object * obj = (Object *)hover[0];
 
                // Skip if it's not a line...
@@ -1613,7 +1619,7 @@ n.b.: this code is lifted straight out of the old oo code.  needs to be updated.
                        return;
                }
 
-               std::vector<void *> hover = GetHovered();
+               VPVector hover = GetHovered();
                Object * obj = (Object *)hover[0];
 
                // Skip if it's not a line...
@@ -1628,7 +1634,7 @@ n.b.: this code is lifted straight out of the old oo code.  needs to be updated.
 
                // Currently only deal with line against line trimming, can expand to
                // others as well (line/circle, circle/circle, line/arc, etc)
-               std::vector<void *>::iterator i;
+               VPVectorIter i;
                for(i=document.objects.begin(); i!=document.objects.end(); i++)
                {
                        obj = (Object *)(*i);
@@ -1692,7 +1698,7 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::LeftButton)
        {
-printf("mousePressEvent::Qt::LeftButton numHovered=%li\n", numHovered);
+//printf("mousePressEvent::Qt::LeftButton numHovered=%li\n", numHovered);
                Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
 
                // Handle tool processing, if any
@@ -1727,10 +1733,10 @@ printf("mousePressEvent::Qt::LeftButton numHovered=%li\n", numHovered);
                        AddHoveredToSelection();
                        update();       // needed??
 //                     GetHovered(hover);      // prolly needed
-                       std::vector<void *> hover2 = GetHovered();
+                       VPVector hover2 = GetHovered();
                        dragged = (Object *)hover2[0];
                        draggingObject = true;
-printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged, objName[dragged->type]);
+//printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged, objName[dragged->type]);
 
                        // Alert the pen widget
                        emit ObjectSelected(dragged);
@@ -1770,10 +1776,12 @@ printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged,
                        return;
                }
 
-               // Didn't hit any object and not using a tool, so do a selection rectangle
+               // Didn't hit any object and not using a tool, so do a selection
+               // rectangle
                Global::selectionInProgress = true;
                Global::selection.setTopLeft(QPointF(point.x, point.y));
                Global::selection.setBottomRight(QPointF(point.x, point.y));
+               select = GetSelection();
        }
        else if (event->button() == Qt::MiddleButton)
        {
@@ -1817,14 +1825,19 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
        if (Global::selectionInProgress)
        {
                CheckObjectBounds();
+
+               // Make sure previously selected objects stay selected (CTRL held)
+               for(VPVectorIter i=select.begin(); i!=select.end(); i++)
+                       ((Object *)(*i))->selected = true;
+
                update();
                return;
        }
 
        // Do object hit testing...
        bool needUpdate = HitTestObjects(point);
-//     GetHovered(hover);
-       std::vector<void *> hover2 = GetHovered();
+       VPVector hover2 = GetHovered();
+#if 0
 {
 if (needUpdate)
 {
@@ -1834,6 +1847,7 @@ if (needUpdate)
                printf("                 (hover2[0]=$%llX, type=%s)\n", hover2[0], objName[((Object *)hover2[0])->type]);
 }
 }
+#endif
 
        // Check for multi-hover...
        if (numHovered > 1)
@@ -1962,23 +1976,17 @@ void DrawingView::mouseReleaseEvent(QMouseEvent * event)
                        return;
                }
 
-               if (Global::selectionInProgress)
+//             if (Global::selectionInProgress)
                        Global::selectionInProgress = false;
 
                informativeText.clear();
 // Should we be doing this automagically? Hmm...
                // Clear our vectors
-               select.clear();
-//             hover.clear();
-
-               // Scoop 'em up
-               std::vector<void *>::iterator i;
+//             select.clear();
+////           hover.clear();
 
-               for(i=document.objects.begin(); i!=document.objects.end(); i++)
-               {
-                       if (((Object *)(*i))->selected)
-                               select.push_back(*i);
-               }
+               // Scoop 'em up (do we need to??? Seems we do, because keyboard movement uses it.  Also, tools use it too.  But we can move it out of here)
+               select = GetSelection();
 
                draggingObject = false;
        }
@@ -2000,12 +2008,18 @@ void DrawingView::wheelEvent(QWheelEvent * event)
        // This is not centering for some reason. Need to figure out why. :-/
        if (event->delta() > 0)
        {
+               if (Global::zoom > 20.0)
+                       return;
+
                Vector newOrigin = center - ((center - Global::origin) / zoomFactor);
                Global::origin = newOrigin;
                Global::zoom *= zoomFactor;
        }
        else
        {
+               if (Global::zoom < 0.25)
+                       return;
+
                Vector newOrigin = center + ((-center + Global::origin) * zoomFactor);
                Global::origin = newOrigin;
                Global::zoom /= zoomFactor;
@@ -2032,6 +2046,8 @@ void DrawingView::keyPressEvent(QKeyEvent * event)
        else if (event->key() == Qt::Key_Alt)
                altDown = true;
 
+       // If there's a change in any of the modifier key states, pass it on to
+       // the current tool's handler
        if ((oldShift != shiftDown) || (oldCtrl != ctrlDown))
        {
                if (Global::tool)
@@ -2210,7 +2226,7 @@ Rect DrawingView::GetObjectExtents(Object * obj)
        case OTContainer:
        {
                Container * c = (Container *)obj;
-               std::vector<void *>::iterator i = c->objects.begin();
+               VPVectorIter i = c->objects.begin();
                rect = GetObjectExtents((Object *)*i);
                i++;
 
@@ -2228,7 +2244,7 @@ Rect DrawingView::GetObjectExtents(Object * obj)
 
 void DrawingView::CheckObjectBounds(void)
 {
-       std::vector<void *>::iterator i;
+       VPVectorIter i;
 
        for(i=document.objects.begin(); i!=document.objects.end(); i++)
        {
@@ -2355,7 +2371,7 @@ void DrawingView::CheckObjectBounds(void)
 
 bool DrawingView::HitTestObjects(Point point)
 {
-       std::vector<void *>::iterator i;
+       VPVectorIter i;
        numHovered = 0;
        bool needUpdate = false;
        hoverPointValid = false;
@@ -2514,8 +2530,13 @@ bool DrawingView::HitTest(Object * obj, Point point)
                Vector orthogonal = Vector::Normal(d->lp[0], d->lp[1]);
                // Get our line parallel to our points
                float scaledThickness = Global::scale * obj->thickness;
+#if 1
+               Point p1 = d->lp[0] + (orthogonal * (d->offset + (10.0 * scaledThickness)));
+               Point p2 = d->lp[1] + (orthogonal * (d->offset + (10.0 * scaledThickness)));
+#else
                Point p1 = d->lp[0] + (orthogonal * (10.0 + d->offset) * scaledThickness);
                Point p2 = d->lp[1] + (orthogonal * (10.0 + d->offset) * scaledThickness);
+#endif
                Point p3(p1, point);
 
                Vector v1(d->p[0], point);
@@ -2592,16 +2613,15 @@ still need to compare old state to new state, and set things up based upon that.
 likely we can just rely on the object itself and steal its state like we have in the commented out portion below; can prolly rewrite the HitTest() portion to be one line: needUpdate = HitTest(cObj, point);
 Well, you could if there was only one object in the Container.  But since there isn't, we have to keep the if HitTest() == true then needUpdate = true bit.  Because otherwise, a false result anywhere will kill the needed update elsewhere.
 */
-
                Container * c = (Container *)obj;
                c->hitObject = false;
                c->hovered = false;
                c->clicked = NULL;
 
-               std::vector<void *> flat = Flatten(c);
+               VPVector flat = Flatten(c);
 
 //printf("HitTest::OTContainer (size=%li)\n", flat.size());
-               for(std::vector<void *>::iterator i=flat.begin(); i!=flat.end(); i++)
+               for(VPVectorIter i=flat.begin(); i!=flat.end(); i++)
                {
                        Object * cObj = (Object *)(*i);
 
@@ -2643,6 +2663,13 @@ Well, you could if there was only one object in the Container.  But since there
                                c->clicked = cObj;
                        }//*/
 
+                       if (cObj->hitPoint[2] == true)
+                       {
+//printf("HitTest::cObj->hitObject == true! ($%llX)\n", cObj);
+                               c->hitPoint[2] = true;
+                               c->clicked = cObj;
+                       }//*/
+
                        if (cObj->hovered == true)
                                c->hovered = true;//*/
                }
@@ -2834,8 +2861,24 @@ void DrawingView::HandleObjectMovement(Point point)
                        obj->p[1] = point;
                else if (obj->hitObject)
                {
-                       obj->p[0] += delta;
-                       obj->p[1] += delta;
+                       // Move measurement lines in/out
+                       if (shiftDown)
+                       {
+                               Dimension * d = (Dimension *)obj;
+                               double dist = Geometry::DistanceToLineFromPoint(d->lp[0], d->lp[1], point);
+                               float scaledThickness = Global::scale * obj->thickness;
+                               // Looks like offset is 0 to +MAX, but line is at 10.0.  So
+                               // anything less than 10.0 should set the offset to 0.
+                               d->offset = 0;
+
+                               if (dist > (10.0 * scaledThickness))
+                                       d->offset = dist - (10.0 * scaledThickness);
+                       }
+                       else
+                       {
+                               obj->p[0] += delta;
+                               obj->p[1] += delta;
+                       }
                }
 
                break;
index 768c5c029b26a518b2f7959eaa8d2987f9aa53b9..7e5a9d1db52b212509ef5041ba283e7a4c8f9ded 100644 (file)
@@ -22,11 +22,11 @@ class DrawingView: public QWidget
                void UpdateGridBackground(void);
                Point SnapPointToGrid(Point);
                Point SnapPointToAngle(Point);
-               void RenderObjects(Painter *, std::vector<void *> &, int, bool ignoreLayer = false);
+               void RenderObjects(Painter *, VPVector &, int, bool ignoreLayer = false);
                void AddHoveredToSelection(void);
-               void GetSelection(std::vector<void *> &);
-//             void GetHovered(std::vector<void *> &);
-               std::vector<void *> GetHovered(void);
+               void GetSelection(VPVector &);
+               VPVector GetSelection(void);
+               VPVector GetHovered(void);
                void ToolHandler(int, Point);
                void ToolDraw(Painter *);
                void LineHandler(int, Point);
@@ -53,6 +53,7 @@ class DrawingView: public QWidget
                void HandlePenWidth(float);
                void HandlePenStyle(int);
                void HandlePenColor(uint32_t);
+               void HandlePenStamp(void);
 
        signals:
                void ObjectHovered(Object *);
@@ -95,11 +96,10 @@ class DrawingView: public QWidget
                QString informativeText;
 
        public:
-               std::vector<void *> select;
-//             std::vector<void *> hover;
-               std::vector<void *> toolObjects;
+               VPVector select;
+               VPVector toolObjects;
                std::vector<Object> toolScratch;
-               std::vector<void *> toolScratch2;
+               VPVector toolScratch2;
                Point toolPoint[32];
                Object * toolObj[32];
                Point intersectionPoint;
index 4cd229f76da7967d10811ed3ff803a0d46427e92..95d12c65068b16715086191e1d70c7e01483dcbd 100644 (file)
@@ -39,6 +39,29 @@ double Geometry::ParameterOfLineAndPoint(Point tail, Point head, Point point)
 }
 
 
+double Geometry::DistanceToLineFromPoint(Point tail, Point head, Point point)
+{
+       // Interpretation: given a line in the form x = a + tu, where u is the
+       // unit vector of the line, a is the tail and t is a parameter which
+       // describes the line, the distance of a point p to the line is given by:
+       // || (a - p) - ((a - p) . u) u ||
+       // We go an extra step: we set the sign to reflect which side of the line
+       // it's on (+ == to the left if head points away from you, - == to the
+       // right)
+       Vector line(tail, head);
+       Vector u = line.Unit();
+       Vector a_p = tail - point;
+       Vector dist = a_p - (u * (a_p).Dot(u));
+
+       double angle = Vector::Angle(tail, point) - line.Angle();
+
+       if (angle < 0)
+               angle += TAU;
+
+       return dist.Magnitude() * (angle < HALF_TAU ? +1.0 : -1.0);
+}
+
+
 Point Geometry::MirrorPointAroundLine(Point point, Point tail, Point head)
 {
        // Get the vector of the intersection of the line and the normal on the
index 41cd472580f30621d546a45d658aaa4a2e8eab6a..bc532da4a9a3e0e206a06144ba9b01dff22ab1bd 100644 (file)
@@ -9,6 +9,7 @@ class Geometry
        public:
                // All methods are class methods for this class
                static double ParameterOfLineAndPoint(Point, Point, Point);
+               static double DistanceToLineFromPoint(Point, Point, Point);
                static Point MirrorPointAroundLine(Point, Point, Point);
                static Point RotatePointAroundPoint(Point, Point, double);
                static double Determinant(Point, Point);
index 6dfbd901ca140d7f8ec0d9db1476235d15fd1dda..7a7cc9b7739829fc1db6e63faef40a29d6d5c847 100644 (file)
@@ -49,6 +49,6 @@ int Global::numIntersectParams = 0;
 
 int Global::activeLayer = 0;
 int Global::numLayers = 1;
-std::vector<bool> Global::layerHidden;
-std::vector<bool> Global::layerLocked;
-std::vector<std::string> Global::layerName;
+BVector Global::layerHidden;
+BVector Global::layerLocked;
+SVector Global::layerName;
index cdcd204e800d153b67ce45eb39f0073b41b3a4e3..93ad6f7f9484a23ecdba2b373f60413b587cb37f 100644 (file)
@@ -14,6 +14,10 @@ class QFont;
 
 enum LineStyle { LSNone, LSSolid, LSDash, LSDot, LSDashDot, LSDashDotDot };
 
+typedef std::vector<void *> VPVector;
+typedef std::vector<void *>::iterator VPVectorIter;
+typedef std::vector<bool> BVector;
+typedef std::vector<std::string> SVector;
 
 class Global
 {
@@ -56,9 +60,9 @@ class Global
 
                static int activeLayer;
                static int numLayers;
-               static std::vector<bool> layerHidden;
-               static std::vector<bool> layerLocked;
-               static std::vector<std::string> layerName;
+               static BVector layerHidden;
+               static BVector layerLocked;
+               static SVector layerName;
 };
 
 #endif // __GLOBALS_H__
index 16edb26e580c7aae7f42086abe2479182f134471..6cb74eac9c3998fd5ebc51254fc3e69955b2d3b4 100644 (file)
@@ -139,13 +139,15 @@ void Painter::DrawAngledText(Vector center, double angle, QString text, double s
        // Need to figure out if dimensions are always rendered at one size
        // regardless of zoom, or if they have a definite size, and are thus
        // zoomable.
-       float yOffset = -12.0 * Global::zoom * size;
+//     float yOffset = -12.0 * Global::zoom * size;
+       float yOffset = -8.0 * Global::zoom * size;
 
        // Fix text so it isn't upside down...
        if ((angle > QTR_TAU) && (angle < THREE_QTR_TAU))
        {
                angle += HALF_TAU;
-               yOffset = 12.0 * Global::zoom * size;
+//             yOffset = 12.0 * Global::zoom * size;
+               yOffset = 8.0 * Global::zoom * size;
        }
 
        textBox.translate(0, yOffset);
index 2a557e39d150f54ab48e080eace9d234d0425aee..4bd966af36e2af3cf3ac4e1f8c1d7a893f768f33 100644 (file)
@@ -29,6 +29,14 @@ PenWidget::PenWidget(void): QWidget(), r(0), g(0), b(0), programChange(false)
        QLabel * l1 = new QLabel(tr("Width:"));
        QLabel * l2 = new QLabel(tr("RGB:"));
        QLabel * l3 = new QLabel(tr("Style:"));
+       QToolButton * qtb = new QToolButton(this);
+
+       QAction * action = new QAction(QIcon(":/res/pen-stamp.png"), tr(""), this);
+       action->setToolTip(tr("Stamp Selected"));
+       action->setStatusTip(tr("Stamp selected objects with pen attributes."));
+       action->setShortcut(QKeySequence(tr("p,p")));
+//     action->setCheckable(checkable);
+       qtb->setDefaultAction(action);
 
        style->insertItem(1, tr("Solid"));
        style->insertItem(2, tr("Dash"));
@@ -63,6 +71,7 @@ PenWidget::PenWidget(void): QWidget(), r(0), g(0), b(0), programChange(false)
        hbox1->addWidget(blue, 0, Qt::AlignLeft);
        hbox1->addWidget(l3, 0, Qt::AlignLeft);
        hbox1->addWidget(style, 0, Qt::AlignLeft);
+       hbox1->addWidget(qtb, 0, Qt::AlignLeft);
        hbox1->addStretch(1);
 
        setLayout(hbox1);
@@ -72,6 +81,7 @@ PenWidget::PenWidget(void): QWidget(), r(0), g(0), b(0), programChange(false)
        connect(green, SIGNAL(textEdited(QString)), this, SLOT(HandleGreenSelected(QString)));
        connect(blue, SIGNAL(textEdited(QString)), this, SLOT(HandleBlueSelected(QString)));
        connect(style, SIGNAL(currentIndexChanged(int)), this, SLOT(HandleStyleSelected(int)));
+       connect(qtb, SIGNAL(triggered(QAction *)), this, SLOT(HandleStamp(QAction *)));
 }
 
 
@@ -175,3 +185,9 @@ void PenWidget::HandleBlueSelected(QString text)
        emit ColorSelected(Global::penColor);
 }
 
+
+void PenWidget::HandleStamp(QAction * /* action */)
+{
+       emit StampSelected();
+}
+
index 11dcdcf44b67097a3f5436c8ba1e14ab5f08cdb2..5809c446731a5e3669826615cf43d9d53a05532c 100644 (file)
@@ -22,11 +22,13 @@ class PenWidget: public QWidget
                void HandleRedSelected(QString);
                void HandleGreenSelected(QString);
                void HandleBlueSelected(QString);
+               void HandleStamp(QAction *);
 
        signals:
                void WidthSelected(float);
                void StyleSelected(int);
                void ColorSelected(uint32_t);
+               void StampSelected(void);
 
        private:
                QLineEdit * width;
index 5f694886d5b079843c05ce5db191f8bd8a9c8525..bef3c52f93879fa24f545b90ca9cf4cdc97ac813 100644 (file)
@@ -128,13 +128,14 @@ struct Spline {
 
 struct Container {
        OBJECT_COMMON;
-       std::vector<void *> objects;
+       VPVector objects;
        double scale;
        bool topLevel;
        Object * clicked;
 
        Container(bool tl = false): type(OTContainer), id(Global::objectID++), selected(false), hovered(false), hitObject(false), topLevel(tl), clicked(NULL) {}
        void Add(void * obj) { objects.push_back(obj); }
+       void Add(VPVector objs) { objects.insert(objects.end(), objs.begin(), objs.end()); }
 //     void DeleteContents(void) {}
 /*     void DeleteContents(Container * c)
        {
index 98902d7a80a439de0b39a6a0613e963dde30d1aa..b9ca463bbc948bda5ba79bcfeaa220af0588d0c3 100644 (file)
@@ -12,6 +12,7 @@
 //
 
 #include "utils.h"
+#include <math.h>
 #include <string.h>            // For memcpy()
 #include "geometry.h"
 
@@ -20,9 +21,9 @@
 // Copy objects in one vector to another, creating copies and placing them in
 // the other vector. Clearing & etc. of vectors is responsibility of the caller!
 //
-void CopyObjects(std::vector<void *> & from, std::vector<void *> & to)
+void CopyObjects(VPVector & from, VPVector & to)
 {
-       for(std::vector<void *>::iterator i=from.begin(); i!=from.end(); i++)
+       for(VPVectorIter i=from.begin(); i!=from.end(); i++)
        {
                Object * obj = (Object *)(*i);
                Object * newObject = CopyObject(obj);
@@ -31,6 +32,20 @@ void CopyObjects(std::vector<void *> & from, std::vector<void *> & to)
 }
 
 
+VPVector CopyObjects(VPVector & src)
+{
+       VPVector copy;
+
+       for(VPVectorIter i=src.begin(); i!=src.end(); i++)
+       {
+               Object * newObject = CopyObject2((Object *)(*i));
+               copy.push_back(newObject);
+       }
+
+       return copy;
+}
+
+
 //
 // Create a copy of the passed in object.
 //
@@ -60,12 +75,10 @@ Object * CopyObject(Object * obj)
                newObject = new Dimension();
                memcpy(newObject, obj, sizeof(Dimension));
                break;
-#if 0
        case OTSpline:
                newObject = new Spline();
                memcpy(newObject, obj, sizeof(Spline));
                break;
-#endif
        case OTText:
                newObject = new Text();
                memcpy(newObject, obj, sizeof(Text));
@@ -77,6 +90,7 @@ Object * CopyObject(Object * obj)
 //             memcpy(newObject, obj, sizeof(Line));
                ((Container *)newObject)->p[0] = obj->p[0];
                ((Container *)newObject)->p[1] = obj->p[1];
+               ((Container *)newObject)->layer = obj->layer;
                CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects);
                break;
        default:
@@ -91,9 +105,72 @@ Object * CopyObject(Object * obj)
 }
 
 
-void MoveSelectedObjectsTo(std::vector<void *> & dest, std::vector<void *> & from)
+//
+// Create a copy of the passed in object.  This version calls the second
+// version of CopyObjects() (with one parameter and a vector return value).
+//
+Object * CopyObject2(Object * obj)
+{
+       void * newObject = NULL;
+
+       switch (obj->type)
+       {
+       case OTLine:
+               newObject = new Line();
+               memcpy(newObject, obj, sizeof(Line));
+               break;
+
+       case OTCircle:
+               newObject = new Circle();
+               memcpy(newObject, obj, sizeof(Circle));
+               break;
+
+       case OTEllipse:
+               newObject = new Ellipse();
+               memcpy(newObject, obj, sizeof(Ellipse));
+               break;
+
+       case OTArc:
+               newObject = new Arc();
+               memcpy(newObject, obj, sizeof(Arc));
+               break;
+
+       case OTDimension:
+               newObject = new Dimension();
+               memcpy(newObject, obj, sizeof(Dimension));
+               break;
+
+       case OTSpline:
+               newObject = new Spline();
+               memcpy(newObject, obj, sizeof(Spline));
+               break;
+
+       case OTText:
+               newObject = new Text();
+               memcpy(newObject, obj, sizeof(Text));
+               ((Text *)newObject)->s = ((Text *)obj)->s;
+               break;
+
+       case OTContainer:
+               newObject = new Container();
+               ((Container *)newObject)->p[0] = obj->p[0];
+               ((Container *)newObject)->p[1] = obj->p[1];
+               ((Container *)newObject)->layer = obj->layer;
+               ((Container *)newObject)->objects = CopyObjects(((Container *)obj)->objects);
+               break;
+       }
+
+       // Fix objectID
+       if (newObject && (((Object *)newObject)->type != OTContainer))
+               ((Object *)newObject)->id = Global::objectID++;
+
+       return (Object *)newObject;
+}
+
+
+void MoveSelectedObjectsTo(VPVector & dest, VPVector & from)
 {
-       std::vector<void *>::iterator i = from.begin();
+       VPVectorIter i = from.begin();
 
        while (i != from.end())
        {
@@ -110,45 +187,83 @@ void MoveSelectedObjectsTo(std::vector<void *> & dest, std::vector<void *> & fro
 }
 
 
+VPVector MoveSelectedObjectsFrom(VPVector & from)
+{
+       VPVector objects;
+       VPVectorIter i = from.begin();
+
+       while (i != from.end())
+       {
+               Object * obj = (Object *)(*i);
+
+               if (obj->selected)
+               {
+                       objects.push_back(*i);
+                       from.erase(i);
+               }
+               else
+                       i++;
+       }
+
+       return objects;
+}
+
+
 //hmm, this won't work, as these are just pointers...
 //[should work now]
-void CopySelectedObjectsTo(std::vector<void *> & dest, std::vector<void *> & from)
+void CopySelectedObjectsTo(VPVector & dest, VPVector & from)
 {
-       for(std::vector<void *>::iterator i=from.begin(); i!=from.end(); i++)
+       for(VPVectorIter i=from.begin(); i!=from.end(); i++)
        {
                Object * obj = (Object *)(*i);
 
                if (obj->selected)
-//             {
-//                     Object * newObject = CopyObject(obj);
-                       dest.push_back(CopyObject(obj));
-//             }
+                       dest.push_back(CopyObject2(obj));
        }
 }
 
 
-void AddObjectsTo(std::vector<void *> & dest, std::vector<void *> & from)
+VPVector CopySelectedObjects(VPVector & src)
 {
-       for(std::vector<void *>::iterator i=from.begin(); i!=from.end(); i++)
-               dest.push_back(*i);
+       VPVector copy;
+
+       for(VPVectorIter i=src.begin(); i!=src.end(); i++)
+       {
+               Object * obj = (Object *)(*i);
+
+               if (obj->selected)
+                       copy.push_back(CopyObject2(obj));
+       }
+
+       return copy;
 }
 
 
-void ClearSelected(std::vector<void *> & v)
+void AddObjectsTo(VPVector & dest, VPVector & from)
 {
-       std::vector<void *>::iterator i;
+       for(VPVectorIter i=from.begin(); i!=from.end(); i++)
+               dest.push_back(*i);
+}
 
-       for(i=v.begin(); i!=v.end(); i++)
+
+void ClearSelected(VPVector & v)
+{
+       for(VPVectorIter i=v.begin(); i!=v.end(); i++)
                ((Object *)(*i))->selected = false;
 }
 
 
-void SelectAll(std::vector<void *> & v)
+//
+// Select all *visible* objects.  If an object's layer is invisible, skip it.
+//
+void SelectAll(VPVector & v)
 {
-       std::vector<void *>::iterator i;
-
-       for(i=v.begin(); i!=v.end(); i++)
-               ((Object *)(*i))->selected = true;
+       for(VPVectorIter i=v.begin(); i!=v.end(); i++)
+       {
+               Object * obj = (Object *)(*i);
+               bool visible = !Global::layerHidden[obj->layer];
+               obj->selected = visible;
+       }
 }
 
 
@@ -160,11 +275,9 @@ void SelectAll(std::vector<void *> & v)
 // have to keep track of that stuff ourselves.  :-P  Believe it or not, this is
 // a Good Thing(TM).  ;-)
 //
-void DeleteContents(std::vector<void *> & v)
+void DeleteContents(VPVector & v)
 {
-       std::vector<void *>::iterator i;
-
-       for(i=v.begin(); i!=v.end(); i++)
+       for(VPVectorIter i=v.begin(); i!=v.end(); i++)
        {
                Object * obj = (Object *)(*i);
 
@@ -178,9 +291,9 @@ void DeleteContents(std::vector<void *> & v)
 }
 
 
-void DeleteSelectedObjects(std::vector<void *> & v)
+void DeleteSelectedObjects(VPVector & v)
 {
-       std::vector<void *>::iterator i = v.begin();
+       VPVectorIter i = v.begin();
 
        while (i != v.end())
        {
@@ -201,9 +314,9 @@ void DeleteSelectedObjects(std::vector<void *> & v)
 // This is used to remove selected objects from one container in order to move
 // them to a different container.
 //
-void RemoveSelectedObjects(std::vector<void *> & v)
+void RemoveSelectedObjects(VPVector & v)
 {
-       std::vector<void *>::iterator i = v.begin();
+       VPVectorIter i = v.begin();
 
        while (i != v.end())
        {
@@ -217,12 +330,12 @@ void RemoveSelectedObjects(std::vector<void *> & v)
 }
 
 
-void SavePointsFrom(std::vector<void *> & v, std::vector<Object> & save)
+void SavePointsFrom(VPVector & v, std::vector<Object> & save)
 {
        save.clear();
        Object o;
 
-       for(std::vector<void *>::iterator i=v.begin(); i!=v.end(); i++)
+       for(VPVectorIter i=v.begin(); i!=v.end(); i++)
        {
                memcpy(&o, (Object *)(*i), sizeof(Object));
                save.push_back(o);
@@ -230,12 +343,12 @@ void SavePointsFrom(std::vector<void *> & v, std::vector<Object> & save)
 }
 
 
-void RestorePointsTo(std::vector<void *> & v, std::vector<Object> & s)
+void RestorePointsTo(VPVector & v, std::vector<Object> & s)
 {
-       std::vector<Object>::iterator i = s.begin();
-       std::vector<void *>::iterator j = v.begin();
+       std::vector<Object>::iterator i;
+       VPVectorIter j;
 
-       for(; i!=s.end(); i++, j++)
+       for(i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
        {
                Object * obj2 = (Object *)(*j);
                obj2->p[0] = (*i).p[0];
@@ -248,12 +361,9 @@ void RestorePointsTo(std::vector<void *> & v, std::vector<Object> & s)
 }
 
 
-void RestorePointsTo(std::vector<void *> & v, std::vector<void *> & s)
+void RestorePointsTo(VPVector & v, VPVector & s)
 {
-       std::vector<void *>::iterator i = s.begin();
-       std::vector<void *>::iterator j = v.begin();
-
-       for(; i!=s.end(); i++, j++)
+       for(VPVectorIter i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
        {
                Object * objS = (Object *)(*i);
                Object * objV = (Object *)(*j);
@@ -274,21 +384,22 @@ void RestorePointsTo(std::vector<void *> & v, std::vector<void *> & s)
 }
 
 
+//
+// Translate a single object; it it's a Container, translate all its contents,
+// including subcontainers.
+//
 void TranslateObject(Object * obj, Point delta)
 {
        if (obj->type == OTContainer)
        {
                Container * c = (Container *)obj;
-               std::vector<void *>::iterator i;
 
-               for(i=c->objects.begin(); i!=c->objects.end(); i++)
+               for(VPVectorIter i=c->objects.begin(); i!=c->objects.end(); i++)
                        TranslateObject((Object *)*i, delta);
        }
-//     else
-//     {
-               obj->p[0] += delta;
-               obj->p[1] += delta;
-//     }
+
+       obj->p[0] += delta;
+       obj->p[1] += delta;
 }
 
 
@@ -298,14 +409,16 @@ So we need to make it so that we pick the container's point clicked on, and tran
 void TranslateContainer(Container * c, Point point, Point delta)
 {
        if (c->clicked == NULL)
-       {
+//     {
 //             TranslateObject((Object *)c, delta);
                return;
-       }
+//     }
 
-static int i=0;
-printf("TranslateContainer: boop (%i)\n", i++);
-       Point clickedPoint;
+//static int i=0;
+//printf("TranslateContainer: boop (%i)\n", i++);
+//we can set this to "point" and it won't move...
+//do it *this* way, and non-enumerated clicks will do the right thing
+       Point clickedPoint = point - delta;
 
        switch (c->clicked->type)
        {
@@ -315,6 +428,7 @@ printf("TranslateContainer: boop (%i)\n", i++);
                else if (c->clicked->hitPoint[1])
                        clickedPoint = c->clicked->p[1];
                else if (c->clicked->hitObject)
+//Weirdness: some lines get a midpoint, some don't...
                        clickedPoint = Geometry::Midpoint((Line *)(c->clicked));
 
                break;
@@ -322,12 +436,21 @@ printf("TranslateContainer: boop (%i)\n", i++);
        case OTCircle:
                if (c->clicked->hitPoint[0])
                        clickedPoint = c->clicked->p[0];
-               else if (c->clicked->hitObject)
-                       clickedPoint = point;
+//             else if (c->clicked->hitObject)
+//                     clickedPoint = point - delta;
 
                break;
 
        case OTArc:
+               if (c->clicked->hitPoint[0])
+                       clickedPoint = c->clicked->p[0];
+               else if (c->clicked->hitPoint[1])
+                       clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0]), sin(c->clicked->angle[0])) * c->clicked->radius[0]);
+               else if (c->clicked->hitPoint[2])
+                       clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0] + c->clicked->angle[1]), sin(c->clicked->angle[0] + c->clicked->angle[1])) * c->clicked->radius[0]);
+//             else if (c->clicked->hitObject)
+//                     clickedPoint = point - delta;
+
                break;
 
        case OTDimension:
@@ -342,41 +465,61 @@ printf("TranslateContainer: boop (%i)\n", i++);
 }
 
 
-void TranslateObjects(std::vector<void *> & v, Point delta)
+//
+// Translate all objects in the passed in vector, including Containers and all
+// the objects they contain.
+//
+void TranslateObjects(VPVector & v, Point delta)
 {
-#if 0
-       if (obj->type == OTContainer)
-       {
-               Container * c = (Container *)obj;
-               std::vector<void *>::iterator i;
-
-               for(i=c->objects.begin(); i!=c->objects.end(); i++)
-                       TranslateObject((Object *)*i, delta);
-       }
-       else
+       for(VPVectorIter i=v.begin(); i!=v.end(); i++)
        {
+               Object * obj = (Object *)(*i);
                obj->p[0] += delta;
                obj->p[1] += delta;
+
+               if (obj->type == OTContainer)
+               {
+                       Container * c = (Container *)obj;
+                       TranslateObjects(c->objects, delta);
+               }
        }
-#endif
-       // Handle containters too???
-       std::vector<void *>::iterator i;
+}
 
-       for(i=v.begin(); i!=v.end(); i++)
+
+//
+// This does not *copy* the objects, it simply flattens out the pointers in the
+// Container and all sub-Containers.
+//
+VPVector Flatten(Container * src)
+{
+       VPVector flat;
+
+       for(VPVectorIter i=src->objects.begin(); i!=src->objects.end(); i++)
        {
+               flat.push_back(*i);
                Object * obj = (Object *)(*i);
-               obj->p[0] += delta;
-               obj->p[1] += delta;
+
+               // Recursively add objects to the flat vector, if necessary
+               if (obj->type == OTContainer)
+               {
+                       VPVector sub = Flatten((Container *)obj);
+                       flat.insert(flat.end(), sub.begin(), sub.end());
+               }
        }
+
+       return flat;
 }
 
 
-std::vector<void *> Flatten(Container * src)
+//
+// This does not *copy* the objects, it simply flattens out the pointers in the
+// vector and all sub-Containers in the vector.
+//
+VPVector Flatten(VPVector src)
 {
-       std::vector<void *> flat;
-       std::vector<void *>::iterator i;
+       VPVector flat;
 
-       for(i=src->objects.begin(); i!=src->objects.end(); i++)
+       for(VPVectorIter i=src.begin(); i!=src.end(); i++)
        {
                flat.push_back(*i);
                Object * obj = (Object *)(*i);
@@ -384,7 +527,7 @@ std::vector<void *> Flatten(Container * src)
                // Recursively add objects to the flat vector, if necessary
                if (obj->type == OTContainer)
                {
-                       std::vector<void *> sub = Flatten((Container *)obj);
+                       VPVector sub = Flatten(((Container *)obj)->objects);
                        flat.insert(flat.end(), sub.begin(), sub.end());
                }
        }
index a72ca394750078324440e9a7c54598600bce50c1..6fd59d0adaf3eca3bf93f99b47251b7f347f1bde 100644 (file)
@@ -4,22 +4,27 @@
 #include <vector>
 #include "structs.h"
 
-void CopyObjects(std::vector<void *> & from, std::vector<void *> & to);
+void CopyObjects(VPVector & from, VPVector & to);
+VPVector CopyObjects(VPVector & from);
 Object * CopyObject(Object * obj);
-void MoveSelectedObjectsTo(std::vector<void *> & dest, std::vector<void *> & from);
-void CopySelectedObjectsTo(std::vector<void *> & dest, std::vector<void *> & from);
-void AddObjectsTo(std::vector<void *> & dest, std::vector<void *> & from);
-void ClearSelected(std::vector<void *> & v);
-void SelectAll(std::vector<void *> & v);
-void DeleteContents(std::vector<void *> & v);
-void DeleteSelectedObjects(std::vector<void *> & v);
-void RemoveSelectedObjects(std::vector<void *> & v);
-void SavePointsFrom(std::vector<void *> & v, std::vector<Object> & s);
-void RestorePointsTo(std::vector<void *> & v, std::vector<Object> & s);
-void RestorePointsTo(std::vector<void *> & v, std::vector<void *> & s);
+Object * CopyObject2(Object * obj);
+void MoveSelectedObjectsTo(VPVector & dest, VPVector & from);
+VPVector MoveSelectedObjectsFrom(VPVector & from);
+void CopySelectedObjectsTo(VPVector & dest, VPVector & from);
+VPVector CopySelectedObjects(VPVector & from);
+void AddObjectsTo(VPVector & dest, VPVector & from);
+void ClearSelected(VPVector & v);
+void SelectAll(VPVector & v);
+void DeleteContents(VPVector & v);
+void DeleteSelectedObjects(VPVector & v);
+void RemoveSelectedObjects(VPVector & v);
+void SavePointsFrom(VPVector & v, std::vector<Object> & s);
+void RestorePointsTo(VPVector & v, std::vector<Object> & s);
+void RestorePointsTo(VPVector & v, VPVector & s);
 void TranslateObject(Object * obj, Point delta);
 void TranslateContainer(Container * c, Point point, Point delta);
-void TranslateObjects(std::vector<void *> & v, Point delta);
-std::vector<void *> Flatten(Container * src);
+void TranslateObjects(VPVector & v, Point delta);
+VPVector Flatten(Container * src);
+VPVector Flatten(VPVector src);
 
 #endif // __UTILS_H__
index 20b8ef5f99e5bde36b6020120042d4691a1f222b..57f49fbb8b1d4bc7ae1566c91cdb58586691895f 100644 (file)
@@ -205,7 +205,7 @@ Vector Vector::Unit(void)
 
 double Vector::Magnitude(void)
 {
-       return sqrt(x * x + y * y + z * z);
+       return sqrt((x * x) + (y * y) + (z * z));
 }