From: Shamus Hammons Date: Fri, 14 Feb 2014 19:38:28 +0000 (-0600) Subject: Added preliminary (i.e., non-functional) trim tool. Also: X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=architektonas;a=commitdiff_plain;h=31dd33b097661175a86b6799df525972055099fb Added preliminary (i.e., non-functional) trim tool. Also: - Bugfix for incorrect mirrored point in Geomtry::Mirror() - Added miscellaneous missing icons - Added auto-connect to add lines tool - Fixed Dimension object to respond to where the dimension line actually is --- diff --git a/architektonas.pro b/architektonas.pro index edea5ee..eea6798 100644 --- a/architektonas.pro +++ b/architektonas.pro @@ -78,6 +78,7 @@ HEADERS = \ src/rotateaction.h \ src/settingsdialog.h \ src/text.h \ + src/trimaction.h \ src/vector.h SOURCES = \ @@ -112,5 +113,6 @@ SOURCES = \ src/rotateaction.cpp \ src/settingsdialog.cpp \ src/text.cpp \ + src/trimaction.cpp \ src/vector.cpp diff --git a/res/architektonas.qrc b/res/architektonas.qrc index cf1593b..602ddae 100644 --- a/res/architektonas.qrc +++ b/res/architektonas.qrc @@ -15,6 +15,7 @@ rotate-tool.png snap-to-grid-tool.png splash.png + trim-tool.png quit.png zoom-in.png zoom-out.png diff --git a/res/block-import.png b/res/block-import.png new file mode 100644 index 0000000..8648f4f Binary files /dev/null and b/res/block-import.png differ diff --git a/res/layer-add.png b/res/layer-add.png new file mode 100644 index 0000000..40745b5 Binary files /dev/null and b/res/layer-add.png differ diff --git a/res/layer-delete.png b/res/layer-delete.png new file mode 100644 index 0000000..43369c2 Binary files /dev/null and b/res/layer-delete.png differ diff --git a/res/layer-down.png b/res/layer-down.png new file mode 100644 index 0000000..04d9219 Binary files /dev/null and b/res/layer-down.png differ diff --git a/res/layer-edit.png b/res/layer-edit.png new file mode 100644 index 0000000..105cb5d Binary files /dev/null and b/res/layer-edit.png differ diff --git a/res/layer-up.png b/res/layer-up.png new file mode 100644 index 0000000..1891222 Binary files /dev/null and b/res/layer-up.png differ diff --git a/res/trim-tool.png b/res/trim-tool.png new file mode 100644 index 0000000..4f80fbd Binary files /dev/null and b/res/trim-tool.png differ diff --git a/src/applicationwindow.cpp b/src/applicationwindow.cpp index 5261dd1..4f1be35 100644 --- a/src/applicationwindow.cpp +++ b/src/applicationwindow.cpp @@ -45,6 +45,7 @@ #include "painter.h" #include "rotateaction.h" #include "settingsdialog.h" +#include "trimaction.h" // Class variables @@ -267,6 +268,13 @@ void ApplicationWindow::MirrorTool(void) } +void ApplicationWindow::TrimTool(void) +{ + ClearUIToolStatesExcept(trimAct); + SetInternalToolStates(); +} + + void ApplicationWindow::AddLineTool(void) { ClearUIToolStatesExcept(addLineAct); @@ -397,6 +405,9 @@ void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception) if (exception != mirrorAct) mirrorAct->setChecked(false); + + if (exception != trimAct) + trimAct->setChecked(false); } @@ -421,6 +432,7 @@ void ApplicationWindow::SetInternalToolStates(void) drawing->SetToolActive(addDimensionAct->isChecked() ? new DrawDimensionAction() : NULL); drawing->SetToolActive(mirrorAct->isChecked() ? new MirrorAction() : NULL); drawing->SetToolActive(rotateAct->isChecked() ? new RotateAction() : NULL); + drawing->SetToolActive(trimAct->isChecked() ? new TrimAction() : NULL); if (drawing->toolAction) Object::ignoreClicks = true; @@ -700,6 +712,9 @@ void ApplicationWindow::CreateActions(void) mirrorAct = CreateAction(tr("&Mirror"), tr("Mirror"), tr("Mirror selected objects around a line."), QIcon(":/res/mirror-tool.png"), QKeySequence("m,i"), true); connect(mirrorAct, SIGNAL(triggered()), this, SLOT(MirrorTool())); + trimAct = CreateAction(tr("&Trim"), tr("Trim"), tr("Trim extraneous lines from selected objects."), QIcon(":/res/trim-tool.png"), QKeySequence("t,r"), true); + connect(trimAct, SIGNAL(triggered()), this, SLOT(TrimTool())); + //Hm. I think we'll have to have separate logic to do the "Radio Group Toolbar" thing... // Yup, in order to turn them off, we'd have to have an "OFF" toolbar button. Ick. @@ -770,6 +785,7 @@ void ApplicationWindow::CreateMenus(void) menu->addAction(fixLengthAct); menu->addAction(rotateAct); menu->addAction(mirrorAct); + menu->addAction(trimAct); menu->addAction(connectAct); menu->addAction(disconnectAct); menu->addSeparator(); @@ -818,6 +834,7 @@ void ApplicationWindow::CreateToolbars(void) toolbar->addAction(fixLengthAct); toolbar->addAction(rotateAct); toolbar->addAction(mirrorAct); + toolbar->addAction(trimAct); toolbar->addAction(deleteAct); toolbar->addAction(connectAct); toolbar->addAction(disconnectAct); diff --git a/src/applicationwindow.h b/src/applicationwindow.h index cf25247..089ab8f 100644 --- a/src/applicationwindow.h +++ b/src/applicationwindow.h @@ -34,6 +34,7 @@ class ApplicationWindow: public QMainWindow void DimensionTool(void); void RotateTool(void); void MirrorTool(void); + void TrimTool(void); void AddLineTool(void); void AddCircleTool(void); void AddArcTool(void); @@ -94,6 +95,7 @@ class ApplicationWindow: public QMainWindow QAction * connectAct; QAction * disconnectAct; QAction * mirrorAct; + QAction * trimAct; // Class variables public: diff --git a/src/circle.cpp b/src/circle.cpp index d8a2e5d..88cdaa7 100644 --- a/src/circle.cpp +++ b/src/circle.cpp @@ -253,7 +253,6 @@ same reference number. /*virtual*/ void Circle::Mirror(Point p1, Point p2) { Point c1 = Geometry::MirrorPointAroundLine(position, p1, p2); -// return new Circle(c1, radius); position = c1; } diff --git a/src/dimension.cpp b/src/dimension.cpp index 7c4488d..01d7ec3 100644 --- a/src/dimension.cpp +++ b/src/dimension.cpp @@ -73,33 +73,33 @@ all objects move as a unified whole. double angle = v.Angle(); Vector orthogonal = Vector::Normal(position, endpoint); Vector unit = v.Unit(); + linePt1 = position, linePt2 = endpoint; // Horizontally aligned display #if 1 - Vector pos = position, endp = endpoint, ortho; - double y1, y2; + Vector /*pos = position, endp = endpoint,*/ ortho; + double y1; if ((angle < PI_OVER_2) || (angle > PI3_OVER_2)) { - y1 = (pos.y > endp.y ? pos.y : endp.y); - y2 = (pos.y > endp.y ? endp.y : pos.y); + y1 = (position.y > endpoint.y ? position.y : endpoint.y); ortho = Vector(0, 1.0); angle = 0; } else { - y1 = (pos.y > endp.y ? endp.y : pos.y); - y2 = (pos.y > endp.y ? pos.y : endp.y); + y1 = (position.y > endpoint.y ? endpoint.y : position.y); ortho = Vector(0, -1.0); angle = PI; } - pos.y = endp.y = y1; - unit = Vector(pos, endp).Unit(); - Point p1 = pos + (ortho * 10.0 * size); - Point p2 = endp + (ortho * 10.0 * size); - Point p3 = pos + (ortho * 16.0 * size); - Point p4 = endp + (ortho * 16.0 * size); +// pos.y = endp.y = y1; + linePt1.y = linePt2.y = y1; + unit = Vector(linePt1, linePt2).Unit(); + Point p1 = linePt1 + (ortho * 10.0 * size); + Point p2 = linePt2 + (ortho * 10.0 * size); + Point p3 = linePt1 + (ortho * 16.0 * size); + Point p4 = linePt2 + (ortho * 16.0 * size); Point p5 = position + (ortho * 4.0 * size); Point p6 = endpoint + (ortho * 4.0 * size); #endif @@ -124,7 +124,8 @@ I believe they are pixels. // Calculate whether or not the arrowheads are too crowded to put inside // the extension lines. 9.0 is the length of the arrowhead. // double t = Geometry::ParameterOfLineAndPoint(position, endpoint, endpoint - (unit * 9.0 * size)); - double t = Geometry::ParameterOfLineAndPoint(pos, endp, endp - (unit * 9.0 * size)); +// double t = Geometry::ParameterOfLineAndPoint(pos, endp, endp - (unit * 9.0 * size)); + double t = Geometry::ParameterOfLineAndPoint(linePt1, linePt2, linePt2 - (unit * 9.0 * size)); //printf("Dimension::Draw(): t = %lf\n", t); // On the screen, it's acting like this is actually 58%... @@ -326,8 +327,13 @@ about keeping track of old states... { Vector orthogonal = Vector::Normal(position, endpoint); // Get our line parallel to our points +#if 0 Point p1 = position + (orthogonal * 10.0 * size); Point p2 = endpoint + (orthogonal * 10.0 * size); +#else + Point p1 = linePt1 + (orthogonal * 10.0 * size); + Point p2 = linePt2 + (orthogonal * 10.0 * size); +#endif Point p3(p1, point); hitPoint1 = hitPoint2 = hitLine = hitFlipSwitch = false; diff --git a/src/dimension.h b/src/dimension.h index c3709b6..9a9b3d4 100644 --- a/src/dimension.h +++ b/src/dimension.h @@ -1,7 +1,6 @@ #ifndef __DIMENSION_H__ #define __DIMENSION_H__ -#include "connection.h" #include "object.h" class Line; @@ -38,6 +37,7 @@ class Dimension: public Object Vector endpoint; // Starting point is Object::position Vector oldPoint; // Used for dragging Point oldEndpoint; + Point linePt1, linePt2; // Used for testing dimension line hits private: bool dragging; diff --git a/src/drawlineaction.cpp b/src/drawlineaction.cpp index 27b9513..5490e98 100644 --- a/src/drawlineaction.cpp +++ b/src/drawlineaction.cpp @@ -80,12 +80,22 @@ DrawLineAction::~DrawLineAction() { p2 = p1; state = NEXT_POINT; + line = NULL; } else if (state == NEXT_POINT) { + Line * oldLine = line; // We create the new object here, and then pass it off to the // DrawingView which stuffs it into the document. line = new Line(p1, p2); + + // Connect Lines by default + if (oldLine) + { + oldLine->Connect(line, 0); + line->Connect(oldLine, 1.0); + } + // We don't need no stinkin' sentinels, when we have signals & slots! emit ObjectReady(line); @@ -103,7 +113,7 @@ DrawLineAction::~DrawLineAction() p1Save = p1; p1 = p2; state = FIRST_POINT; - emit(NeedRefresh()); + emit NeedRefresh(); } } diff --git a/src/geometry.cpp b/src/geometry.cpp index cfb0511..41928aa 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -62,15 +62,15 @@ double Geometry::ParameterOfLineAndPoint(Point tail, Point head, Point point) } -Point Geometry::MirrorPointAroundLine(Point point, Point p1, Point p2) +Point Geometry::MirrorPointAroundLine(Point point, Point tail, Point head) { // Get the vector of the intersection of the line and the normal on the // line to the point in question. - double t = ParameterOfLineAndPoint(p1, p2, point); - Vector v = Vector(p1, p2) * t; + double t = ParameterOfLineAndPoint(tail, head, point); + Vector v = Vector(tail, head) * t; - // Get the point normal to point to the line passed in (p2 is the tail) - Point normalOnLine = p2 + v; + // Get the point normal to point to the line passed in + Point normalOnLine = tail + v; // Make our mirrored vector (head - tail) Vector mirror = -(point - normalOnLine); diff --git a/src/trimaction.cpp b/src/trimaction.cpp new file mode 100644 index 0000000..ea8e9eb --- /dev/null +++ b/src/trimaction.cpp @@ -0,0 +1,161 @@ +// TrimAction.cpp: Action class for mirroring selected objects +// +// Part of the Architektonas Project +// (C) 2011 Underground Software +// See the README and GPLv3 files for licensing and warranty information +// +// JLH = James Hammons +// +// WHO WHEN WHAT +// --- ---------- ------------------------------------------------------------ +// JLH 08/27/2011 Created this file +// + +#include "trimaction.h" +#include "applicationwindow.h" +#include "container.h" +#include "drawingview.h" +#include "line.h" +#include "mathconstants.h" +#include "painter.h" + + +enum { FIRST_POINT, NEXT_POINT }; + + +TrimAction::TrimAction(): state(FIRST_POINT), line(NULL), + shiftWasPressedOnNextPoint(false), ctrlWasPressed(false), + mirror(new Container(Vector())) +{ + ApplicationWindow::drawing->document.CopySelectedContentsTo(mirror); + mirror->Save(); +} + + +TrimAction::~TrimAction() +{ +} + + +/*virtual*/ void TrimAction::Draw(Painter * painter) +{ + painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine)); + + if (state == FIRST_POINT) + { + painter->DrawHandle(p1); + } + else + { + Vector reflectedP2 = -(p2 - p1); + Point newP2 = p1 + reflectedP2; + painter->DrawLine(newP2, p2); + painter->DrawHandle(p1); + + double absAngle = (Vector(p2 - p1).Angle()) * RADIANS_TO_DEGREES; + + // Keep the angle between 0 and 180 degrees + if (absAngle > 180.0) + absAngle -= 180.0; + + QString text = QChar(0x2221) + QObject::tr(": %1"); + text = text.arg(absAngle); + + if (ctrlWasPressed) + text += " (Copy)"; + + painter->DrawInformativeText(text); + + // Draw the mirror only if there's been a line to mirror around + if (p1 != p2) + mirror->Draw(painter); + } +} + + +/*virtual*/ void TrimAction::MouseDown(Vector point) +{ + // Clear our override... + shiftWasPressedOnNextPoint = false; + + if (state == FIRST_POINT) + p1 = point; + else + p2 = point; +} + + +/*virtual*/ void TrimAction::MouseMoved(Vector point) +{ + if (state == FIRST_POINT) + p1 = point; + else + { + p2 = point; + mirror->Restore(); + mirror->Mirror(p1, p2); + } +} + + +/*virtual*/ void TrimAction::MouseReleased(void) +{ + if (state == FIRST_POINT) + { + p2 = p1; + state = NEXT_POINT; + } + else if (state == NEXT_POINT) + { + if (!ctrlWasPressed) + { + state = FIRST_POINT; + ApplicationWindow::drawing->document.MirrorSelected(p1, p2); + + mirror->Clear(); + ApplicationWindow::drawing->document.CopySelectedContentsTo(mirror); + mirror->Save(); + } + else + { + mirror->CopyContentsTo(&(ApplicationWindow::drawing->document)); + } + } +} + + +/*virtual*/ void TrimAction::KeyDown(int key) +{ + if ((key == Qt::Key_Shift) && (state == NEXT_POINT)) + { + shiftWasPressedOnNextPoint = true; + p1Save = p1; + p1 = p2; + state = FIRST_POINT; + emit NeedRefresh(); + } + else if (key == Qt::Key_Control) + { + ctrlWasPressed = true; + emit NeedRefresh(); + } +} + + +/*virtual*/ void TrimAction::KeyReleased(int key) +{ + if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint) + { + shiftWasPressedOnNextPoint = false; + p2 = p1; + p1 = p1Save; + state = NEXT_POINT; + emit NeedRefresh(); + } + else if (key == Qt::Key_Control) + { + ctrlWasPressed = false; + emit NeedRefresh(); + } +} + diff --git a/src/trimaction.h b/src/trimaction.h new file mode 100644 index 0000000..02720de --- /dev/null +++ b/src/trimaction.h @@ -0,0 +1,32 @@ +#ifndef __TRIMACTION_H__ +#define __TRIMACTION_H__ + +#include "action.h" + +class Container; +class Line; + +class TrimAction: public Action +{ + public: + TrimAction(); + ~TrimAction(); + + 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; + Line * line; + Vector p1, p2, p1Save; + bool shiftWasPressedOnNextPoint; + bool ctrlWasPressed; + Container * mirror; +}; + +#endif // __TRIMACTION_H__ +