# Architektonas Qt project file
#
# by James Hammons
-# Copyright (C) 2011 Underground Software
+# Copyright (C) 2015 Underground Software
#
# See the README and GPLv3 files for licensing and warranty information
#
src/painter.h \
src/settingsdialog.h \
src/structs.h \
+ src/utils.h \
src/vector.h
-# src/action.h \
-# src/arc.h \
-# src/circle.h \
-# src/connection.h \
-# src/container.h \
-# src/dimension.h \
-# src/drawarcaction.h \
-# src/drawcircleaction.h \
-# src/drawdimensionaction.h \
-# src/drawlineaction.h \
-# src/drawsplineaction.h \
-# src/drawtextaction.h \
-# src/ellipse.h \
-# src/line.h \
-# src/mirroraction.h \
-# src/object.h \
-# src/rotateaction.h \
-# src/spline.h \
-# src/text.h \
-# src/triangulateaction.h \
-# src/trimaction.h \
-
-
SOURCES = \
src/about.cpp \
src/applicationwindow.cpp \
src/main.cpp \
src/painter.cpp \
src/settingsdialog.cpp \
+ src/utils.cpp \
src/vector.cpp
-# src/action.cpp \
-# src/arc.cpp \
-# src/circle.cpp \
-# src/connection.cpp \
-# src/container.cpp \
-# src/dimension.cpp \
-# src/drawarcaction.cpp \
-# src/drawcircleaction.cpp \
-# src/drawdimensionaction.cpp \
-# src/drawlineaction.cpp \
-# src/drawsplineaction.cpp \
-# src/drawtextaction.cpp \
-# src/ellipse.cpp \
-# src/line.cpp \
-# src/mirroraction.cpp \
-# src/object.cpp \
-# src/rotateaction.cpp \
-# src/spline.cpp \
-# src/text.cpp \
-# src/triangulateaction.cpp \
-# src/trimaction.cpp \
-
#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
void SetGridSize(uint32_t);
void UpdateGridBackground(void);
Point SnapPointToGrid(Point);
- void RenderObjects(Painter *, Container *);
+ void RenderObjects(Painter *, std::vector<void *> &);
void DeleteSelectedItems(void);
void ClearSelection(void);
void AddHoveredToSelection(void);
void ToolMouse(int, Point);
void ToolDraw(Painter *);
void LineHandler(int, Point);
+ void RotateHandler(int, Point);
void CheckObjectBounds(void);
bool HitTestObjects(Point);
+ void HandleObjectMovement(Point);
public slots:
void AddNewObjectToDocument(Object *);
uint32_t numHovered;
bool shiftDown;
bool ctrlDown;
+ bool overrideColor;
private:
QPixmap gridBackground;
public:
std::vector<void *> select;
std::vector<void *> hover;
+ std::vector<void *> toolObjects;
Point toolPoint[32];
// public:
+++ /dev/null
-// drawsplineaction.cpp: Action class for drawing NURBS
-//
-// Part of the Architektonas Project
-// (C) 2014 Underground Software
-// See the README and GPLv3 files for licensing and warranty information
-//
-// JLH = James Hammons <jlhamm@acm.org>
-//
-// WHO WHEN WHAT
-// --- ---------- ------------------------------------------------------------
-// JLH 03/20/2014 Created this file
-//
-
-#include "drawsplineaction.h"
-#include "spline.h"
-#include "mathconstants.h"
-#include "painter.h"
-
-
-enum { FIRST_POINT, NEXT_POINT };
-
-
-DrawSplineAction::DrawSplineAction(): state(FIRST_POINT), spline(NULL),
- shiftWasPressedOnNextPoint(false)
-{
-}
-
-
-DrawSplineAction::~DrawSplineAction()
-{
-}
-
-
-/*virtual*/ void DrawSplineAction::Draw(Painter * painter)
-{
- painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
-
- // I think stuff like crosshairs should be done in the DrawingView, tho
- // (and it's done there now...)
- if (state == FIRST_POINT)
- {
- painter->DrawHandle(p1);
- }
- else
- {
- painter->DrawLine(p1, p2);
- painter->DrawHandle(p2);
-
- Vector v(p1, p2);
- double absAngle = v.Angle() * RADIANS_TO_DEGREES;
- double absLength = v.Magnitude();
- QString text = tr("Length: %1 in.\n") + QChar(0x2221) + tr(": %2");
- text = text.arg(absLength).arg(absAngle);
- painter->DrawInformativeText(text);
- }
-}
-
-
-/*virtual*/ void DrawSplineAction::MouseDown(Vector point)
-{
- // Clear our override...
- shiftWasPressedOnNextPoint = false;
-
- if (state == FIRST_POINT)
- p1 = point;
- else
- p2 = point;
-}
-
-
-/*virtual*/ void DrawSplineAction::MouseMoved(Vector point)
-{
- if (state == FIRST_POINT)
- p1 = point;
- else
- p2 = point;
-}
-
-
-/*virtual*/ void DrawSplineAction::MouseReleased(void)
-{
- if (state == FIRST_POINT)
- {
- p2 = p1;
- state = NEXT_POINT;
- spline = NULL;
- }
- else if (state == NEXT_POINT)
- {
- Spline * oldSpline = spline;
- // We create the new object here, and then pass it off to the
- // DrawingView which stuffs it into the document.
- spline = new Spline(p1, p2.Angle());
-
- // Connect Lines by default
- if (oldSpline)
- {
- oldSpline->Connect(spline, 0);
- spline->Connect(oldSpline, 1.0);
- }
-
- // We don't need no stinkin' sentinels, when we have signals & slots!
- emit ObjectReady(spline);
-
- p1 = p2;
- state = NEXT_POINT;
- }
-}
-
-
-/*virtual*/ void DrawSplineAction::KeyDown(int key)
-{
- if ((key == Qt::Key_Shift) && (state == NEXT_POINT))
- {
- shiftWasPressedOnNextPoint = true;
- p1Save = p1;
- p1 = p2;
- state = FIRST_POINT;
- emit NeedRefresh();
- }
-}
-
-
-/*virtual*/ void DrawSplineAction::KeyReleased(int key)
-{
- if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint)
- {
- shiftWasPressedOnNextPoint = false;
- p2 = p1;
- p1 = p1Save;
- state = NEXT_POINT;
- emit(NeedRefresh());
- }
-}
-
+++ /dev/null
-#ifndef __DRAWSPLINEACTION_H__
-#define __DRAWSPLINEACTION_H__
-
-#include "action.h"
-
-class Spline;
-
-class DrawSplineAction: public Action
-{
- public:
- DrawSplineAction();
- ~DrawSplineAction();
-
- virtual void Draw(Painter *);
- virtual void MouseDown(Vector);
- virtual void MouseMoved(Vector);
- virtual void MouseReleased(void);
- virtual void KeyDown(int);
- virtual void KeyReleased(int);
-
- private:
- int state;
- Spline * spline;
- Vector p1, p2, p1Save;
- bool shiftWasPressedOnNextPoint;
-};
-
-#endif // __DRAWSPLINEACTION_H__
-
+++ /dev/null
-// drawtextaction.cpp: Draw text object
-//
-// Part of the Architektonas Project
-// (C) 2011 Underground Software
-// See the README and GPLv3 files for licensing and warranty information
-//
-// JLH = James Hammons <jlhamm@acm.org>
-//
-// WHO WHEN WHAT
-// --- ---------- ------------------------------------------------------------
-// JLH 03/14/2013 Created this file
-//
-
-#include "drawtextaction.h"
-#include "painter.h"
-#include "text.h"
-//#include "vector.h"
-
-
-#define FIRST_POINT 0
-#define NEXT_POINT 1
-
-
-DrawTextAction::DrawTextAction(): state(0), text(NULL)
-{
-}
-
-
-DrawTextAction::~DrawTextAction()
-{
-}
-
-
-/*virtual*/ void DrawTextAction::Draw(Painter * painter)
-{
- painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
-
- // I think stuff like crosshairs should be done in the DrawingView, tho
- if (state == FIRST_POINT)
- {
- painter->DrawHandle(p1);
- }
- else
- {
-// painter->DrawLine(p1, p2);
-// painter->DrawHandle(p2);
- }
-}
-
-
-/*virtual*/ void DrawTextAction::MouseDown(Vector point)
-{
- if (state == FIRST_POINT)
- p1 = point;
-// else
-// p2 = point;
-}
-
-
-/*virtual*/ void DrawTextAction::MouseMoved(Vector point)
-{
- if (state == FIRST_POINT)
- p1 = point;
-// else
-// p2 = point;
-}
-
-
-/*virtual*/ void DrawTextAction::MouseReleased(void)
-{
- if (state == FIRST_POINT)
- {
-// p2 = p1;
- state = NEXT_POINT;
- }
- else if (state == NEXT_POINT)
- {
- // We create the new object here, and then pass it off to the
- // DrawingView which stuffs it into the document.
-// text = new Text(p1, p2);
- // We don't need no stinkin' sentinels, when we have signals & slots!
- emit ObjectReady(text);
-
-// p1 = p2;
- }
-}
-
-
-/*virtual*/ void DrawTextAction::KeyDown(int /*key*/)
-{
-}
-
-
-/*virtual*/ void DrawTextAction::KeyReleased(int /*key*/)
-{
-}
-
+++ /dev/null
-#ifndef __DRAWTEXTACTION_H__
-#define __DRAWTEXTACTION_H__
-
-#include "action.h"
-
-class Text;
-
-class DrawTextAction: public Action
-{
- public:
- DrawTextAction();
- ~DrawTextAction();
-
- virtual void Draw(Painter *);
- virtual void MouseDown(Vector);
- virtual void MouseMoved(Vector);
- virtual void MouseReleased(void);
- virtual void KeyDown(int);
- virtual void KeyReleased(int);
-
- private:
- int state;
- Text * text;
- Vector p1;
-};
-
-#endif // __DRAWTEXTACTION_H__
-
+++ /dev/null
-/*
-An ellipse is just a variant of a circle, do we really need a separate class
-for them?
-
-We have a separate class for arcs, and those are circle variants too.
-
-Maybe. The ellipse (and elliptical arc) have two focii and a rotation angle.
-But there's no reason why those extras couldn't go into the Circle class as
-well.
-
-Actually, all that's needed are the two focii and radius...
-*/
+++ /dev/null
-// spline.cpp: NURBS object
-//
-// Part of the Architektonas Project
-// (C) 2014 Underground Software
-// See the README and GPLv3 files for licensing and warranty information
-//
-// JLH = James Hammons <jlhamm@acm.org>
-//
-// WHO WHEN WHAT
-// --- ---------- ------------------------------------------------------------
-// JLH 03/20/2014 Created this file
-//
-
-#include "spline.h"
-
-#include <QtGui>
-#include "geometry.h"
-#include "painter.h"
-
-#warning "!!! This class is NOT CORRECT !!! FIX !!!"
-Spline::Spline(Vector p1, double r, Object * p/*= NULL*/): Object(p1, p), radius(r),
- draggingEdge(false), draggingCenter(false), hitCenter(false), hitSpline(false)
-{
- type = OTSpline;
-}
-
-
-Spline::~Spline()
-{
-}
-
-
-/*virtual*/ void Spline::Draw(Painter * painter)
-{
- if (state == OSSelected || hitSpline || hitCenter)
- painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
- else
- painter->SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
-
- // Hatch/Fill...
-// QBrush brush(Qt::DiagCrossPattern);
-// brush.setColor(QColor(255, 255, 0));
-// painter->SetBrush(brush);
- painter->SetBrush(QBrush(Qt::NoBrush));
-
- // Draw the object...
- painter->DrawEllipse(position, radius, radius);
-
- // & draw handles (if needed)
- if (state == OSSelected || hitCenter)
- painter->DrawHandle(position);
-
- if (state == OSSelected && draggingEdge && objectWasDragged)
- painter->DrawHandle(dragPoint);
-
- // If resizing the circle, draw an information panel showing the new radius.
- if (draggingEdge)
- {
- QString text = QObject::tr("Radius: %1\nScale: %2%");
- text = text.arg(radius, 0, 'd', 4).arg(radius / oldRadius * 100.0, 0, 'd', 0);
-#if 0
- QPen 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);
- pen = QPen(QColor(0x00, 0x5F, 0xDF));
- painter->SetPen(pen);
- painter->DrawText(textRect, Qt::AlignVCenter, text);
-#else
- painter->DrawInformativeText(text);
-#endif
- }
-}
-
-
-/*virtual*/ Vector Spline::Center(void)
-{
- return position;
-}
-
-
-/*virtual*/ bool Spline::Collided(Vector point)
-{
- // Someone told us to fuck off, so we'll fuck off. :-)
- if (ignoreClicks)
- return false;
-
- // We can assume this, since this is a mouse down event here.
- objectWasDragged = false;
- HitTest(point);
-
- // Now that we've done our hit testing on the non-snapped point, snap it if
- // necessary...
- if (snapToGrid)
- point = SnapPointToGrid(point);
-
- draggingCenter = hitCenter;
- draggingEdge = hitSpline;
-
- if (hitCenter || hitSpline)
- {
- dragPoint = point;
- oldState = state;
- state = OSSelected;
- oldRadius = radius;
- return true;
- }
-
- // We didn't hit anything, so deselect this object and report failure to hit
- state = OSInactive;
- return false;
-}
-
-
-/*virtual*/ bool Spline::PointerMoved(Vector point)
-{
- if (selectionInProgress)
- {
- // Check for whether or not the rect contains this circle
-// if (selection.normalized().contains(Extents()))
- if (selection.contains(Extents()))
- state = OSSelected;
- else
- state = OSInactive;
-
- return false;
- }
-
- // Hit test tells us what we hit (if anything) through boolean variables. It
- // also tells us whether or not the state changed.
- SaveHitState();
- bool hovered = HitTest(point);
- needUpdate = HitStateChanged();
- objectWasDragged = (draggingEdge | draggingCenter);
-
- if (objectWasDragged)
- needUpdate = true;
-
- if (draggingEdge)
- radius = Vector::Magnitude(point, position);
- else if (draggingCenter)
- position = point;
-
- // Save this point so the rendering code knows where to draw the handle...
- dragPoint = point;
- return hovered;
-}
-
-
-/*virtual*/ void Spline::PointerReleased(void)
-{
- // Mouse went up, so our dragging is done (if any *was* done, that is)
- draggingEdge = draggingCenter = false;
- hitCenter = hitSpline = false;
-
- // If the object was dragged, then revert to the old state.
- // Otherwise, we were probably just clicked, and want to stay in the selected state.
- if (objectWasDragged)
- state = oldState;
-}
-
-
-/*virtual*/ bool Spline::HitTest(Point point)
-{
-// SaveHitState();
- hitCenter = hitSpline = false;
- double length = Vector::Magnitude(position, point);
-//printf("Spline::length = %lf, radius = %lf\n", length, radius);
-//How to translate this into pixels from Document space???
-//Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
-//the caller knows about the zoom factor and all that good kinda crap
-/*
-Document passes in the correct Cartesian coordinates being pointed to by the mouse.
-So all we have to be concerned with is properly scaling our hot zones/handle sizes,
-since we generally *don't* want those to scale with the zoom level. ;-)
-
-What is going on here?
-If we're zoomed out to, say, 50%, & our radius is 10.0 (absolute), then on screen
-the radius will be 5.0. By multiplying the length by the zoom factor, we align our
-pointed at length with our on screen length.
-*/
- if ((length * Painter::zoom) < 8.0)
- hitCenter = true;
-//wrong: else if ((length < (radius + 2.0)) && (length > (radius - 2.0)))
-/*NB: The following should be identical to what we have down below, but it doesn't work out that way... :-P */
-//close, but no else if (((length * Painter::zoom) < ((radius * Painter::zoom) + 2.0)) && ((length * Painter::zoom) > ((radius * Painter::zoom) - 2.0)))
-//really wrong! else if (((length * Painter::zoom) < (radius + 2.0)) && ((length * Painter::zoom) > (radius - 2.0)))
-// close again, but sill no else if (((length * Painter::zoom) < ((radius + 2.0) * Painter::zoom)) && ((length * Painter::zoom) > ((radius - 2.0) * Painter::zoom)))
- else if ((fabs(length - radius) * Painter::zoom) < 2.0)
- hitSpline = true;
-
-// return HitStateChanged();
- return (hitCenter || hitSpline ? true : false);
-}
-
-
-/*virtual*/ QRectF Spline::Extents(void)
-{
- return QRectF(QPointF(position.x - radius, position.y - radius), QPointF(position.x + radius, position.y + radius));
-}
-
-
-void Spline::SaveHitState(void)
-{
- oldHitCenter = hitCenter;
- oldHitSpline = hitSpline;
-}
-
-
-bool Spline::HitStateChanged(void)
-{
- if ((hitCenter != oldHitCenter) || (hitSpline != oldHitSpline))
- return true;
-
- return false;
-}
-
-
-/*virtual*/ void Spline::Enumerate(FILE * file)
-{
- fprintf(file, "SPLINE %i (%lf,%lf) %lf\n", layer, position.x, position.y, radius);
-}
-
-
-/*virtual*/ Object * Spline::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 Spline(position, radius, parent);
-}
-
-
-/*virtual*/ void Spline::Rotate(Point point, double angle)
-{
- Point c1 = Geometry::RotatePointAroundPoint(position, point, angle);
- position = c1;
-}
-
-
-/*virtual*/ void Spline::Mirror(Point p1, Point p2)
-{
- Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2);
- position = c1;
-}
-
-
-/*virtual*/ void Spline::Save(void)
-{
- Object::Save();
- oldRadius2 = radius;
-}
-
-
-/*virtual*/ void Spline::Restore(void)
-{
- Object::Restore();
- radius = oldRadius2;
-}
-
+++ /dev/null
-#ifndef __SPLINE_H__
-#define __SPLINE_H__
-
-#include "object.h"
-
-class Spline: public Object
-{
- friend class Geometry;
-
- public:
- Spline(Vector, double, Object * p = 0);
- ~Spline();
-
- virtual void Draw(Painter *);
- virtual Vector Center(void);
- virtual bool Collided(Vector);
- virtual bool PointerMoved(Vector);
- virtual void PointerReleased(void);
- virtual bool HitTest(Point);
- virtual void Enumerate(FILE *);
- virtual Object * Copy(void);
- virtual QRectF Extents(void);
- virtual void Rotate(Point, double);
- virtual void Mirror(Point, Point);
- virtual void Save(void);
- virtual void Restore(void);
-
- protected:
- void SaveHitState(void);
- bool HitStateChanged(void);
-
- protected:
- double radius; // Center is Object::position
- Vector dragPoint; // Used for rendering edge dragging
- double oldRadius2;
-
- private:
- bool draggingEdge;
- bool draggingCenter;
- bool objectWasDragged;
- bool hitCenter, hitSpline;
- bool oldHitCenter, oldHitSpline;
- double oldRadius;
-};
-
-#endif // __SPLINE_H__
-
bool selected; \
bool hovered; \
bool hitPoint[4]; \
- bool hitObject;
+ bool hitObject; \
+ Point p[4];
struct Line {
OBJECT_COMMON;
- Point p1;
- Point p2;
Line(): type(OTLine), id(Global::objectID++) {}
Line(Vector pt1, Vector pt2, float th = 1.0, uint32_t c = 0, int l = LSSolid):
type(OTLine), id(Global::objectID++), layer(0), color(c), thickness(th),
- style(l), selected(false), hovered(false), hitObject(false), p1(pt1), p2(pt2) {}
+ style(l), selected(false), hovered(false), hitObject(false) { p[0] = pt1; p[1] = pt2; }
};
struct Circle {
OBJECT_COMMON;
- Point p1;
double radius;
+ Circle(): type(OTCircle), id(Global::objectID++) {}
Circle(Vector pt1, double r, float th = 1.0, uint32_t c = 0, int l = LSSolid):
type(OTCircle), id(Global::objectID++), layer(0), color(c), thickness(th),
- style(l), selected(false), hovered(false), hitObject(false), p1(pt1), radius(r) {}
+ style(l), selected(false), hovered(false), hitObject(false), radius(r) { p[0] = pt1; }
};
struct Ellipse {
OBJECT_COMMON;
- Point p1;
- Point p2;
double radius1;
double radius2;
+ Ellipse(): type(OTEllipse), id(Global::objectID++) {}
Ellipse(Vector pt1, Vector pt2, double r1, double r2, float th = 1.0, uint32_t c = 0, int l = LSSolid):
type(OTEllipse), id(Global::objectID++), layer(0), color(c), thickness(th),
- style(l), selected(false), hovered(false), hitObject(false), p1(pt1), p2(pt2), radius1(r1), radius2(r2) {}
+ style(l), selected(false), hovered(false), hitObject(false), radius1(r1), radius2(r2) { p[0] = pt1; p[1] = pt2; }
};
struct Arc {
OBJECT_COMMON;
- Point p1;
double radius;
double angle1;
double angle2;
+ Arc(): type(OTArc), id(Global::objectID++) {}
Arc(Vector pt1, double r, double a1, double a2, float th = 1.0, uint32_t c = 0, int l = LSSolid):
type(OTArc), id(Global::objectID++), layer(0), color(c), thickness(th),
- style(l), selected(false), hovered(false), hitObject(false), p1(pt1), radius(r), angle1(a1), angle2(a2) {}
+ style(l), selected(false), hovered(false), hitObject(false), radius(r), angle1(a1), angle2(a2) { p[0] = pt1; }
};
struct Dimension {
OBJECT_COMMON;
int subtype;
- Point p1;
- Point p2;
double offset;
+ Dimension(): type(OTDimension), id(Global::objectID++) {}
Dimension(Vector pt1, Vector pt2, DimensionType dt = DTLinear, float th = 1.0, uint32_t c = 0x0000FF, int l = LSSolid):
type(OTDimension), id(Global::objectID++), layer(0), color(c), thickness(th),
- style(l), selected(false), hovered(false), hitObject(false), subtype(dt), p1(pt1), p2(pt2) {}
+ style(l), selected(false), hovered(false), hitObject(false), subtype(dt) { p[0] = pt1; p[1] = pt2; }
};
struct Text {
OBJECT_COMMON;
- Point p1;
std::string s;
- Text(Vector pt, char * str, float th = 10.0, uint32_t c = 0):
+ Text(): type(OTText), id(Global::objectID++) {}
+ Text(Vector pt1, char * str, float th = 10.0, uint32_t c = 0):
type(OTText), id(Global::objectID++), layer(0), color(c), thickness(th),
- style(LSSolid), selected(false), hovered(false), hitObject(false), p1(pt), s(str) {}
+ style(LSSolid), selected(false), hovered(false), hitObject(false), s(str) { p[0] = pt1; }
};
struct Container {
OBJECT_COMMON;
- Point p1;
std::vector<void *> objects;
double angle;
double scale;
+++ /dev/null
-// text.cpp: Draw text object
-//
-// Part of the Architektonas Project
-// (C) 2011 Underground Software
-// See the README and GPLv3 files for licensing and warranty information
-//
-// JLH = James Hammons <jlhamm@acm.org>
-//
-// WHO WHEN WHAT
-// --- ---------- ------------------------------------------------------------
-// JLH 03/14/2013 Created this file
-//
-
-#include "text.h"
-
+++ /dev/null
-#ifndef __TEXT_H__
-#define __TEXT_H__
-
-#include "object.h"
-#include <QtWidgets>
-
-class Text: public Object
-{
- public:
- Text(Vector, QString, Object * p = 0);
- ~Text();
-
- virtual void Draw(Painter *);
- virtual Vector Center(void);
- virtual bool Collided(Vector);
- virtual bool PointerMoved(Vector);
- virtual void PointerReleased(void);
- virtual bool HitTest(Point);
- virtual void Enumerate(FILE *);
-// virtual Object * Copy(void);
- virtual Vector GetPointAtParameter(double parameter);
-
- protected:
- Vector oldPoint; // Used for dragging
-
- private:
- bool dragging;
- bool draggingHandle1;
- bool draggingHandle2;
- bool objectWasDragged;
-};
-
-#endif // __TEXT_H__
--- /dev/null
+// utils.cpp: Stuff that's useful to have kicking around, in one spot
+//
+// Part of the Architektonas Project
+// (C) 2015 Underground Software
+// See the README and GPLv3 files for licensing and warranty information
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// Who When What
+// --- ---------- -------------------------------------------------------------
+// JLH 05/01/2015 Created this file
+//
+
+#include "utils.h"
+#include <string.h> // For memcpy()
+
+
+//
+// Copy objects in one vector to another, creating copies and placing them in
+// the other vector. Clearing & etc. of vectors is responsibility of the caller!
+//
+void CopyObjects(std::vector<void *> & from, std::vector<void *> & to)
+{
+ std::vector<void *>::iterator i;
+
+ for(i=from.begin(); i!=from.end(); i++)
+ {
+ Object * obj = (Object *)(*i);
+ Object * newObject = CopyObject(obj);
+ to.push_back(newObject);
+ }
+}
+
+
+//
+// Create a copy of the passed in object.
+//
+Object * CopyObject(Object * obj)
+{
+ Object * newObject = NULL;
+
+ switch (obj->type)
+ {
+ case OTLine:
+ newObject = (Object *)new Line();
+ memcpy(newObject, obj, sizeof(Line));
+ break;
+ case OTCircle:
+ newObject = (Object *)new Circle();
+ memcpy(newObject, obj, sizeof(Circle));
+ break;
+ case OTEllipse:
+ newObject = (Object *)new Ellipse();
+ memcpy(newObject, obj, sizeof(Ellipse));
+ break;
+ case OTArc:
+ newObject = (Object *)new Arc();
+ memcpy(newObject, obj, sizeof(Arc));
+ break;
+ case OTDimension:
+ newObject = (Object *)new Dimension();
+ memcpy(newObject, obj, sizeof(Dimension));
+ break;
+#if 0
+ case OTSpline:
+ newObject = (Object *)new Spline();
+ memcpy(newObject, obj, sizeof(Spline));
+ break;
+#endif
+ case OTText:
+ newObject = (Object *)new Text();
+ memcpy(newObject, obj, sizeof(Text));
+ ((Text *)newObject)->s = ((Text *)obj)->s;
+ break;
+ case OTContainer:
+ newObject = (Object *)new Container();
+//this won't work...
+// memcpy(newObject, obj, sizeof(Line));
+ CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects);
+ break;
+ default:
+ break;
+ }
+
+ // Fix objectID
+ if (newObject && (newObject->type != OTContainer))
+ newObject->id = Global::objectID;
+
+ return newObject;
+}
+
+
+void ClearSelected(std::vector<void *> & v)
+{
+ std::vector<void *>::iterator i;
+
+ for(i=v.begin(); i!=v.end(); i++)
+ ((Object *)(*i))->selected = false;
+}
+
+
--- /dev/null
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <vector>
+#include "structs.h"
+
+void CopyObjects(std::vector<void *> & from, std::vector<void *> & to);
+Object * CopyObject(Object * obj);
+void ClearSelected(std::vector<void *> & v);
+
+#endif // __UTILS_H__
+