]> Shamusworld >> Repos - ttedit/blobdiff - src/editwindow.cpp
Converted from Qt4 to Qt5.
[ttedit] / src / editwindow.cpp
index 97546ef5c3a54ea151eed268410e6c4a2be940e2..429943d2a7c707cfbcdc08cff1f0e894ce1319f9 100755 (executable)
 #define DEBUGTP                                // Toolpalette debugging...
 
 #include "editwindow.h"
-//#include <QtGui>
-#include "graphicprimitives.h"
-#include "debug.h"
-#include "vector.h"
 #include "charwindow.h"
+#include "debug.h"
+#include "graphicprimitives.h"
+#include "mainwindow.h"
 #include "ttedit.h"
+#include "vector.h"
+
 
 EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent),
        scale(1.0), offsetX(-10), offsetY(-10), tool(TOOLSelect),
        ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1), oldPtNextHighlight(-1),
-       polyFirstPoint(true)
+       polyFirstPoint(true), showRotationCenter(false), haveZeroPoint(false)
 {
        setBackgroundRole(QPalette::Base);
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -55,30 +56,36 @@ EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent),
        setMouseTracking(true);
 }
 
+
 QSize EditWindow::minimumSizeHint() const
 {
        return QSize(50, 50);
 }
 
+
 QSize EditWindow::sizeHint() const
 {
        return QSize(400, 400);
 }
 
+
 void EditWindow::CreateCursors(void)
 {
-       int hotx[8] = {  1,  1, 11, 15,  1,  1,  1,  1 };
-       int hoty[8] = {  1,  1, 11, 13,  1,  1,  1,  1 };
+       int hotx[11] = {  1,  1, 11, 15,  1,  1,  1,  1,  1,  1,  1 };
+       int hoty[11] = {  1,  1, 11, 13,  1,  1,  1,  1,  1,  1,  1 };
+       char cursorName[11][48] = { "select", "select-poly", "scroll", "zoom", "add-point",
+               "add-poly", "del-point", "del-poly", "rotate", "rotate", "select" };
 
-       for(int i=0; i<8; i++)
+       for(int i=0; i<11; i++)
        {
                QString s;
-               s.sprintf(":/res/cursor%u.png", i+1);
+               s.sprintf(":/res/cursor-%s.png", cursorName[i]);
                QPixmap pmTmp(s);
                cur[i] = QCursor(pmTmp, hotx[i], hoty[i]);
        }
 }
 
+
 QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event)
 {
        QSize winSize = size();
@@ -88,6 +95,7 @@ QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event)
        return QPoint(offsetX + event->x(), offsetY + (winSize.height() - event->y()));
 }
 
+
 QPoint EditWindow::GetAdjustedClientPosition(int x, int y)
 {
        QSize winSize = size();
@@ -96,6 +104,7 @@ QPoint EditWindow::GetAdjustedClientPosition(int x, int y)
        return QPoint(-offsetX + x, (winSize.height() - (-offsetY + y)) * +1.0);
 }
 
+
 /*
 TODO:
  o  Different colors for polys on selected points
@@ -106,19 +115,11 @@ TODO:
 void EditWindow::paintEvent(QPaintEvent * /*event*/)
 {
        QPainter p(this);
-//hm, causes lockup
-//     p.setRenderHint(QPainter::Antialiasing);
-//Doesn't do crap!
-//dc.SetBackground(*wxWHITE_BRUSH);
-
-// Due to the screwiness of wxWidgets coord system, the origin is ALWAYS
-// the upper left corner--regardless of axis orientation, etc...
-//     int width, height;
-//     dc.GetSize(&width, &height);
+//hm, causes lockup (or does it???)
+       p.setRenderHint(QPainter::Antialiasing);
+
        QSize winSize = size();
 
-//     dc.SetDeviceOrigin(-offsetX, height - (-offsetY));
-//     dc.SetAxisOrientation(true, true);
        p.translate(QPoint(-offsetX, winSize.height() - (-offsetY)));
        p.scale(1.0, -1.0);
 
@@ -129,24 +130,28 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
 // Instead, we have to scale EVERYTHING by hand. Crap!
 // It's not *that* bad, but not as convenient either...
 
-//     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0xFF), 1, wxDOT)));
-////   dc.DrawLine(0, 0, 10, 10);
        p.setPen(QPen(Qt::blue, 1.0, Qt::DotLine));
 
-    // Draw coordinate axes
+       // Draw coordinate axes
 
-//     dc.CrossHair(0, 0);
        p.drawLine(0, -16384, 0, 16384);
        p.drawLine(-16384, 0, 16384, 0);
 
-    // Draw points
+       // Draw rotation center (if active)
+
+       if (showRotationCenter)
+       {
+               p.setPen(QPen(Qt::red, 2.0, Qt::SolidLine));
+               p.drawLine(rotationCenter.x() + 7, rotationCenter.y(), rotationCenter.x() - 7, rotationCenter.y());
+               p.drawLine(rotationCenter.x(), rotationCenter.y() + 7, rotationCenter.x(), rotationCenter.y() - 7);
+       }
+
+       // Draw points
 
        for(int i=0; i<pts.GetNumPoints(); i++)
        {
                if (i == ptHighlight)
                {
-//                     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));
-////                   SelectObject(hdc, hRedPen1);
                        p.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
@@ -162,8 +167,6 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
                }
                else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt)
                {
-//                     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0xAF, 0x00), 1, wxSOLID)));
-////                   SelectObject(hdc, hGreenPen1);
                        p.setPen(QPen(Qt::green, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
@@ -179,8 +182,6 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
                }
                else
                {
-//                     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));
-////                   SelectObject(hdc, hBlackPen1);
                        p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
@@ -191,75 +192,128 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
 
                if (tool == TOOLDelPt && i == ptHighlight)
                {
-#if 0
-                       dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID)));
-//                     SelectObject(hdc, hRedPen1);
-//                     MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL);
-//                     LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5);
-//                     LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness!
-//                     MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL);
-//                     LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5);
-//                     LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!!
-#endif
                        p.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
                        p.drawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);
                        p.drawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);
                }
        }
 
-////           SelectObject(hdc, hBlackPen1);
-//     dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID)));
-       p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
-
        // Draw curve formed by points
 
-       for(int poly=0; poly<pts.GetNumPolys(); poly++)
+       p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+       DrawGlyph(p, pts);
+
+       if (haveZeroPoint)
        {
-               if (pts.GetNumPoints(poly) > 2)
+               // Rotation code
+               GlyphPoints rotated = pts;
+
+               if (tool == TOOLRotate)
+                       rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+               else if (tool == TOOLRotatePoly)
                {
-                       // Initial move...
-                       // If it's not on curve, then move to it, otherwise move to last point...
+                       uint16 poly = rotated.GetPolyForPointNumber(ptHighlight);
+                       rotated.RotatePolyAroundCentroid(poly, rotationAngle);
+               }
 
-                       int x, y;
+               p.setPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
+               DrawGlyph(p, rotated);
+       }
+}
 
-                       if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1))
-                               x = (int)pts.GetX(poly, pts.GetNumPoints(poly) - 1), y = (int)pts.GetY(poly, pts.GetNumPoints(poly) - 1);
-                       else
-                               x = (int)pts.GetX(poly, 0), y = (int)pts.GetY(poly, 0);
 
-                       for(int i=0; i<pts.GetNumPoints(poly); i++)
-                       {
-                               if (pts.GetOnCurve(poly, i))
-//                                     LineTo(hdc, pts.GetX(poly, i), pts.GetY(poly, i));
-                               {
-                                       p.drawLine(x, y, pts.GetX(poly, i), pts.GetY(poly, i));
-                                       x = (int)pts.GetX(poly, i), y = (int)pts.GetY(poly, i);
-                               }
-                               else
-                               {
-                                       uint32 prev = pts.GetPrev(poly, i), next = pts.GetNext(poly, i);
-                                       float px = pts.GetX(poly, prev), py = pts.GetY(poly, prev),
-                                               nx = pts.GetX(poly, next), ny = pts.GetY(poly, next);
-
-                                       if (!pts.GetOnCurve(poly, prev))
-                                               px = (px + pts.GetX(poly, i)) / 2.0f,
-                                               py = (py + pts.GetY(poly, i)) / 2.0f;
+void EditWindow::DrawGlyph(QPainter & p, GlyphPoints & glyph)
+{
+       for(int poly=0; poly<glyph.GetNumPolys(); poly++)
+       {
+               if (glyph.GetNumPoints(poly) < 3)
+                       continue;
 
-                                       if (!pts.GetOnCurve(poly, next))
-                                               nx = (nx + pts.GetX(poly, i)) / 2.0f,
-                                               ny = (ny + pts.GetY(poly, i)) / 2.0f;
+               // Initial move: If our start point is on curve, then go to it. Otherwise,
+               // check previous point. If it's on curve, go to it otherwise go the
+               // midpoint between start point and previous (since it's between two curve
+               // control points).
+               IPoint pt = (glyph.GetOnCurve(poly, 0)
+                       ? glyph.GetPoint(poly, 0) : (glyph.GetPrevOnCurve(poly, 0)
+                               ? glyph.GetPrevPoint(poly, 0) : glyph.GetMidpointToPrev(poly, 0)));
 
-                                       Bezier(p, point(px, py), point(pts.GetX(poly, i), pts.GetY(poly, i)), point(nx, ny));
-                                       x = (int)nx, y = (int)ny;
+// Need to add separate color handling here for polys that are being manipulated...
 
-                                       if (pts.GetOnCurve(poly, next))
-                                               i++;                                    // Following point is on curve, so move past it
-                               }
+               for(int i=0; i<glyph.GetNumPoints(poly); i++)
+               {
+                       // If this point and then next are both on curve, we have a line...
+                       if (glyph.GetOnCurve(poly, i) && glyph.GetNextOnCurve(poly, i))
+                       {
+                               IPoint pt2 = glyph.GetNextPoint(poly, i);
+                               p.drawLine(pt.x, pt.y, pt2.x, pt2.y);
+                               pt = pt2;
                        }
+                       else
+                       {
+                               // Skip point if it's on curve (start of curve--it's already
+                               // been plotted so we don't need to handle it...)
+                               if (glyph.GetOnCurve(poly, i))
+                                       continue;
+
+                               // We are now guaranteed that we are sitting on a curve control point
+                               // (off curve). Figure the extent of the curve: If the following is a
+                               // curve control point, then use the midpoint to it otherwise go to
+                               // the next point since it's on curve.
+                               IPoint pt2 = (glyph.GetNextOnCurve(poly, i)
+                                       ? glyph.GetNextPoint(poly, i) : glyph.GetMidpointToNext(poly, i));
+
+                               Bezier(p, pt, glyph.GetPoint(poly, i), pt2);
+                               pt = pt2;
+                       }
+               }
+       }
+}
+
+
+void EditWindow::DrawGlyphPoly(QPainter & p, GlyphPoints & glyph, uint16 poly)
+{
+       // Sanity check
+       if (glyph.GetNumPoints(poly) < 3)
+               return;
+
+       // Initial move: If our start point is on curve, then go to it. Otherwise,
+       // check previous point. If it's on curve, go to it otherwise go the
+       // midpoint between start point and previous (since it's between two curve
+       // control points).
+       IPoint pt = (glyph.GetOnCurve(poly, 0)
+               ? glyph.GetPoint(poly, 0) : (glyph.GetPrevOnCurve(poly, 0)
+                       ? glyph.GetPrevPoint(poly, 0) : glyph.GetMidpointToPrev(poly, 0)));
+
+       for(int i=0; i<glyph.GetNumPoints(poly); i++)
+       {
+               // If this point and then next are both on curve, we have a line...
+               if (glyph.GetOnCurve(poly, i) && glyph.GetNextOnCurve(poly, i))
+               {
+                       IPoint pt2 = glyph.GetNextPoint(poly, i);
+                       p.drawLine(pt.x, pt.y, pt2.x, pt2.y);
+                       pt = pt2;
+               }
+               else
+               {
+                       // Skip point if it's on curve (start of curve--it's already
+                       // been plotted so we don't need to handle it...)
+                       if (glyph.GetOnCurve(poly, i))
+                               continue;
+
+                       // We are now guaranteed that we are sitting on a curve control point
+                       // (off curve). Figure the extent of the curve: If the following is a
+                       // curve control point, then use the midpoint to it otherwise go to
+                       // the next point since it's on curve.
+                       IPoint pt2 = (glyph.GetNextOnCurve(poly, i)
+                               ? glyph.GetNextPoint(poly, i) : glyph.GetMidpointToNext(poly, i));
+
+                       Bezier(p, pt, glyph.GetPoint(poly, i), pt2);
+                       pt = pt2;
                }
        }
 }
 
+
 void EditWindow::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::RightButton)
@@ -279,13 +333,25 @@ void EditWindow::mousePressEvent(QMouseEvent * event)
 ;//meh                 CaptureMouse();                                         // Make sure we capture the mouse when in scroll/zoom mode
                else if (tool == TOOLAddPt)             // "Add Point" tool
                {
-                       if (pts.GetNumPoints() > 0)
+                       QPoint pt = GetAdjustedMousePosition(event);
+                       IPoint pointToAdd(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+
+                       if (pts.GetNumPoints() < 2)
                        {
-                               QPoint pt = GetAdjustedMousePosition(event);
-                               pts.InsertPoint(pts.GetNext(ptHighlight), pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+//                             pts += IPoint(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+                               pts += pointToAdd;
+                               ptHighlight = pts.GetNumPoints() - 1;
+                       }
+                       else
+                       {
+//                             QPoint pt = GetAdjustedMousePosition(event);
+//                             pts.InsertPoint(pts.GetNext(ptHighlight), pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+                               pts.InsertPoint(pts.GetNext(ptHighlight), pointToAdd);
                                ptHighlight = ptNextHighlight;
-                               update();
+//                             update();
                        }
+
+                       update();
                }
                else if (tool == TOOLAddPoly)   // "Add Poly" tool
                {
@@ -336,11 +402,43 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                                update();
                        }
                }
+               else if (tool == TOOLRotate)
+               {
+                       // I think what's needed here is to keep the initial mouse click,
+                       // paint the rotation center, then use the 1st mouse move event to establish
+                       // the rotation "zero line", which becomes the line of reference to all
+                       // subsequent mouse moves.
+                       rotationCenter = GetAdjustedMousePosition(event);
+                       showRotationCenter = true;
+                       haveZeroPoint = false;
+                       rotationAngle = 0;
+                       update();
+               }
+               else if (tool == TOOLRotatePoly)
+               {
+                       IPoint centroid = pts.GetPolyCentroid(pts.GetPolyForPointNumber(ptHighlight));
+                       rotationCenter = QPoint(centroid.x, centroid.y);
+                       showRotationCenter = true;
+                       pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       QCursor::setPos(mapToGlobal(pt));
+                       rotationZeroPoint = QPoint(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       haveZeroPoint = true;
+                       rotationAngle = 0;
+                       update();
+               }
+               else if (tool == TOOLFlipWinding)
+               {
+                       pts.InvertPolyDrawSequence(pts.GetPolyForPointNumber(ptHighlight));
+                       pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       QCursor::setPos(mapToGlobal(pt));
+                       update();
+               }
        }
 
        event->accept();
 }
 
+
 void EditWindow::mouseMoveEvent(QMouseEvent * event)
 {
        if (event->buttons() == Qt::RightButton)
@@ -368,63 +466,64 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        }
        else if (event->buttons() == Qt::LeftButton)
        {
-#if 0
-                       if (tool == TOOLScroll)
-                       {
-                           // Extract current point from lParam/calc offset from previous point
-
-                               pt = e.GetPosition();
-                               ptOffset.x = pt.x - ptPrevious.x,
-                               ptOffset.y = pt.y - ptPrevious.y;
-
-                               // NOTE: OffsetViewportOrg operates in DEVICE UNITS...
-
-//Seems there's no equivalent for this in wxWidgets...!
-//!!! FIX !!!
-//                             hdc = GetDC(hWnd);
-//                             OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL);
-//                             ReleaseDC(hWnd, hdc);
+               if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)
+               {
+                       // Bail out if we have the select tool and no points yet...
+                       if (tool == TOOLSelect && pts.GetNumPoints() == 0)
+                               return;
 
-// this shows that it works, so the logic above must be faulty...
-// And it is. It should convert the coords first, then do the subtraction to figure the offset...
-// Above: DONE
-// Then multiply it by the scaling factor. Whee!
-                               // This looks wacky because we're using screen coords for the offset...
-                               // Otherwise, we would subtract both offsets!
-                               offsetX -= ptOffset.x, offsetY += ptOffset.y;
-                               Refresh();
+                       QPoint pt2 = GetAdjustedMousePosition(event);
+                       pts.SetXY(ptHighlight, pt2.x(), pt2.y());
+                       update();
+               }
+               else if (tool == TOOLPolySelect)
+               {
+                       if (pts.GetNumPoints() > 0)
+                       {
+                               QPoint pt2 = GetAdjustedMousePosition(event);
+                               // Should also set onCurve here as well, depending on keystate
+//Or should we?
+//Would be nice, but we'd need to trap the keyPressEvent() as well, otherwise pressing/releasing
+//the hotkey would show no change until the user moved their mouse.
+                               pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight));
+                               update();
                        }
-                       else
-#endif
-                       if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)
+               }
+               else if (tool == TOOLRotate || tool == TOOLRotatePoly)
+               {
+                       if (pts.GetNumPoints() > 0)
                        {
-                               if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch.
+                               if (!haveZeroPoint)
                                {
-//temporary, for testing. BTW, Select drag bug is here...!
-#if 1
-                                       QPoint pt2 = GetAdjustedMousePosition(event);
-                                       pts.SetXY(ptHighlight, pt2.x(), pt2.y());
-                                       update();
-#endif
+                                       rotationZeroPoint = GetAdjustedMousePosition(event);
+                                       haveZeroPoint = true;
                                }
-                       }
-                       else if (tool == TOOLPolySelect)
-                       {
-                               if (pts.GetNumPoints() > 0)
+                               else
                                {
-                                       QPoint pt2 = GetAdjustedMousePosition(event);
-                                       // Should also set onCurve here as well, depending on keystate
-//Or should we?
-                                       pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight));
-                                       update();
+                                       // Figure out the angle between the "zero" vector and the current one,
+                                       // then rotate all points relative to the "zero" vector (done by paint())
+                                       QPoint currentPoint = GetAdjustedMousePosition(event);
+                                       Vector v1(rotationZeroPoint.x(), rotationZeroPoint.y(), 0,
+                                               rotationCenter.x(), rotationCenter.y(), 0);
+                                       Vector v2(currentPoint.x(), currentPoint.y(), 0,
+                                               rotationCenter.x(), rotationCenter.y(), 0);
+//                                     rotationAngle = v1.Angle(v2);
+                                       rotationAngle = v2.Angle(v1);
+
+                                       QString s;
+                                       s.sprintf("%.3f degrees", rotationAngle * 180.0 / 3.14159265358979323);
+                                       ((TTEdit *)qApp)->mainWindow->statusBar()->showMessage(s);
                                }
+
+                               update();
                        }
+               }
        }
        else if (event->buttons() == Qt::NoButton)
        {
                // Moving, not dragging...
                if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt
-                       || tool == TOOLPolySelect)// || tool == TOOLAddPoly)
+                       || tool == TOOLPolySelect || tool == TOOLRotatePoly || tool == TOOLFlipWinding)
                {
                        QPoint pt2 = GetAdjustedMousePosition(event);
                        double closest = 1.0e+99;
@@ -463,20 +562,20 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                                        int32 p1x = pts.GetX(i), p1y = pts.GetY(i),
                                                p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));
 
-                                       vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x(), pt2.y(), 0, p1x, p1y, 0),
+                                       Vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x(), pt2.y(), 0, p1x, p1y, 0),
                                                v2(pt2.x(), pt2.y(), 0, p2x, p2y, 0);
-                                       double pp = ls.dot(v1) / ls.length(), dist;
+                                       double pp = ls.Dot(v1) / ls.Magnitude(), dist;
 // Geometric interpretation:
 // pp is the paremeterized point on the vector ls where the perpendicular intersects ls.
 // If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls,
 // then the perpendicular lies beyond the 2nd endpoint.
 
                                        if (pp < 0.0)
-                                               dist = v1.length();
-                                       else if (pp > ls.length())
-                                               dist = v2.length();
+                                               dist = v1.Magnitude();
+                                       else if (pp > ls.Magnitude())
+                                               dist = v2.Magnitude();
                                        else                                    // distance = ?Det?(ls, v1) / |ls|
-                                               dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.length());
+                                               dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.Magnitude());
 
 //The answer to the above looks like it might be found here:
 //
@@ -491,8 +590,10 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
 //ex ey 1
 //px py 1
 //
-//(???) By translating the start point to the origin, this can be rewritten as:
+//By translating the start point to the origin, this can be rewritten as:
 //By subtracting row 1 from all rows, you get the following:
+//[because sx = sy = 0. you could leave out the -sx/y terms below. because we subtracted
+// row 1 from all rows (including row 1) row 1 turns out to be zero. duh!]
 //
 //0         0         0
 //(ex - sx) (ey - sy) 0
@@ -518,6 +619,7 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        event->accept();
 }
 
+
 void EditWindow::mouseReleaseEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::RightButton)
@@ -548,12 +650,41 @@ void EditWindow::mouseReleaseEvent(QMouseEvent * event)
        }
        else if (event->button() == Qt::LeftButton)
        {
+               if (showRotationCenter)
+               {
+                       showRotationCenter = false;
+                       haveZeroPoint = false;
+
+                       if (tool == TOOLRotate)
+                               pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+                       else
+                       {
+                               uint16 poly = pts.GetPolyForPointNumber(ptHighlight);
+                               pts.RotatePolyAroundCentroid(poly, rotationAngle);
+                       }
+
+                       update();
+                       ((TTEdit *)qApp)->mainWindow->statusBar()->showMessage("");
+               }
+
 //             if (tool == TOOLScroll || tool == TOOLZoom)
 //                     ReleaseMouse();
 //this is prolly too much
                ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&pts);
                ((TTEdit *)qApp)->charWnd->update();
+
        }
 
        event->accept();
 }
+
+
+void EditWindow::keyPressEvent(QKeyEvent * event)
+{
+}
+
+
+void EditWindow::keyReleaseEvent(QKeyEvent * event)
+{
+}
+