]> Shamusworld >> Repos - architektonas/blobdiff - src/drawingview.cpp
Added angle snap to whole degrees, ability to manipulate Dimensions.
[architektonas] / src / drawingview.cpp
index 1fd0482a83d266c0e313081f878ded884655b649..943a9b9f4cd9edb088df0a5d8a75a9824512d4cd 100644 (file)
@@ -48,14 +48,14 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        ctrlDown(false),
        gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
        scale(1.0), offsetX(-10), offsetY(-10), document(true),
-       gridPixels(0), collided(false), hoveringIntersection(false)
+       gridPixels(0), collided(false), hoveringIntersection(false),
+       dragged(NULL), draggingObject(false), angleSnap(false)
 {
 //wtf? doesn't work except in c++11??? document = { 0 };
        setBackgroundRole(QPalette::Base);
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
        Global::gridSpacing = 12.0;             // In base units (inch is default)
-
 #if 0
        Line * line = new Line(Vector(5, 5), Vector(50, 40), &document);
        document.Add(line);
@@ -444,7 +444,7 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int
                        Vector v(d->p[0], d->p[1]);
                        double angle = v.Angle();
                        Vector unit = v.Unit();
-                       Vector linePt1 = d->p[0], linePt2 = d->p[1];
+                       d->lp[0] = d->p[0], d->lp[1] = d->p[1];
                        Vector ortho;
                        double x1, y1, length;
 
@@ -465,7 +465,7 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int
                                        angle = QTR_TAU;
                                }
 
-                               linePt1.x = linePt2.x = x1;
+                               d->lp[0].x = d->lp[1].x = x1;
                                length = fabs(d->p[0].y - d->p[1].y);
                        }
                        else if (d->subtype == DTLinearHorz)
@@ -485,22 +485,22 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int
                                        angle = HALF_TAU;
                                }
 
-                               linePt1.y = linePt2.y = y1;
+                               d->lp[0].y = d->lp[1].y = y1;
                                length = fabs(d->p[0].x - d->p[1].x);
                        }
                        else if (d->subtype == DTLinear)
                        {
-                               angle = Vector(linePt1, linePt2).Angle();
-                               ortho = Vector::Normal(linePt1, linePt2);
+                               angle = Vector(d->lp[0], d->lp[1]).Angle();
+                               ortho = Vector::Normal(d->lp[0], d->lp[1]);
                                length = v.Magnitude();
                        }
 
-                       unit = Vector(linePt1, linePt2).Unit();
+                       unit = Vector(d->lp[0], d->lp[1]).Unit();
 
-                       Point p1 = linePt1 + (ortho * 10.0 * scaledThickness);
-                       Point p2 = linePt2 + (ortho * 10.0 * scaledThickness);
-                       Point p3 = linePt1 + (ortho * 16.0 * scaledThickness);
-                       Point p4 = linePt2 + (ortho * 16.0 * scaledThickness);
+                       Point p1 = d->lp[0] + (ortho * 10.0 * scaledThickness);
+                       Point p2 = d->lp[1] + (ortho * 10.0 * scaledThickness);
+                       Point p3 = d->lp[0] + (ortho * 16.0 * scaledThickness);
+                       Point p4 = d->lp[1] + (ortho * 16.0 * scaledThickness);
                        Point p5 = d->p[0] + (ortho * 4.0 * scaledThickness);
                        Point p6 = d->p[1] + (ortho * 4.0 * scaledThickness);
 
@@ -514,7 +514,7 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int
 
                        // Calculate whether or not the arrowheads are too crowded to put
                        // inside the extension lines. 9.0 is the length of the arrowhead.
-                       double t = Geometry::ParameterOfLineAndPoint(linePt1, linePt2, linePt2 - (unit * 9.0 * scaledThickness));
+                       double t = Geometry::ParameterOfLineAndPoint(d->lp[0], d->lp[1], d->lp[1] - (unit * 9.0 * scaledThickness));
 
                        // On the screen, it's acting like this is actually 58%...
                        // This is correct, we want it to happen at > 50%
@@ -557,6 +557,51 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int
 
                        painter->DrawAngledText(ctr, angle, dimText, scaledThickness);
 
+                       if (d->hitObject)
+                       {
+                               Point hp1 = (p1 + p2) / 2.0;
+                               Point hp2 = (p1 + hp1) / 2.0;
+                               Point hp3 = (hp1 + p2) / 2.0;
+
+                               if (d->hitPoint[2])
+                               {
+                                       painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+                                       painter->SetBrush(QBrush(QColor(Qt::magenta)));
+                                       painter->DrawArrowHandle(hp1, ortho.Angle() + HALF_TAU);
+                                       painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+                               }
+
+                               painter->DrawHandle(hp1);
+                               painter->SetPen(QPen(Qt::blue, 1.0 * Global::zoom * scaledThickness, Qt::SolidLine));
+
+                               if (d->hitPoint[3])
+                               {
+                                       painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+                                       painter->SetBrush(QBrush(QColor(Qt::magenta)));
+                                       painter->DrawArrowToLineHandle(hp2, (d->subtype == DTLinearVert ? v.Angle() - QTR_TAU : (v.Angle() < HALF_TAU ? HALF_TAU : 0)));
+                                       painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+                               }
+
+                               painter->DrawHandle(hp2);
+                               painter->SetPen(QPen(Qt::blue, 1.0 * Global::zoom * scaledThickness, Qt::SolidLine));
+
+                               if (d->hitPoint[4])
+                               {
+                                       painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+                                       painter->SetBrush(QBrush(QColor(Qt::magenta)));
+                                       painter->DrawArrowToLineHandle(hp3, (d->subtype == DTLinearHorz ? v.Angle() - QTR_TAU : (v.Angle() > HALF_TAU && v.Angle() < THREE_QTR_TAU ? THREE_QTR_TAU : QTR_TAU)));
+                                       painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+                               }
+
+                               painter->DrawHandle(hp3);
+                       }
+
+                       if (obj->hitPoint[0])
+                               painter->DrawHandle(obj->p[0]);
+
+                       if (obj->hitPoint[1])
+                               painter->DrawHandle(obj->p[1]);
+
                        break;
                }
                case OTText:
@@ -646,6 +691,9 @@ void DrawingView::resizeEvent(QResizeEvent * /*event*/)
 
 void DrawingView::ToolHandler(int mode, Point p)
 {
+       // Drop angle snap until it's needed
+       angleSnap = false;
+
        if (Global::tool == TTLine)
                LineHandler(mode, p);
        else if (Global::tool == TTCircle)
@@ -904,9 +952,15 @@ void DrawingView::ArcHandler(int mode, Point p)
                else if (Global::toolState == TSPoint2)
                        toolPoint[1] = p;
                else if (Global::toolState == TSPoint3)
+               {
                        toolPoint[2] = p;
+                       angleSnap = true;
+               }
                else
+               {
                        toolPoint[3] = p;
+                       angleSnap = true;
+               }
 
                break;
        case ToolMouseUp:
@@ -920,7 +974,7 @@ void DrawingView::ArcHandler(int mode, Point p)
                {
                        if (shiftDown)
                        {
-                               // Key override is telling us to start circle at new center, not
+                               // Key override is telling us to start arc at new center, not
                                // continue the current one.
                                toolPoint[0] = toolPoint[1];
                                return;
@@ -980,6 +1034,7 @@ void DrawingView::RotateHandler(int mode, Point p)
                        if (shiftDown)
                                return;
 
+                       angleSnap = true;
                        double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
                        std::vector<void *>::iterator j = select.begin();
                        std::vector<Object>::iterator i = toolScratch.begin();
@@ -1082,6 +1137,7 @@ void DrawingView::MirrorHandler(int mode, Point p)
                        if (shiftDown)
                                return;
 
+                       angleSnap = true;
                        double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
                        std::vector<void *>::iterator j = select.begin();
                        std::vector<Object>::iterator i = toolScratch.begin();
@@ -1172,12 +1228,12 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
                        else if (Global::snapToGrid)
                                point = SnapPointToGrid(point);
 
-                       //Also, may want to figure out if hovering over a snap point on an object,
-                       //snap to grid if not.
+                       //Also, may want to figure out if hovering over a snap point on an
+                       //object, snap to grid if not.
                        // Snap to object point if valid...
 //                     if (Global::snapPointIsValid)
 //                             point = Global::snapPoint;
-                       
+
                        ToolHandler(ToolMouseDown, point);
                        return;
                }
@@ -1194,6 +1250,16 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
                        AddHoveredToSelection();
                        update();       // needed??
                        GetHovered(hover);      // prolly needed
+                       dragged = (Object *)hover[0];
+                       draggingObject = true;
+
+                       // See if anything is using just a straight click on a handle
+                       if (HandleObjectClicked())
+                       {
+                               draggingObject = false;
+                               update();
+                               return;
+                       }
 
                        // Needed for grab & moving objects
                        // We do it *after*... why? (doesn't seem to confer any advantage...)
@@ -1255,36 +1321,25 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
                return;
        }
 
-       // Handle object movement (left button down & over an object)
-       if ((event->buttons() & Qt::LeftButton) && numHovered && !Global::tool)
-       {
-               if (hoveringIntersection)
-                       point = intersectionPoint;
-               else if (Global::snapToGrid)
-                       point = SnapPointToGrid(point);
-
-               HandleObjectMovement(point);
-               update();
-               oldPoint = point;
-               return;
-       }
-
        // Do object hit testing...
        bool needUpdate = HitTestObjects(point);
+       GetHovered(hover);
 
        // Check for multi-hover...
        if (numHovered > 1)
        {
-               GetHovered(hover);
-               Geometry::Intersects((Object *)hover[0], (Object *)hover[1]);
+//need to check for case where hover is over 2 circles and a 3rd's center...
+               Object * obj1 = (Object *)hover[0], * obj2 = (Object *)hover[1];
+
+               Geometry::Intersects(obj1, obj2);
                int numIntersecting = Global::numIntersectParams;
                double t = Global::intersectParam[0];
                double u = Global::intersectParam[1];
 
                if (numIntersecting > 0)
                {
-                       Vector v1 = Geometry::GetPointForParameter((Object *)hover[0], t);
-                       Vector v2 = Geometry::GetPointForParameter((Object *)hover[1], u);
+                       Vector v1 = Geometry::GetPointForParameter(obj1, t);
+                       Vector v2 = Geometry::GetPointForParameter(obj2, u);
                        QString text = tr("Intersection t=%1 (%3, %4), u=%2 (%5, %6)");
                        informativeText = text.arg(t).arg(u).arg(v1.x).arg(v1.y).arg(v2.x).arg(v2.y);
 
@@ -1313,14 +1368,13 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
                }
        }
 
-//this doesn't work down here for some reason... :-P
-//could be because the object being moved is part of the intersection, and this is screwing things up. In which case, we need to exclude the moving object somehow from the hit test function...
-#if 0
        // Handle object movement (left button down & over an object)
-       if ((event->buttons() & Qt::LeftButton) && numHovered && !Global::tool)
+       if ((event->buttons() & Qt::LeftButton) && draggingObject && !Global::tool)
        {
                if (hoveringIntersection)
                        point = intersectionPoint;
+               else if (hoverPointValid)
+                       point = hoverPoint;
                else if (Global::snapToGrid)
                        point = SnapPointToGrid(point);
 
@@ -1329,15 +1383,21 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
                oldPoint = point;
                return;
        }
-#endif
 
        // Do tool handling, if any are active...
        if (Global::tool)
        {
                if (hoveringIntersection)
                        point = intersectionPoint;
+               else if (hoverPointValid)
+                       point = hoverPoint;
                else if (Global::snapToGrid)
-                       point = SnapPointToGrid(point);
+               {
+                       if (angleSnap)
+                               point = SnapPointToAngle(point);
+                       else
+                               point = SnapPointToGrid(point);
+               }
 
                ToolHandler(ToolMouseMove, point);
        }
@@ -1385,11 +1445,9 @@ void DrawingView::mouseReleaseEvent(QMouseEvent * event)
                {
                        if (((Object *)(*i))->selected)
                                select.push_back(*i);
-
-//hmm, this is no good, too late to do any good :-P
-//                     if ((*i)->hovered)
-//                             hover.push_back(*i);
                }
+
+               draggingObject = false;
        }
        else if (event->button() == Qt::MiddleButton)
        {
@@ -1445,6 +1503,30 @@ void DrawingView::keyPressEvent(QKeyEvent * event)
 
                update();
        }
+
+       if (select.size() > 0)
+       {
+               if (event->key() == Qt::Key_Up)
+               {
+                       TranslateObjects(select, Point(0, +1.0));
+                       update();
+               }
+               else if (event->key() == Qt::Key_Down)
+               {
+                       TranslateObjects(select, Point(0, -1.0));
+                       update();
+               }
+               else if (event->key() == Qt::Key_Right)
+               {
+                       TranslateObjects(select, Point(+1.0, 0));
+                       update();
+               }
+               else if (event->key() == Qt::Key_Left)
+               {
+                       TranslateObjects(select, Point(-1.0, 0));
+                       update();
+               }
+       }
 }
 
 
@@ -1488,6 +1570,24 @@ Point DrawingView::SnapPointToGrid(Point point)
 }
 
 
+Point DrawingView::SnapPointToAngle(Point point)
+{
+       // Snap to a single digit angle (using toolpoint #1 as the center)
+       double angle = Vector::Angle(toolPoint[0], point);
+       double length = Vector::Magnitude(toolPoint[0], point);
+
+       // Convert from radians to degrees
+       double degAngle = angle * RADIANS_TO_DEGREES;
+       double snapAngle = (double)((int)(degAngle + 0.5));
+
+       Vector v;
+       v.SetAngleAndLength(snapAngle * DEGREES_TO_RADIANS, length);
+       point = toolPoint[0] + v;
+
+       return point;
+}
+
+
 Rect DrawingView::GetObjectExtents(Object * obj)
 {
        // Default to empty rect, if object checks below fail for some reason
@@ -1669,119 +1769,18 @@ bool DrawingView::HitTestObjects(Point point)
        std::vector<void *>::iterator i;
        numHovered = 0;
        bool needUpdate = false;
+       hoverPointValid = false;
 
        for(i=document.objects.begin(); i!=document.objects.end(); i++)
        {
                Object * obj = (Object *)(*i);
 
+               // If we're seeing the object we're dragging, skip it
+               if (draggingObject && (obj == dragged))
+                       continue;
+
                if (HitTest(obj, point))
                        needUpdate = true;
-#if 0
-               switch (obj->type)
-               {
-               case OTLine:
-               {
-                       bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHO = obj->hitObject;
-                       obj->hitPoint[0] = obj->hitPoint[1] = obj->hitObject = false;
-                       Vector lineSegment = obj->p[1] - obj->p[0];
-                       Vector v1 = point - obj->p[0];
-                       Vector v2 = point - obj->p[1];
-                       double t = Geometry::ParameterOfLineAndPoint(obj->p[0], obj->p[1], point);
-                       double distance;
-
-                       if (t < 0.0)
-                               distance = v1.Magnitude();
-                       else if (t > 1.0)
-                               distance = v2.Magnitude();
-                       else
-                               // distance = ?Det?(ls, v1) / |ls|
-                               distance = fabs((lineSegment.x * v1.y - v1.x * lineSegment.y)
-                                       / lineSegment.Magnitude());
-
-                       if ((v1.Magnitude() * Global::zoom) < 8.0)
-                               obj->hitPoint[0] = true;
-                       else if ((v2.Magnitude() * Global::zoom) < 8.0)
-                               obj->hitPoint[1] = true;
-                       else if ((distance * Global::zoom) < 5.0)
-                               obj->hitObject = true;
-
-                       obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitObject ? true : false);
-
-                       if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHO != obj->hitObject))
-                               needUpdate = true;
-
-                       break;
-               }
-               case OTCircle:
-               {
-                       bool oldHP = obj->hitPoint[0], oldHO = obj->hitObject;
-                       obj->hitPoint[0] = obj->hitObject = false;
-                       double length = Vector::Magnitude(obj->p[0], point);
-
-                       if ((length * Global::zoom) < 8.0)
-                               obj->hitPoint[0] = true;
-                       else if ((fabs(length - obj->radius[0]) * Global::zoom) < 2.0)
-                               obj->hitObject = true;
-
-                       obj->hovered = (obj->hitPoint[0] || obj->hitObject ? true : false);
-
-                       if ((oldHP != obj->hitPoint[0]) || (oldHO != obj->hitObject))
-                               needUpdate = true;
-
-                       break;
-               }
-               case OTArc:
-               {
-                       bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHP2 = obj->hitPoint[2], oldHO = obj->hitObject;
-                       obj->hitPoint[0] = obj->hitPoint[1] = obj->hitPoint[2] = obj->hitObject = false;
-                       double length = Vector::Magnitude(obj->p[0], point);
-                       double angle = Vector::Angle(obj->p[0], point);
-
-                       // Make sure we get the angle in the correct spot
-                       if (angle < obj->angle[0])
-                               angle += TAU;
-
-                       // Get the span that we're pointing at...
-                       double span = angle - obj->angle[0];
-
-                       // N.B.: Still need to hit test the arc start & arc span handles...
-                       double spanAngle = obj->angle[0] + obj->angle[1];
-                       Point handle1 = obj->p[0] + (Vector(cos(obj->angle[0]), sin(obj->angle[0])) * obj->radius[0]);
-                       Point handle2 = obj->p[0] + (Vector(cos(spanAngle), sin(spanAngle)) * obj->radius[0]);
-                       double length2 = Vector::Magnitude(point, handle1);
-                       double length3 = Vector::Magnitude(point, handle2);
-
-                       if ((length * Global::zoom) < 8.0)
-                               obj->hitPoint[0] = true;
-                       else if ((length2 * Global::zoom) < 8.0)
-                               obj->hitPoint[1] = true;
-                       else if ((length3 * Global::zoom) < 8.0)
-                               obj->hitPoint[2] = true;
-                       else if (((fabs(length - obj->radius[0]) * Global::zoom) < 2.0) && (span < obj->angle[1]))
-                               obj->hitObject = true;
-
-                       obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitObject ? true : false);
-
-                       if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHO != obj->hitObject))
-                               needUpdate = true;
-
-                       break;
-               }
-               case OTContainer:
-               {
-                       // Containers must be recursively tested...
-                       Container * c = (Container *)obj;
-                       std::vector<void *>::iterator i;
-
-                       for(i=c->objects.begin(); i!=c->objects.end(); i++)
-                       {
-                               
-                       }
-               }
-               default:
-                       break;
-               }
-#endif
 
                if (obj->hovered)
                {
@@ -1821,9 +1820,17 @@ bool DrawingView::HitTest(Object * obj, Point point)
                                / lineSegment.Magnitude());
 
                if ((v1.Magnitude() * Global::zoom) < 8.0)
+               {
                        obj->hitPoint[0] = true;
+                       hoverPoint = obj->p[0];
+                       hoverPointValid = true;
+               }
                else if ((v2.Magnitude() * Global::zoom) < 8.0)
+               {
                        obj->hitPoint[1] = true;
+                       hoverPoint = obj->p[1];
+                       hoverPointValid = true;
+               }
                else if ((distance * Global::zoom) < 5.0)
                        obj->hitObject = true;
 
@@ -1876,9 +1883,17 @@ bool DrawingView::HitTest(Object * obj, Point point)
                if ((length * Global::zoom) < 8.0)
                        obj->hitPoint[0] = true;
                else if ((length2 * Global::zoom) < 8.0)
+               {
                        obj->hitPoint[1] = true;
+                       hoverPoint = handle1;
+                       hoverPointValid = true;
+               }
                else if ((length3 * Global::zoom) < 8.0)
+               {
                        obj->hitPoint[2] = true;
+                       hoverPoint = handle2;
+                       hoverPointValid = true;
+               }
                else if (((fabs(length - obj->radius[0]) * Global::zoom) < 2.0) && (span < obj->angle[1]))
                        obj->hitObject = true;
 
@@ -1889,6 +1904,62 @@ bool DrawingView::HitTest(Object * obj, Point point)
 
                break;
        }
+       case OTDimension:
+       {
+               bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHP2 = obj->hitPoint[2], oldHP3 = obj->hitPoint[3], oldHP4 = obj->hitPoint[4], oldHO = obj->hitObject;
+               obj->hitPoint[0] = obj->hitPoint[1] = obj->hitPoint[2] = obj->hitPoint[3] = obj->hitPoint[4] = obj->hitObject = false;
+
+               Dimension * d = (Dimension *)obj;
+
+               Vector orthogonal = Vector::Normal(d->lp[0], d->lp[1]);
+               // Get our line parallel to our points
+               float scaledThickness = Global::scale * obj->thickness;
+               Point p1 = d->lp[0] + (orthogonal * 10.0 * scaledThickness);
+               Point p2 = d->lp[1] + (orthogonal * 10.0 * scaledThickness);
+               Point p3(p1, point);
+
+               Vector v1(d->p[0], point);
+               Vector v2(d->p[1], point);
+               Vector lineSegment(p1, p2);
+               double t = Geometry::ParameterOfLineAndPoint(p1, p2, point);
+               double distance;
+               Point midpoint = (p1 + p2) / 2.0;
+               Point hFSPoint = Point(midpoint, point);
+               Point hCS1Point = Point((p1 + midpoint) / 2.0, point);
+               Point hCS2Point = Point((midpoint + p2) / 2.0, point);
+
+               if (t < 0.0)
+                       distance = v1.Magnitude();
+               else if (t > 1.0)
+                       distance = v2.Magnitude();
+               else
+                       // distance = ?Det?(ls, v1) / |ls|
+                       distance = fabs((lineSegment.x * p3.y - p3.x * lineSegment.y)
+                               / lineSegment.Magnitude());
+
+               if ((v1.Magnitude() * Global::zoom) < 8.0)
+                       obj->hitPoint[0] = true;
+               else if ((v2.Magnitude() * Global::zoom) < 8.0)
+                       obj->hitPoint[1] = true;
+               else if ((distance * Global::zoom) < 5.0)
+                       obj->hitObject = true;
+
+               if ((hFSPoint.Magnitude() * Global::zoom) < 8.0)
+                       obj->hitPoint[2] = true;
+               else if ((hCS1Point.Magnitude() * Global::zoom) < 8.0)
+                       obj->hitPoint[3] = true;
+               else if ((hCS2Point.Magnitude() * Global::zoom) < 8.0)
+                       obj->hitPoint[4] = true;
+
+//             return (hitPoint1 || hitPoint2 || hitLine || hitFlipSwitch || hitChangeSwitch1 || hitChangeSwitch2 ? true : false);
+               obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitPoint[3] || obj->hitPoint[4] || obj->hitObject ? true : false);
+
+               if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHP3 != obj->hitPoint[3]) || (oldHP4 != obj->hitPoint[4]) || (oldHO != obj->hitObject))
+                       needUpdate = true;
+
+
+               break;
+       }
        case OTContainer:
        {
                // Containers must be recursively tested...
@@ -1921,11 +1992,56 @@ bool DrawingView::HitTest(Object * obj, Point point)
 }
 
 
+bool DrawingView::HandleObjectClicked(void)
+{
+       if (dragged->type == OTDimension)
+       {
+               Dimension * d = (Dimension *)dragged;
+
+               if (d->hitPoint[2])
+               {
+                       // Hit the "flip sides" switch, so flip 'em
+                       Point temp = d->p[0];
+                       d->p[0] = d->p[1];
+                       d->p[1] = temp;
+                       return true;
+               }
+               else if (d->hitPoint[3])
+               {
+                       // There are three cases here: aligned, horizontal, & vertical.
+                       // Aligned and horizontal do the same thing, vertical goes back to
+                       // linear.
+                       if (d->subtype == DTLinearVert)
+                               d->subtype = DTLinear;
+                       else
+                               d->subtype = DTLinearVert;
+
+                       return true;
+               }
+               else if (d->hitPoint[4])
+               {
+                       // There are three cases here: aligned, horizontal, & vertical.
+                       // Aligned and vertical do the same thing, horizontal goes back to
+                       // linear.
+                       if (d->subtype == DTLinearHorz)
+                               d->subtype = DTLinear;
+                       else
+                               d->subtype = DTLinearHorz;
+
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
 void DrawingView::HandleObjectMovement(Point point)
 {
        Point delta = point - oldPoint;
 //printf("HOM: old = (%f,%f), new = (%f, %f), delta = (%f, %f)\n", oldPoint.x, oldPoint.y, point.x, point.y, delta.x, delta.y);
-       Object * obj = (Object *)hover[0];
+//     Object * obj = (Object *)hover[0];
+       Object * obj = dragged;
 //printf("Object type = %i (size=%i), ", obj->type, hover.size());
 //printf("Object (%X) move: hp1=%s, hp2=%s, hl=%s\n", obj, (obj->hitPoint[0] ? "true" : "false"), (obj->hitPoint[1] ? "true" : "false"), (obj->hitObject ? "true" : "false"));
 
@@ -1943,6 +2059,7 @@ void DrawingView::HandleObjectMovement(Point point)
                }
 
                break;
+
        case OTCircle:
                if (obj->hitPoint[0])
                        obj->p[0] = point;
@@ -1957,6 +2074,7 @@ void DrawingView::HandleObjectMovement(Point point)
                }
 
                break;
+
        case OTArc:
                if (obj->hitPoint[0])
                        obj->p[0] = point;
@@ -2025,6 +2143,20 @@ void DrawingView::HandleObjectMovement(Point point)
                }
 
                break;
+
+       case OTDimension:
+               if (obj->hitPoint[0])
+                       obj->p[0] = point;
+               else if (obj->hitPoint[1])
+                       obj->p[1] = point;
+               else if (obj->hitObject)
+               {
+                       obj->p[0] += delta;
+                       obj->p[1] += delta;
+               }
+
+               break;
+
        case OTContainer:
                // This is shitty, but works for now until I can code up something
                // nicer :-)