]> Shamusworld >> Repos - architektonas/blobdiff - src/drawingview.cpp
Added base units & display style to drawing.
[architektonas] / src / drawingview.cpp
index d8726fed5d91d82d86e2616877306ba2a1401cb6..3b6f92c6663c363bba9b1cf68e006793f101a7e0 100644 (file)
@@ -41,6 +41,7 @@
 #include "painter.h"
 #include "penwidget.h"
 #include "structs.h"
+#include "units.h"
 #include "utils.h"
 
 #define BACKGROUND_MAX_SIZE    512
@@ -52,8 +53,9 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
        gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
        scale(1.0), offsetX(-10), offsetY(-10), supressSelected(false),
        document(true),
-       gridPixels(0), collided(false), scrollDrag(false), hoverPointValid(false),
-       hoveringIntersection(false), dragged(NULL), draggingObject(false),
+       gridPixels(0), collided(false), scrollDrag(false),
+       hoverPointValid(false), hoveringIntersection(false),
+       dragged(NULL), draggingObject(false),
        angleSnap(false), dirty(false)
 {
 //wtf? doesn't work except in c++11??? document = { 0 };
@@ -357,8 +359,8 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
        // 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.SetPen(QPen(QColor(0xFF, 0x7F, 0x00, 0xFF)));
+               painter.SetBrush(QBrush(QColor(0xFF, 0x7F, 0x00, 0x64)));
                painter.DrawRect(Global::selection);
        }
 
@@ -556,20 +558,7 @@ void DrawingView::RenderObjects(Painter * painter, VPVector & v, int layer, bool
                        painter->SetFont(QFont("Arial", 8.0 * Global::zoom * scaledThickness));
                        Point ctr = p2 + (Vector(p2, p1) / 2.0);
 
-                       QString dimText;
-
-                       if (length < 12.0)
-                               dimText = QString("%1\"").arg(length);
-                       else
-                       {
-                               double feet = (double)((int)length / 12);
-                               double inches = length - (feet * 12.0);
-
-                               if (inches == 0)
-                                       dimText = QString("%1'").arg(feet);
-                               else
-                                       dimText = QString("%1' %2\"").arg(feet).arg(inches);
-                       }
+                       QString dimText = GetDimensionText(&document, length);
 
 /*
 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().
@@ -809,8 +798,9 @@ void DrawingView::ToolHandler(int mode, Point p)
 
 void DrawingView::ToolDraw(Painter * painter)
 {
-       if (Global::tool == TTLine)
+       switch (Global::tool)
        {
+       case TTLine:
                if (Global::toolState == TSNone)
                {
                        painter->DrawHandle(toolPoint[0]);
@@ -830,9 +820,10 @@ void DrawingView::ToolDraw(Painter * painter)
                        QString text = tr("Length: %1 in.\n") + QChar(0x2221) + tr(": %2");
                        informativeText = text.arg(absLength).arg(absAngle);
                }
-       }
-       else if (Global::tool == TTCircle)
-       {
+
+               break;
+
+       case TTCircle:
                if (Global::toolState == TSNone)
                {
                        painter->DrawHandle(toolPoint[0]);
@@ -850,9 +841,10 @@ void DrawingView::ToolDraw(Painter * painter)
                        QString text = tr("Radius: %1 in.");
                        informativeText = text.arg(length);
                }
-       }
-       else if (Global::tool == TTArc)
-       {
+
+               break;
+
+       case TTArc:
                if (Global::toolState == TSNone)
                {
                        painter->DrawHandle(toolPoint[0]);
@@ -894,9 +886,10 @@ void DrawingView::ToolDraw(Painter * painter)
                        QString text = tr("Arc span: %1") + QChar(0x00B0);
                        informativeText = text.arg(RADIANS_TO_DEGREES * span);
                }
-       }
-       else if (Global::tool == TTRotate)
-       {
+
+               break;
+
+       case TTRotate:
                if ((Global::toolState == TSNone) || (Global::toolState == TSPoint1))
                        painter->DrawHandle(toolPoint[0]);
                else if ((Global::toolState == TSPoint2) && shiftDown)
@@ -915,9 +908,10 @@ void DrawingView::ToolDraw(Painter * painter)
                        if (ctrlDown)
                                informativeText += " (Copy)";
                }
-       }
-       else if (Global::tool == TTMirror)
-       {
+
+               break;
+
+       case TTMirror:
                if ((Global::toolState == TSNone) || (Global::toolState == TSPoint1))
                        painter->DrawHandle(toolPoint[0]);
                else if ((Global::toolState == TSPoint2) && shiftDown)
@@ -941,9 +935,10 @@ void DrawingView::ToolDraw(Painter * painter)
                        if (ctrlDown)
                                informativeText += " (Copy)";
                }
-       }
-       else if (Global::tool == TTDimension)
-       {
+
+               break;
+
+       case TTDimension:
                if (Global::toolState == TSNone)
                {
                        painter->DrawHandle(toolPoint[0]);
@@ -963,9 +958,10 @@ void DrawingView::ToolDraw(Painter * painter)
                        QString text = tr("Length: %1 in.\n") + QChar(0x2221) + tr(": %2");
                        informativeText = text.arg(absLength).arg(absAngle);
                }
-       }
-       else if (Global::tool == TTTrim)
-       {
+
+               break;
+
+       case TTTrim:
                if (toolObj[0] != NULL)
                {
                        // We're assuming ATM it's just a line...
@@ -974,9 +970,43 @@ void DrawingView::ToolDraw(Painter * painter)
 //                     QString text = tr("Arc span: %1") + QChar(0x00B0);
 //                     informativeText = text.arg(RADIANS_TO_DEGREES * span);
                }
-       }
-       else if (Global::tool == TTParallel)
-       {
+
+               break;
+
+       case TTParallel:
+               if (Global::toolState == TSPoint1)
+               {
+                       painter->SetPen(0xFF00FF, 2.0, LSSolid);
+                       painter->SetBrush(QBrush(Qt::NoBrush));
+
+                       double length = Vector::Magnitude(toolObj[0]->p[0], toolPoint[0]);
+                       bool inside = (length >= toolObj[0]->radius[0] ? false : true);
+
+                       for(int i=1; i<=Global::parallelNum; i++)
+                       {
+                               if (toolObj[0]->type == OTLine)
+                               {
+                                       painter->DrawLine(toolObj[0]->p[0] + (toolPoint[0] * Global::parallelDist * (double)i), toolObj[0]->p[1] + (toolPoint[0] * Global::parallelDist * (double)i));
+                               }
+                               else if ((toolObj[0]->type == OTCircle) || (toolObj[0]->type == OTArc))
+                               {
+                                       double radius = toolObj[0]->radius[0] + ((double)i * Global::parallelDist * (inside ? -1.0 : 1.0));
+
+                                       if (radius > 0)
+                                       {
+                                               if (toolObj[0]->type == OTCircle)
+                                                       painter->DrawEllipse(toolObj[0]->p[0], radius, radius);
+                                               else
+                                                       painter->DrawArc(toolObj[0]->p[0], radius, toolObj[0]->angle[0], toolObj[0]->angle[1]);
+                                       }
+                               }
+                       }
+               }
+
+               break;
+
+       default:
+               break;
        }
 }
 
@@ -1757,14 +1787,85 @@ void DrawingView::TrimHandler(int mode, Point p)
        }
 }
 
-void DrawingView::ParallelHandler(int mode, Point /*p*/)
+void DrawingView::ParallelHandler(int mode, Point p)
 {
        switch (mode)
        {
        case ToolMouseDown:
+               if (numHovered == 1)
+               {
+                       // New selection made...
+                       VPVector hover = GetHovered();
+                       toolObj[0] = (Object *)hover[0];
+                       Global::toolState = TSNone;
+               }
+               else if ((numHovered == 0) && (toolObj[0] != NULL))
+               {
+                       double length = Vector::Magnitude(toolObj[0]->p[0], toolPoint[0]);
+                       bool inside = (length >= toolObj[0]->radius[0] ? false : true);
+
+                       // Stamp out new parallel object(s)...
+                       for(int i=1; i<=Global::parallelNum; i++)
+                       {
+                               if (toolObj[0]->type == OTLine)
+                               {
+                                       Line * l = new Line(toolObj[0]->p[0] + (toolPoint[0] * Global::parallelDist * (double)i), toolObj[0]->p[1] + (toolPoint[0] * Global::parallelDist * (double)i), Global::penWidth, Global::penColor, Global::penStyle);
+                                       // Should probably have a user selection for this whether it goes into the selected objects layer or the global layer...
+                                       l->layer = toolObj[0]->layer;
+                                       document.objects.push_back(l);
+                               }
+                               else if (toolObj[0]->type == OTCircle)
+                               {
+                                       double radius = toolObj[0]->radius[0] + ((double)i * Global::parallelDist * (inside ?  -1.0 : 1.0));
+
+                                       if (radius > 0)
+                                       {
+                                               Circle * c = new Circle(toolObj[0]->p[0], radius, Global::penWidth, Global::penColor, Global::penStyle);
+                                               c->layer = toolObj[0]->layer;
+                                               document.objects.push_back(c);
+                                       }
+                               }
+                               else if (toolObj[0]->type == OTArc)
+                               {
+                                       double radius = toolObj[0]->radius[0] + ((double)i * Global::parallelDist * (inside ?  -1.0 : 1.0));
+
+                                       if (radius > 0)
+                                       {
+                                               Arc * a = new Arc(toolObj[0]->p[0], radius, toolObj[0]->angle[0], toolObj[0]->angle[1], Global::penWidth, Global::penColor, Global::penStyle);
+                                               a->layer = toolObj[0]->layer;
+                                               document.objects.push_back(a);
+                                       }
+                               }
+                       }
+
+                       // Then reset the state
+                       toolObj[0]->selected = false;
+                       toolObj[0] = NULL;
+                       Global::toolState = TSNone;
+               }
+
                break;
 
        case ToolMouseMove:
+               if ((numHovered == 0) && toolObj[0] != NULL)
+                       Global::toolState = TSPoint1;
+               else
+                       Global::toolState = TSNone;
+
+               if (Global::toolState == TSPoint1)
+               {
+                       // Figure out which side of the object we're on, and draw the preview on that side...
+                       if (toolObj[0]->type == OTLine)
+                       {
+                               Vector normal = Geometry::GetNormalOfPointAndLine(p, (Line *)toolObj[0]);
+                               toolPoint[0] = normal;
+                       }
+                       else if ((toolObj[0]->type == OTCircle) || (toolObj[0]->type == OTArc))
+                       {
+                               toolPoint[0] = p;
+                       }
+               }
+
                break;
 
        case ToolMouseUp:
@@ -1852,9 +1953,14 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
                        if (Global::fixedLength)
                        {
                                if (dragged->type == OTLine)
-                               {
-                                       dragged->length = Vector::Magnitude(dragged->p[0], dragged->p[1]);
-                               }
+                                       dragged->length = ((Line *)dragged)->Length();
+                       }
+
+                       // Needed for fixed angle handling
+                       if (Global::fixedAngle)
+                       {
+                               if (dragged->type == OTLine)
+                                       dragged->p[2] = ((Line *)dragged)->Unit();
                        }
 
                        if (dragged->type == OTCircle)
@@ -2522,6 +2628,10 @@ bool DrawingView::HitTest(Object * obj, Point point)
 {
        bool needUpdate = false;
 
+       // Make sure we don't hit test stuff on an invisible layer...
+       if (Global::layerHidden[obj->layer] == true)
+               return false;
+
        switch (obj->type)
        {
        case OTLine:
@@ -2860,24 +2970,40 @@ void DrawingView::HandleObjectMovement(Point point)
        case OTLine:
                if (obj->hitPoint[0])
                {
+/*
+N.B.: Mixing fixed length with fixed angle (and in this order) is probably *not* going to work out in any meaningful way, and we should probably make the GUI force these to be mutually exclusive.  Besides, this combined effect already works by dragging the line segment by clicking on it.  :-P
+*/
                        if (Global::fixedLength)
                        {
-                               Vector line = point - obj->p[1];
-                               Vector unit = line.Unit();
+                               Vector unit = Vector::Unit(obj->p[1], point);
                                point = obj->p[1] + (unit * obj->length);
                        }
 
+                       if (Global::fixedAngle)
+                       {
+                               // Calculate the component of the current vector along the
+                               // fixed angle: A_compB = (A • Bu) * Bu  (p[2] has the unit
+                               // vector "Bu".)
+                               double magnitudeAlongB = Vector::Dot(Vector(point - obj->p[1]), obj->p[2]);
+                               point = obj->p[1] + (obj->p[2] * magnitudeAlongB);
+                       }
+
                        obj->p[0] = point;
                }
                else if (obj->hitPoint[1])
                {
                        if (Global::fixedLength)
                        {
-                               Vector line = point - obj->p[0];
-                               Vector unit = line.Unit();
+                               Vector unit = Vector::Unit(obj->p[0], point);
                                point = obj->p[0] + (unit * obj->length);
                        }
 
+                       if (Global::fixedAngle)
+                       {
+                               double magnitudeAlongB = Vector::Dot(Vector(point - obj->p[0]), obj->p[2]);
+                               point = obj->p[0] + (obj->p[2] * magnitudeAlongB);
+                       }
+
                        obj->p[1] = point;
                }
                else if (obj->hitObject)
@@ -2897,7 +3023,7 @@ void DrawingView::HandleObjectMovement(Point point)
                        obj->radius[0] = Vector::Magnitude(obj->p[0], point);
 
                        QString text = QObject::tr("Radius: %1\nScale: %2%");
-                       informativeText = text.arg(obj->radius[0], 0, 'd', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'd', 0);
+                       informativeText = text.arg(obj->radius[0], 0, 'f', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'f', 0);
                }
 
                break;