]> Shamusworld >> Repos - architektonas/blobdiff - src/drawingview.cpp
Initial work on making Rotate tool work, plus removal of unneeded files.
[architektonas] / src / drawingview.cpp
index 21c85dd48236cacb7d1cac4904ab5403af51ff77..f3cac0db04a00f44aa71934bfac4e6b21f122165 100644 (file)
@@ -35,6 +35,7 @@
 #include "mathconstants.h"
 #include "painter.h"
 #include "structs.h"
+#include "utils.h"
 
 
 #define BACKGROUND_MAX_SIZE    512
@@ -48,7 +49,7 @@ enum { ToolMouseDown, ToolMouseMove, ToolMouseUp };
 DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        // The value in the settings file will override this.
        useAntialiasing(true), numSelected(0), numHovered(0), shiftDown(false),
-       ctrlDown(false),
+       ctrlDown(false), overrideColor(false),
        gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
        scale(1.0), offsetX(-10), offsetY(-10),// document(Vector(0, 0)),
        gridPixels(0), collided(false)//, toolAction(NULL)
@@ -79,8 +80,8 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
 #endif
 #else
        Line * line = new Line;//(Vector(5, 5), Vector(50, 40), &document);
-       line->p1 = Vector(5, 5);
-       line->p2 = Vector(50, 40);
+       line->p[0] = Vector(5, 5);
+       line->p[1] = Vector(50, 40);
        line->type = OTLine;
        line->thickness = 2.0;
        line->style = LSDash;
@@ -324,64 +325,60 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
        painter.DrawLine(0, -16384, 0, 16384);
        painter.DrawLine(-16384, 0, 16384, 0);
 
-       // The top level document takes care of rendering for us...
-//     document.Draw(&painter);
-       // Not any more it doesn't...
-       RenderObjects(&painter, &document);
+       // Do object rendering...
+       RenderObjects(&painter, document.objects);
 
-#if 0
-       if (toolAction)
-       {
-               painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine));
-               painter.DrawCrosshair(oldPoint);
-               toolAction->Draw(&painter);
-       }
-#else
+       // Do tool rendering, if any...
        if (Global::tool)
        {
                painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine));
                painter.DrawCrosshair(oldPoint);
                ToolDraw(&painter);
        }
-#endif
 
-#if 1
+       // Do selection rectangle rendering, if any
        if (Global::selectionInProgress)
        {
                painter.SetPen(QPen(QColor(255, 127, 0, 255)));
                painter.SetBrush(QBrush(QColor(255, 127, 0, 100)));
                painter.DrawRect(Global::selection);
        }
-#endif
 }
 
 
-void DrawingView::RenderObjects(Painter * painter, Container * c)
+//
+// Renders objects in the passed in vector
+//
+void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v)
 {
        std::vector<void *>::iterator i;
 
-       for(i=c->objects.begin(); i!=c->objects.end(); i++)
+       for(i=v.begin(); i!=v.end(); i++)
        {
                Object * obj = (Object *)(*i);
                float scaledThickness = Global::scale * obj->thickness;
-               painter->SetPen(obj->color, Global::zoom * scaledThickness, obj->style);
-               painter->SetBrush(obj->color);
 
-               if (obj->selected || obj->hitObject)
-                       painter->SetPen(0xFF0000, Global::zoom * scaledThickness, LSDash);
+               if (!overrideColor)
+               {
+                       painter->SetPen(obj->color, Global::zoom * scaledThickness, obj->style);
+                       painter->SetBrush(obj->color);
+
+                       if (obj->selected || obj->hitObject)
+                               painter->SetPen(0xFF0000, Global::zoom * scaledThickness, LSDash);
+               }
 
                switch (obj->type)
                {
                case OTLine:
                {
                        Line * l = (Line *)obj;
-                       painter->DrawLine(l->p1, l->p2);
+                       painter->DrawLine(l->p[0], l->p[1]);
 
                        if (l->hitPoint[0])
-                               painter->DrawHandle(l->p1);
+                               painter->DrawHandle(l->p[0]);
 
                        if (l->hitPoint[1])
-                               painter->DrawHandle(l->p2);
+                               painter->DrawHandle(l->p[1]);
 
                        break;
                }
@@ -389,23 +386,23 @@ void DrawingView::RenderObjects(Painter * painter, Container * c)
                {
                        Circle * ci = (Circle *)obj;
                        painter->SetBrush(QBrush(Qt::NoBrush));
-                       painter->DrawEllipse(ci->p1, ci->radius, ci->radius);
+                       painter->DrawEllipse(ci->p[0], ci->radius, ci->radius);
                        break;
                }
                case OTArc:
                {
                        Arc * a = (Arc *)obj;
-                       painter->DrawArc(a->p1, a->radius, a->angle1, a->angle2);
+                       painter->DrawArc(a->p[0], a->radius, a->angle1, a->angle2);
                        break;
                }
                case OTDimension:
                {
                        Dimension * d = (Dimension *)obj;
 
-                       Vector v(d->p1, d->p2);
+                       Vector v(d->p[0], d->p[1]);
                        double angle = v.Angle();
                        Vector unit = v.Unit();
-                       Vector linePt1 = d->p1, linePt2 = d->p2;
+                       Vector linePt1 = d->p[0], linePt2 = d->p[1];
                        Vector ortho;
                        double x1, y1, length;
 
@@ -413,41 +410,41 @@ void DrawingView::RenderObjects(Painter * painter, Container * c)
                        {
                                if ((angle < 0) || (angle > PI))
                                {
-                                       x1 = (d->p1.x > d->p2.x ? d->p1.x : d->p2.x);
-                                       y1 = (d->p1.y > d->p2.y ? d->p1.y : d->p2.y);
+                                       x1 = (d->p[0].x > d->p[1].x ? d->p[0].x : d->p[1].x);
+                                       y1 = (d->p[0].y > d->p[1].y ? d->p[0].y : d->p[1].y);
                                        ortho = Vector(1.0, 0);
                                        angle = PI3_OVER_2;
                                }
                                else
                                {
-                                       x1 = (d->p1.x > d->p2.x ? d->p2.x : d->p1.x);
-                                       y1 = (d->p1.y > d->p2.y ? d->p2.y : d->p1.y);
+                                       x1 = (d->p[0].x > d->p[1].x ? d->p[1].x : d->p[0].x);
+                                       y1 = (d->p[0].y > d->p[1].y ? d->p[1].y : d->p[0].y);
                                        ortho = Vector(-1.0, 0);
                                        angle = PI_OVER_2;
                                }
 
                                linePt1.x = linePt2.x = x1;
-                               length = fabs(d->p1.y - d->p2.y);
+                               length = fabs(d->p[0].y - d->p[1].y);
                        }
                        else if (d->subtype == DTLinearHorz)
                        {
                                if ((angle < PI_OVER_2) || (angle > PI3_OVER_2))
                                {
-                                       x1 = (d->p1.x > d->p2.x ? d->p1.x : d->p2.x);
-                                       y1 = (d->p1.y > d->p2.y ? d->p1.y : d->p2.y);
+                                       x1 = (d->p[0].x > d->p[1].x ? d->p[0].x : d->p[1].x);
+                                       y1 = (d->p[0].y > d->p[1].y ? d->p[0].y : d->p[1].y);
                                        ortho = Vector(0, 1.0);
                                        angle = 0;
                                }
                                else
                                {
-                                       x1 = (d->p1.x > d->p2.x ? d->p2.x : d->p1.x);
-                                       y1 = (d->p1.y > d->p2.y ? d->p2.y : d->p1.y);
+                                       x1 = (d->p[0].x > d->p[1].x ? d->p[1].x : d->p[0].x);
+                                       y1 = (d->p[0].y > d->p[1].y ? d->p[1].y : d->p[0].y);
                                        ortho = Vector(0, -1.0);
                                        angle = PI;
                                }
 
                                linePt1.y = linePt2.y = y1;
-                               length = fabs(d->p1.x - d->p2.x);
+                               length = fabs(d->p[0].x - d->p[1].x);
                        }
                        else if (d->subtype == DTLinear)
                        {
@@ -462,8 +459,8 @@ void DrawingView::RenderObjects(Painter * painter, Container * c)
                        Point p2 = linePt2 + (ortho * 10.0 * scaledThickness);
                        Point p3 = linePt1 + (ortho * 16.0 * scaledThickness);
                        Point p4 = linePt2 + (ortho * 16.0 * scaledThickness);
-                       Point p5 = d->p1 + (ortho * 4.0 * scaledThickness);
-                       Point p6 = d->p2 + (ortho * 4.0 * scaledThickness);
+                       Point p5 = d->p[0] + (ortho * 4.0 * scaledThickness);
+                       Point p6 = d->p[1] + (ortho * 4.0 * scaledThickness);
 
                /*
                The numbers hardcoded into here, what are they?
@@ -528,7 +525,7 @@ void DrawingView::RenderObjects(Painter * painter, Container * c)
                case OTText:
                {
                        Text * t = (Text *)obj;
-                       painter->DrawTextObject(t->p1, t->s.c_str(), scaledThickness);
+                       painter->DrawTextObject(t->p[0], t->s.c_str(), scaledThickness);
                        break;
                }
                default:
@@ -618,6 +615,8 @@ void DrawingView::ToolMouse(int mode, Point p)
 {
        if (Global::tool == TTLine)
                LineHandler(mode, p);
+       else if (Global::tool == TTRotate)
+               RotateHandler(mode, p);
 }
 
 
@@ -646,6 +645,41 @@ void DrawingView::ToolDraw(Painter * painter)
                        painter->DrawInformativeText(text);
                }
        }
+       else if (Global::tool == TTRotate)
+       {
+               if ((Global::toolState == TSNone) || (Global::toolState == TSPoint1))
+                       painter->DrawHandle(toolPoint[0]);
+               else if ((Global::toolState == TSPoint2) && shiftDown)
+                       painter->DrawHandle(toolPoint[1]);
+               else
+               {
+                       if (toolPoint[0] == toolPoint[1])
+                               return;
+                       
+                       painter->DrawLine(toolPoint[0], toolPoint[1]);
+                       // Likely we need a tool container for this... (now we do!)
+#if 0
+                       if (ctrlDown)
+                       {
+                               painter->SetPen(0x00FF00, 2.0, LSSolid);
+                               overrideColor = true;
+                       }
+
+                       RenderObjects(painter, toolObjects);
+                       overrideColor = false;
+#endif
+
+                       double absAngle = (Vector(toolPoint[1] - toolPoint[0]).Angle()) * RADIANS_TO_DEGREES;
+
+                       QString text = QChar(0x2221) + QObject::tr(": %1");
+                       text = text.arg(absAngle);
+
+                       if (ctrlDown)
+                               text += " (Copy)";
+
+                       painter->DrawInformativeText(text);
+               }
+       }
 }
 
 
@@ -690,6 +724,88 @@ void DrawingView::LineHandler(int mode, Point p)
 }
 
 
+void DrawingView::RotateHandler(int mode, Point p)
+{
+       switch (mode)
+       {
+       case ToolMouseDown:
+               if (Global::toolState == TSNone)
+               {
+                       toolPoint[0] = p;
+                       toolObjects.clear();
+                       CopyObjects(select, toolObjects);
+//                     ClearSelected(toolObjects);
+                       Global::toolState = TSPoint1;
+               }
+               else if (Global::toolState == TSPoint1)
+                       toolPoint[0] = p;
+               else
+                       toolPoint[1] = p;
+
+               break;
+       case ToolMouseMove:
+/*
+There's two approaches to this that we can do:
+
+ -- Keep a copy of selected objects & rotate those (drawing rotated + selected)
+ -- Rotate the selected (drawing selected only)
+
+Either way, we need to have a copy of the points before we change them; we also need
+to know whether or not to discard any changes made--maybe with a ToolCleanup()
+function.
+*/
+               if ((Global::toolState == TSPoint1) || (Global::toolState == TSNone))
+                       toolPoint[0] = p;
+               else if (Global::toolState == TSPoint2)
+               {
+// need to reset the selected points to their non-rotated state in this case...
+                       if (shiftDown)
+                               return;
+
+                       toolPoint[1] = p;
+
+                       double angle = Vector(toolPoint[1], toolPoint[0]).Angle();
+                       std::vector<void *>::iterator j = select.begin();
+                       std::vector<void *>::iterator i = toolObjects.begin();
+
+//                     for(; i!=select.end(); i++, j++)
+                       for(; i!=toolObjects.end(); i++, j++)
+                       {
+                               Object * obj = (Object *)(*i);
+                               Point p1 = Geometry::RotatePointAroundPoint(obj->p[0], toolPoint[0], angle);
+                               Point p2 = Geometry::RotatePointAroundPoint(obj->p[1], toolPoint[0], angle);
+                               Object * obj2 = (Object *)(*j);
+                               obj2->p[0] = p1;
+                               obj2->p[1] = p2;
+                       }
+               }
+
+               break;
+       case ToolMouseUp:
+               if (Global::toolState == TSPoint1)
+               {
+                       Global::toolState = TSPoint2;
+                       // Prevent spurious line from drawing...
+                       toolPoint[1] = toolPoint[0];
+               }
+               else if ((Global::toolState == TSPoint2) && shiftDown)
+               {
+                       // Key override is telling us to make a new line, not continue the
+                       // previous one.
+                       toolPoint[0] = toolPoint[1];
+               }
+               else
+               {
+#if 0
+                       Line * l = new Line(toolPoint[0], toolPoint[1]);
+                       document.objects.push_back(l);
+                       toolPoint[0] = toolPoint[1];
+#endif
+               }
+       }
+}
+
+
 void DrawingView::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::LeftButton)
@@ -780,38 +896,9 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
        }
 
        // Handle object movement (left button down & over an object)
-       if ((event->buttons() & Qt::LeftButton) && numHovered)
+       if ((event->buttons() & Qt::LeftButton) && numHovered && !Global::tool)
        {
-               if (Global::snapToGrid)
-                       point = SnapPointToGrid(point);
-
-               Point delta = point - oldPoint;
-               Object * obj = (Object *)hover[0];
-//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"));
-
-               switch (obj->type)
-               {
-               case OTLine:
-               {
-                       Line * l = (Line *)obj;
-
-                       if (l->hitPoint[0])
-                               l->p1 = point;
-                       else if (l->hitPoint[1])
-                               l->p2 = point;
-                       else if (l->hitObject)
-                       {
-                               l->p1 += delta;
-                               l->p2 += delta;
-                       }
-
-                       break;
-               }
-               default:
-                       break;
-               }
-
+               HandleObjectMovement(point);
                update();
                oldPoint = point;
                return;
@@ -841,29 +928,20 @@ void DrawingView::mouseReleaseEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::LeftButton)
        {
-#if 0
-               document.PointerReleased();
-#endif
-
 //We need to update especially if nothing collided and the state needs to change. !!! FIX !!!
 //could set it up to use the document's update function (assumes that all object updates
 //are being reported correctly:
 //             if (document.NeedsUpdate())
+               // Do an update if collided with at least *one* object in the document
 //             if (collided)
-                       update();       // Do an update if collided with at least *one* object in the document
+                       update();
 
-#if 0
-               if (toolAction)
-                       toolAction->MouseReleased();
-#else
                if (Global::tool)
                {
                        Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
-//                     ToolMouseUp(point);
                        ToolMouse(ToolMouseUp, point);
                        return;
                }
-#endif
 
                if (Global::selectionInProgress)
                {
@@ -1000,7 +1078,7 @@ void DrawingView::CheckObjectBounds(void)
                {
                        Line * l = (Line *)obj;
 
-                       if (Global::selection.contains(l->p1.x, l->p1.y) && Global::selection.contains(l->p2.x, l->p2.y))
+                       if (Global::selection.contains(l->p[0].x, l->p[0].y) && Global::selection.contains(l->p[1].x, l->p[1].y))
                                l->selected = true;
 
                        break;
@@ -1009,7 +1087,7 @@ void DrawingView::CheckObjectBounds(void)
                {
                        Circle * c = (Circle *)obj;
 
-                       if (Global::selection.contains(c->p1.x - c->radius, c->p1.y - c->radius) && Global::selection.contains(c->p1.x + c->radius, c->p1.y + c->radius))
+                       if (Global::selection.contains(c->p[0].x - c->radius, c->p[0].y - c->radius) && Global::selection.contains(c->p[0].x + c->radius, c->p[0].y + c->radius))
                                c->selected = true;
 
                        break;
@@ -1072,7 +1150,7 @@ void DrawingView::CheckObjectBounds(void)
 
                        bounds.setTopLeft(QPointF(bounds.left() * a->radius, bounds.top() * a->radius));
                        bounds.setBottomRight(QPointF(bounds.right() * a->radius, bounds.bottom() * a->radius));
-                       bounds.translate(a->p1.x, a->p1.y);
+                       bounds.translate(a->p[0].x, a->p[0].y);
 
                        if (Global::selection.contains(bounds))
                                a->selected = true;
@@ -1106,10 +1184,10 @@ bool DrawingView::HitTestObjects(Point point)
                        Line * l = (Line *)obj;
                        bool oldHP0 = l->hitPoint[0], oldHP1 = l->hitPoint[1], oldHO = l->hitObject;
                        l->hitPoint[0] = l->hitPoint[1] = l->hitObject = false;
-                       Vector lineSegment = l->p2 - l->p1;
-                       Vector v1 = point - l->p1;
-                       Vector v2 = point - l->p2;
-                       double t = Geometry::ParameterOfLineAndPoint(l->p1, l->p2, point);
+                       Vector lineSegment = l->p[1] - l->p[0];
+                       Vector v1 = point - l->p[0];
+                       Vector v2 = point - l->p[1];
+                       double t = Geometry::ParameterOfLineAndPoint(l->p[0], l->p[1], point);
                        double distance;
 
                        if (t < 0.0)
@@ -1168,6 +1246,41 @@ bool DrawingView::HitTestObjects(Point point)
 }
 
 
+void DrawingView::HandleObjectMovement(Point point)
+{
+       if (Global::snapToGrid)
+               point = SnapPointToGrid(point);
+
+       Point delta = point - oldPoint;
+       Object * obj = (Object *)hover[0];
+//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"));
+
+       switch (obj->type)
+       {
+       case OTLine:
+       {
+               Line * l = (Line *)obj;
+
+               if (l->hitPoint[0])
+                       l->p[0] = point;
+               else if (l->hitPoint[1])
+                       l->p[1] = point;
+               else if (l->hitObject)
+               {
+                       l->p[0] += delta;
+                       l->p[1] += delta;
+               }
+
+               break;
+       }
+       default:
+               break;
+       }
+}
+
+
+
 #if 0
        // This returns true if we've moved over an object...
        if (document.PointerMoved(point)) // <-- This