#include "mathconstants.h"
#include "painter.h"
#include "structs.h"
+#include "utils.h"
#define BACKGROUND_MAX_SIZE 512
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)
#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;
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;
}
{
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;
{
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)
{
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?
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:
{
if (Global::tool == TTLine)
LineHandler(mode, p);
+ else if (Global::tool == TTRotate)
+ RotateHandler(mode, p);
}
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);
+ }
+ }
}
}
+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)
}
// 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;
{
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)
{
{
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;
{
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;
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;
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)
}
+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