]> Shamusworld >> Repos - architektonas/blobdiff - src/arc.cpp
Fixed loading code, added "Base Unit" dialog.
[architektonas] / src / arc.cpp
index adccd21507f23c816110b031c45aa3450a0d9c2c..89a46f3dab1e0ca12cd6e65acb4abeed92ef3250 100644 (file)
@@ -4,7 +4,7 @@
 // (C) 2011 Underground Software
 // See the README and GPLv3 files for licensing and warranty information
 //
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
 //
 // WHO  WHEN        WHAT
 // ---  ----------  ------------------------------------------------------------
 
 #include <QtGui>
 #include "mathconstants.h"
+#include "painter.h"
 
 
-Arc::Arc(Vector p1, double r, double a1, double a2, Object * p/*= NULL*/): Object(p1, p),
-       radius(r), startAngle(a1), angleSpan(a2)
+Arc::Arc(Vector p1, double r, double a1, double a2, Object * p/*= NULL*/):
+       Object(p1, p), /*type(OTArc),*/ radius(r), startAngle(a1), angleSpan(a2)
 {
+       // This is in the base class, why can't we use the contructor to fill it???
+       type = OTArc;
 }
 
+
 Arc::~Arc()
 {
 }
 
-/*virtual*/ void Arc::Draw(QPainter * painter)
+
+/*virtual*/ void Arc::Draw(Painter * painter)
 {
+       QPen pen;
+
        if (state == OSSelected)
        {
                Point p1(cos(startAngle), sin(startAngle));
@@ -44,23 +51,25 @@ Arc::~Arc()
                                // moving it from.
                                Point p3(cos(oldAngle), sin(oldAngle));
                                Vector oldLine = (p3 * (radius * 1.25)) + position;
-                               painter->setPen(QPen(QColor(0x80, 0x80, 0x80), 1.0, Qt::DashLine));
-                               painter->drawLine((int)position.x, (int)position.y, (int)oldLine.x, (int)oldLine.y);
+                               pen = QPen(QColor(0x80, 0x80, 0x80), 1.0, Qt::DashLine);
+                               painter->SetPen(pen);
+                               painter->DrawLine((int)position.x, (int)position.y, (int)oldLine.x, (int)oldLine.y);
                        }
 
                        // In rotating and setting the span, we draw a line showing where
                        // we angle/span is that we're setting.
-                       painter->setPen(QPen(QColor(0x00, 0xC0, 0x80), 1.0, Qt::DashLine));
-                       painter->drawLine((int)position.x, (int)position.y, (int)oldPoint.x, (int)oldPoint.y);
+                       pen = QPen(QColor(0x00, 0xC0, 0x80), 1.0, Qt::DashLine);
+                       painter->SetPen(pen);
+                       painter->DrawLine((int)position.x, (int)position.y, (int)oldPoint.x, (int)oldPoint.y);
                }
 
                // Draw the center point of the arc
-               painter->setPen(QPen(Qt::red, 2.0, Qt::DotLine));
-               painter->drawEllipse(QPointF(position.x, position.y), 4.0, 4.0);
+               painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
+               painter->DrawHandle(position);
 
                // Draw the rotation & span setting handles
-               painter->drawEllipse(QPointF(handle2.x, handle2.y), 4.0, 4.0);
-               painter->drawEllipse(QPointF(handle3.x, handle3.y), 4.0, 4.0);
+               painter->DrawHandle(handle2);
+               painter->DrawHandle(handle3);
 
                // If we're rotating or setting the span, draw an information panel
                // showing both absolute and relative angles being set.
@@ -70,13 +79,6 @@ Arc::~Arc()
                        double relAngle = (startAngle >= oldAngle ? startAngle - oldAngle :
                                startAngle - oldAngle + (2.0 * PI)) * RADIANS_TO_DEGREES;
 
-                       painter->save();
-//close, but no cigar. we need to "invert" our transformation to make this work properly
-//     return QPoint(-offsetX + x, (size().height() - (-offsetY + y)) * +1.0);
-//                     painter->translate(0, viewportHeight);
-//                     painter->scale(1.0, -1.0);
-// Give up for now; just paint the info panel in the upper left corner of the screen
-                       painter->resetTransform();
                        QString text;
 
                        if (hitHandle2)
@@ -97,35 +99,38 @@ Arc::~Arc()
                                text = text.arg(radius, 0, 'd', 4).arg(radius / oldRadius * 100.0, 0, 'd', 0);
                        }
 
-                       painter->setPen(QPen(QColor(0x00, 0xFF, 0x00), 1.0, Qt::SolidLine));
-                       painter->setBrush(QBrush(QColor(0x40, 0xFF, 0x40, 0x9F)));
-                       QRectF textRect(10.0, 10.0, 220.0, 60.0);       // x, y, w, h
-                       painter->drawRoundedRect(textRect, 7.0, 7.0);
+                       pen = QPen(QColor(0x00, 0xFF, 0x00), 1.0, Qt::SolidLine);
+                       painter->SetPen(pen);
+                       painter->SetBrush(QBrush(QColor(0x40, 0xFF, 0x40, 0x9F)));
+                       QRectF textRect(10.0, 10.0, 270.0, 70.0);       // x, y, w, h
+                       painter->DrawRoundedRect(textRect, 7.0, 7.0);
 
                        textRect.setLeft(textRect.left() + 14);
-                       painter->setFont(*Object::font);
-                       painter->setPen(QPen(QColor(0xDF, 0x5F, 0x00), 1.0, Qt::SolidLine));
-                       painter->drawText(textRect, Qt::AlignVCenter, text);
-                       painter->restore();
+                       painter->SetFont(*Object::font);
+//                     pen = QPen(QColor(0xDF, 0x5F, 0x00), 1.0, Qt::SolidLine);
+                       pen = QPen(QColor(0x00, 0x5F, 0xDF));
+                       painter->SetPen(pen);
+                       painter->DrawText(textRect, Qt::AlignVCenter, text);
+                       painter->SetPen(QPen(QColor(0xDF, 0x5F, 0x00)));
                }
-
-//             painter->setPen(QPen(Qt::red, 2.0, Qt::DotLine));
        }
        else
-               painter->setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+       {
+               pen = QPen(Qt::black, 1.0, Qt::SolidLine);
+               painter->SetPen(pen);
+       }
 
-       QRectF rectangle(QPointF(position.x - radius, position.y - radius),
-               QPointF(position.x + radius, position.y + radius));
-       int angle1 = (int)(startAngle * RADIANS_TO_DEGREES * 16.0);
-       int angle2 = (int)(angleSpan * RADIANS_TO_DEGREES * 16.0);
-       painter->drawArc(rectangle, -angle1, -angle2);
+       painter->DrawArc(position, radius, startAngle, angleSpan);
+//     painter->DrawRect(Extents());
 }
 
+
 /*virtual*/ Vector Arc::Center(void)
 {
        return position;
 }
 
+
 /*
  We need at least *four* handles for this object:
  - one for moving
@@ -229,8 +234,20 @@ so let's do like this:
        return false;
 }
 
+
 /*virtual*/ void Arc::PointerMoved(Vector point)
 {
+       if (selectionInProgress)
+       {
+               // Check for whether or not the rect contains this circle
+               if (selection.normalized().contains(Extents()))
+                       state = OSSelected;
+               else
+                       state = OSInactive;
+
+               return;
+       }
+
        // The TLC will send these messages if the object is selected but not clicked on.
        // So we have to be careful with our assumptions here.
        // This is actually untrue in that case, we need to come up with something better
@@ -269,16 +286,18 @@ so let's do like this:
        needUpdate = true;
 }
 
+
 /*virtual*/ void Arc::PointerReleased(void)
 {
        hitHandle1 = hitHandle2 = hitHandle3 = hitHandle4 = false;
        // Here we check for just a click: If object was clicked and dragged, then
        // revert to the old state (OSInactive). Otherwise, keep the new state that
        // we set.
-/*Maybe it would be better to just check for "object was dragged" state and not have to worry
-about keeping track of old states...
-Well, we can't know if it was dragged from Inactive or not, that's the problem. We could make
-a variable called "needToRevertToInactive" instead
+/*
+Maybe it would be better to just check for "object was dragged" state and not
+have to worry about keeping track of old states...
+Well, we can't know if it was dragged from Inactive or not, that's the problem.
+We could make a variable called "needToRevertToInactive" instead
 
 I mean, we could write like:
        if (objectWasDragged && oldState == OSInactive)
@@ -290,6 +309,63 @@ but this is actually more compact and cleaner.
                state = oldState;
 }
 
+
+/*virtual*/ QRectF Arc::Extents(void)
+{
+       double start = startAngle;
+       double end = start + angleSpan;
+       QPointF p1(cos(start), sin(start));
+       QPointF p2(cos(end), sin(end));
+       QRectF bounds(p1, p2);
+
+       // Swap X/Y coordinates if they're backwards...
+       if (bounds.left() > bounds.right())
+       {
+               double temp = bounds.left();
+               bounds.setLeft(bounds.right());
+               bounds.setRight(temp);
+       }
+
+       if (bounds.bottom() > bounds.top())
+       {
+               double temp = bounds.bottom();
+               bounds.setBottom(bounds.top());
+               bounds.setTop(temp);
+       }
+
+       // If the end of the arc is before the beginning, add 360 degrees to it
+       if (end < start)
+               end += 2.0 * PI;
+
+       // Adjust the bounds depending on which axes are crossed
+       if ((start < PI_OVER_2) && (end > PI_OVER_2))
+               bounds.setTop(1.0);
+
+       if ((start < PI) && (end > PI))
+               bounds.setLeft(-1.0);
+
+       if ((start < (PI + PI_OVER_2)) && (end > (PI + PI_OVER_2)))
+               bounds.setBottom(-1.0);
+
+       if ((start < (2.0 * PI)) && (end > (2.0 * PI)))
+               bounds.setRight(1.0);
+
+       if ((start < ((2.0 * PI) + PI_OVER_2)) && (end > ((2.0 * PI) + PI_OVER_2)))
+               bounds.setTop(1.0);
+
+       if ((start < (3.0 * PI)) && (end > (3.0 * PI)))
+               bounds.setLeft(-1.0);
+
+       if ((start < ((3.0 * PI) + PI_OVER_2)) && (end > ((3.0 * PI) + PI_OVER_2)))
+               bounds.setBottom(-1.0);
+
+       bounds.setTopLeft(QPointF(bounds.left() * radius, bounds.top() * radius));
+       bounds.setBottomRight(QPointF(bounds.right() * radius, bounds.bottom() * radius));
+       bounds.translate(position.x, position.y);
+       return bounds;
+}
+
+
 #if 0
 /*virtual*/ bool Arc::NeedsUpdate(void)
 {
@@ -297,6 +373,7 @@ but this is actually more compact and cleaner.
 }
 #endif
 
+
 /*
 start = 350, span = 20, end = 10, angle = 5
 angle < start, so angle = 365
@@ -316,3 +393,26 @@ bool Arc::AngleInArcSpan(double angle)
 
        return (passedInSpan <= angleSpan ?  true : false);
 }
+
+
+/*virtual*/ void Arc::Enumerate(FILE * file)
+{
+       fprintf(file, "ARC (%lf,%lf) %lf, %lf, %lf\n", position.x, position.y, radius, startAngle, angleSpan);
+}
+
+
+/*virtual*/ Object * Arc::Copy(void)
+{
+#warning "!!! This doesn't take care of attached Dimensions !!!"
+/*
+This is a real problem. While having a pointer in the Dimension to this line's points
+is fast & easy, it creates a huge problem when trying to replicate an object like this.
+
+Maybe a way to fix that then, is to have reference numbers instead of pointers. That
+way, if you copy them, ... you might still have problems. Because you can't be sure if
+a copy will be persistant or not, you then *definitely* do not want them to have the
+same reference number.
+*/
+       return new Arc(position, radius, startAngle, angleSpan, parent);
+}
+