]> Shamusworld >> Repos - ttedit/blobdiff - src/editwindow.cpp
Added preview window to file loading dialog. :-)
[ttedit] / src / editwindow.cpp
old mode 100755 (executable)
new mode 100644 (file)
index ef3d585..dac63c2
@@ -6,7 +6,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  08/28/2008  Created this file
 // JLH  09/02/2008  Separated scrolling from dedicated tool to MMB drag
 // JLH  03/13/2009  Converted from wxWidgets to Qt
 #include "editwindow.h"
 #include "charwindow.h"
 #include "debug.h"
-#include "graphicprimitives.h"
+#include "global.h"
 #include "mainwindow.h"
+#include "mathconstants.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), showRotationCenter(false), haveZeroPoint(false)
+       tool(TOOLSelect), ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1),
+       oldPtNextHighlight(-1), polyFirstPoint(true), showRotationCenter(false),
+       haveZeroPoint(false), selectionInProgress(false)
 {
        setBackgroundRole(QPalette::Base);
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -54,6 +55,7 @@ EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent),
        CreateCursors();
        setCursor(cur[TOOLSelect]);
        setMouseTracking(true);
+       ClearSelection();
 }
 
 
@@ -71,40 +73,20 @@ QSize EditWindow::sizeHint() const
 
 void EditWindow::CreateCursors(void)
 {
-       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" };
+       int hotx[12] = {  1,  1, 1, 15,  1,  1,  1,  1,  1,  1,  1, 11 };
+       int hoty[12] = {  1,  1, 1, 13,  1,  1,  1,  1,  1,  1,  1, 11 };
+       char cursorName[12][48] = { "select", "select-poly", "select-multi", "zoom",
+               "add-point", "add-poly", "del-point", "del-poly", "rotate", "rotate",
+               "select", "scroll" };
 
-       for(int i=0; i<11; i++)
+       for(int i=0; i<12; i++)
        {
-               QString s;
-               s.sprintf(":/res/cursor-%s.png", cursorName[i]);
-               QPixmap pmTmp(s);
+               QPixmap pmTmp(QString(":/res/cursor-%1.png").arg(cursorName[i]));
                cur[i] = QCursor(pmTmp, hotx[i], hoty[i]);
        }
 }
 
 
-QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event)
-{
-       QSize winSize = size();
-       // This is undoing the transform, e.g. going from client coords to local coords.
-       // In essence, the height - y is height + (y * -1), the (y * -1) term doing the
-       // conversion of the y-axis from increasing bottom to top.
-       return QPoint(offsetX + event->x(), offsetY + (winSize.height() - event->y()));
-}
-
-
-QPoint EditWindow::GetAdjustedClientPosition(int x, int y)
-{
-       QSize winSize = size();
-
-       // VOODOO ALERT (ON Y COMPONENT!!!!)
-       return QPoint(-offsetX + x, (winSize.height() - (-offsetY + y)) * +1.0);
-}
-
-
 /*
 TODO:
  o  Different colors for polys on selected points
@@ -114,94 +96,118 @@ TODO:
 */
 void EditWindow::paintEvent(QPaintEvent * /*event*/)
 {
-       QPainter p(this);
-//hm, causes lockup (or does it???)
-       p.setRenderHint(QPainter::Antialiasing);
-
-       QSize winSize = size();
-
-       p.translate(QPoint(-offsetX, winSize.height() - (-offsetY)));
-       p.scale(1.0, -1.0);
-
-// Scrolling can be done by using OffsetViewportOrgEx
-// Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform)
-// you'd use: % = ViewportExt / WindowExt
-// But it makes the window look like crap: fuggetuboutit.
-// Instead, we have to scale EVERYTHING by hand. Crap!
-// It's not *that* bad, but not as convenient either...
+       QPainter qtp(this);
+       Painter painter(&qtp);
+       painter.SetRenderHint(QPainter::Antialiasing);
 
-       p.setPen(QPen(Qt::blue, 1.0, Qt::DotLine));
+       Global::viewportHeight = size().height();
+       Global::screenSize = Vector(size().width(), size().height());
 
        // Draw coordinate axes
 
-       p.drawLine(0, -16384, 0, 16384);
-       p.drawLine(-16384, 0, 16384, 0);
+       painter.SetPen(QPen(Qt::blue, 1.0, Qt::DotLine));
+       painter.DrawLine(0, -16384, 0, 16384);
+       painter.DrawLine(-16384, 0, 16384, 0);
 
        // 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);
+               painter.SetPen(QPen(Qt::red, 2.0, Qt::SolidLine));
+               painter.DrawLine(rotationCenter.x + 7, rotationCenter.y, rotationCenter.x - 7, rotationCenter.y);
+               painter.DrawLine(rotationCenter.x, rotationCenter.y + 7, rotationCenter.x, rotationCenter.y - 7);
        }
 
        // Draw points
 
        for(int i=0; i<pts.GetNumPoints(); i++)
        {
-               if (i == ptHighlight)
+               /*if (tool == TOOLMultiSelect)
                {
-                       p.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
+                       if (selectedPoints[i])
+                       {
+                               qtp.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
+                       }
+                       else
+                       {
+                               qtp.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+                       }
+               }
+               else*/
+               if (((i == ptHighlight) && (tool != TOOLMultiSelect)) || ((tool == TOOLMultiSelect) && selectedPoints[i]))
+               {
+                       painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
                        {
-                               DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 7);
-                               DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 9);
+                               painter.DrawSquareDotN(pts.GetXY(i), 7);
+                               painter.DrawSquareDotN(pts.GetXY(i), 9);
                        }
                        else
                        {
-                               DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 7);
-                               DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 9);
+                               painter.DrawRoundDotN(pts.GetXY(i), 7);
+                               painter.DrawRoundDotN(pts.GetXY(i), 9);
                        }
                }
                else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt)
                {
-                       p.setPen(QPen(Qt::green, 1.0, Qt::SolidLine));
+                       painter.SetPen(QPen(Qt::green, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
                        {
-                               DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 7);
-                               DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 9);
+                               painter.DrawSquareDotN(pts.GetXY(i), 7);
+                               painter.DrawSquareDotN(pts.GetXY(i), 9);
                        }
                        else
                        {
-                               DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 7);
-                               DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 9);
+                               painter.DrawRoundDotN(pts.GetXY(i), 7);
+                               painter.DrawRoundDotN(pts.GetXY(i), 9);
                        }
                }
                else
                {
-                       p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+                       painter.SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
 
+#if 1
                        if (pts.GetOnCurve(i))
-                               DrawSquareDot(p, pts.GetX(i), pts.GetY(i));
+                               painter.DrawSquareDot(pts.GetXY(i));
                        else
-                               DrawRoundDot(p, pts.GetX(i), pts.GetY(i));
+                               painter.DrawRoundDot(pts.GetXY(i));
+#else
+                       (pts.GetOnCurve(i) ? DrawSquareDot(p, pts.GetX(i), pts.GetY(i))
+                               : DrawRoundDot(p, pts.GetX(i), pts.GetY(i)));
+#endif
                }
 
                if (tool == TOOLDelPt && i == ptHighlight)
                {
-                       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);
+                       painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine));
+                       painter.DrawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);
+                       painter.DrawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);
+               }
+       }
+
+       // Draw highlighted point on poly add tool
+       if (tool == TOOLAddPoly)
+       {
+               painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine));
+
+               if (addPointOnCurve)
+               {
+                       painter.DrawSquareDotN(addPoint, 7);
+                       painter.DrawSquareDotN(addPoint, 9);
+               }
+               else
+               {
+                       painter.DrawRoundDotN(addPoint, 7);
+                       painter.DrawRoundDotN(addPoint, 9);
                }
        }
 
        // Draw curve formed by points
 
-       p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
-       DrawGlyph(p, pts);
+       painter.SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+       DrawGlyph(painter, pts);
 
        if (haveZeroPoint)
        {
@@ -209,23 +215,31 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
                GlyphPoints rotated = pts;
 
                if (tool == TOOLRotate)
-                       rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+                       rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x, rotationCenter.y));
                else if (tool == TOOLRotatePoly)
                {
-                       uint16 poly = rotated.GetPolyForPointNumber(ptHighlight);
+                       uint16_t poly = rotated.GetPolyForPointNumber(ptHighlight);
                        rotated.RotatePolyAroundCentroid(poly, rotationAngle);
                }
 
-               p.setPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
-               DrawGlyph(p, rotated);
+               painter.SetPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
+               DrawGlyph(painter, rotated);
+       }
+
+       if (selectionInProgress)
+       {
+               painter.SetPen(QPen(QColor(255, 127, 0, 255)));
+               painter.SetBrush(QBrush(QColor(255, 127, 0, 100)));
+               painter.DrawRect(selection);
        }
 }
 
 
-void EditWindow::DrawGlyph(QPainter & p, GlyphPoints & glyph)
+void EditWindow::DrawGlyph(Painter & p, GlyphPoints & glyph)
 {
        for(int poly=0; poly<glyph.GetNumPolys(); poly++)
        {
+#if 0
                if (glyph.GetNumPoints(poly) < 3)
                        continue;
 
@@ -266,54 +280,86 @@ void EditWindow::DrawGlyph(QPainter & p, GlyphPoints & glyph)
                                pt = pt2;
                        }
                }
+#else
+               DrawGlyphPoly(p, glyph, poly);
+#endif
        }
 }
 
 
-void EditWindow::DrawGlyphPoly(QPainter & p, GlyphPoints & glyph, uint16 poly)
+/*
+So, to make it draw the point the pointer is pointing at, we need to do something. Either patch the GlyphPoints to handle it, or insert the point into the GlyphPoints and delete it if the user changes tools. Either way, need
+to change the color of the line(s) drawn to the point to signal to the user
+that it isn't finalized until they click the button.
+*/
+void EditWindow::DrawGlyphPoly(Painter & p, GlyphPoints & glyph, uint16_t 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)));
+       IPoint p1 = glyph.GetPrevPoint(poly, 0);
+       IPoint p2 = glyph.GetPoint(poly, 0);
+
+       // Inject the new poly point into the current polygon
+       if ((tool == TOOLAddPoly) && (poly == (glyph.GetNumPolys() - 1)))
+       {
+               p1 = IPoint(addPoint.x, addPoint.y, addPointOnCurve);
+       }
 
        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
+               IPoint p3 = glyph.GetNextPoint(poly, i);
+
+               if ((tool == TOOLAddPoly) && (poly == (glyph.GetNumPolys() - 1))
+                       && (i == (glyph.GetNumPoints(poly) - 1)))
                {
-                       // 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;
+                       p3 = IPoint(addPoint.x, addPoint.y, addPointOnCurve);
+                       p.SetPen(QPen(Qt::green, 1.0, Qt::SolidLine));
+                       DrawGlyphSegment(p, p1, p2, p3);
+                       p1 = p2;
+                       p2 = p3;
+                       p3 = glyph.GetNextPoint(poly, i);
                }
+
+               DrawGlyphSegment(p, p1, p2, p3);
+
+               p1 = p2;
+               p2 = p3;
        }
 }
 
 
+//
+// Draw a glyph segment given 3 points
+//
+void EditWindow::DrawGlyphSegment(Painter & p, IPoint p1, IPoint p2, IPoint p3)
+{
+       if (p2.onCurve)
+       {
+               // Skip drawing if the middle point is on curve and the last is off
+               if (p3.onCurve)
+                       p.DrawLine(p2, p3);
+       }
+       else
+       {
+               // The middle point is off curve, and so we need to draw a Bezier curve.
+               // Also, depending on whether or not the previous or follow points are
+               // off curve, we need to draw to the midpoints if so.
+               IPoint mid12 = IPoint((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
+               IPoint mid23 = IPoint((p2.x + p3.x) / 2, (p2.y + p3.y) / 2);
+               p.DrawBezier((p1.onCurve ? p1 : mid12), p2, (p3.onCurve ? p3 : mid23));
+       }
+}
+
+
+void EditWindow::ClearSelection(void)
+{
+       for(int i=0; i<65536; i++)
+               selectedPoints[i] = false;
+}
+
+
 void EditWindow::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::RightButton)
@@ -325,16 +371,28 @@ void EditWindow::mousePressEvent(QMouseEvent * event)
        }
        else if (event->button() == Qt::MidButton)
        {
-               setCursor(cur[2]);                                                      // Scrolling cursor
+               // Scrolling cursor
+               setCursor(cur[11]);
+               ptPrevious = Vector(event->x(), event->y());
+               ptPrevious /= Global::zoom;
        }
        else if (event->button() == Qt::LeftButton)
        {
                if (tool == TOOLScroll || tool == TOOLZoom)
 ;//meh                 CaptureMouse();                                         // Make sure we capture the mouse when in scroll/zoom mode
+               else if (tool == TOOLMultiSelect)
+               {
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                       selectionInProgress = true;
+                       selection.setTopLeft(QPoint(pt.x, pt.y));
+                       selection.setBottomRight(QPoint(pt.x, pt.y));
+               }
                else if (tool == TOOLAddPt)             // "Add Point" tool
                {
-                       QPoint pt = GetAdjustedMousePosition(event);
-                       IPoint pointToAdd(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                       IPoint pointToAdd(pt.x, pt.y, ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
 
                        if (pts.GetNumPoints() < 2)
                        {
@@ -353,6 +411,8 @@ void EditWindow::mousePressEvent(QMouseEvent * event)
 
                        update();
                }
+// Moved to mouse up routine, so we can slide the point around
+#if 0
                else if (tool == TOOLAddPoly)   // "Add Poly" tool
                {
 #ifdef DEBUGFOO
@@ -364,24 +424,27 @@ WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.
                                pts.AddNewPolyAtEnd();
                        }
 
-                       QPoint pt = GetAdjustedMousePosition(event);
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
 //printf("GetAdjustedMousePosition = %i, %i\n", pt.x(), pt.y());
                        // Append a point to the end of the structure
-                       pts += IPoint(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));
                        ptHighlight = pts.GetNumPoints() - 1;
                        update();
 #ifdef DEBUGFOO
 WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints());
 #endif
                }
+#endif
                else if (tool == TOOLSelect || tool == TOOLPolySelect)
                {
                        if (pts.GetNumPoints() > 0)
                        {
-                               pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
-//printf("GetAdjustedClientPosition = %i, %i\n", pt.x(), pt.y());
-//                             WarpPointer(pt.x, pt.y);
-                               QCursor::setPos(mapToGlobal(pt));
+//                             pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                               Vector pt = Painter::CartesianToQtCoords(Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight)));
+//printf("GetAdjustedClientPosition = %lf, %lf\n", pt.x, pt.y);
+                               QPoint warp(pt.x, pt.y);
+                               QCursor::setPos(mapToGlobal(warp));
 
                                if (event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier)
                                {
@@ -405,10 +468,11 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                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);
+                       // 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);
+                       rotationCenter = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
                        showRotationCenter = true;
                        haveZeroPoint = false;
                        rotationAngle = 0;
@@ -417,11 +481,12 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                else if (tool == TOOLRotatePoly)
                {
                        IPoint centroid = pts.GetPolyCentroid(pts.GetPolyForPointNumber(ptHighlight));
-                       rotationCenter = QPoint(centroid.x, centroid.y);
+                       rotationCenter = Vector(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));
+//                     pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       Vector pt = Painter::CartesianToQtCoords(Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight)));
+                       QCursor::setPos(mapToGlobal(QPoint(pt.x, pt.y)));
+                       rotationZeroPoint = Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
                        haveZeroPoint = true;
                        rotationAngle = 0;
                        update();
@@ -429,8 +494,9 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                else if (tool == TOOLFlipWinding)
                {
                        pts.InvertPolyDrawSequence(pts.GetPolyForPointNumber(ptHighlight));
-                       pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
-                       QCursor::setPos(mapToGlobal(pt));
+//                     pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       Vector pt = Painter::CartesianToQtCoords(Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight)));
+                       QCursor::setPos(mapToGlobal(QPoint(pt.x, pt.y)));
                        update();
                }
        }
@@ -454,38 +520,53 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        else if (event->buttons() == Qt::MidButton)
        {
                // Calc offset from previous point
-               pt = event->pos();
-               ptOffset = QPoint(pt.x() - ptPrevious.x(), pt.y() - ptPrevious.y());
+               Vector pt(event->x(), event->y());
+               pt /= Global::zoom;
+               ptOffset = Vector(pt.x - ptPrevious.x, -(pt.y - ptPrevious.y));
 
 // 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();
-               update();
+//             offsetX -= ptOffset.x, offsetY += ptOffset.y;
+               Global::origin -= ptOffset;
                ptPrevious = pt;
+               update();
        }
        else if (event->buttons() == Qt::LeftButton)
        {
                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)
+                       if ((tool == TOOLSelect) && (pts.GetNumPoints() == 0))
                                return;
 
-                       QPoint pt2 = GetAdjustedMousePosition(event);
-                       pts.SetXY(ptHighlight, pt2.x(), pt2.y());
+//                     QPoint pt2 = GetAdjustedMousePosition(event);
+                       Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+
+                       if (tool != TOOLSelect)
+                       {
+                               addPoint = pt2;
+                               ptHighlight = -1;
+                               // Prolly should move this to the key handlers below...
+//now we do! :-D
+//                             addPointOnCurve = ((event->modifiers() == Qt::ShiftModifier) || (event->modifiers() == Qt::ControlModifier) ? false : true);
+                       }
+                       else
+                               pts.SetXY(ptHighlight, pt2.x, pt2.y);
+
                        update();
                }
                else if (tool == TOOLPolySelect)
                {
                        if (pts.GetNumPoints() > 0)
                        {
-                               QPoint pt2 = GetAdjustedMousePosition(event);
+//                             QPoint pt2 = GetAdjustedMousePosition(event);
+                               Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
                                // 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));
+                               pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));
                                update();
                        }
                }
@@ -495,29 +576,48 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                        {
                                if (!haveZeroPoint)
                                {
-                                       rotationZeroPoint = GetAdjustedMousePosition(event);
+//                                     rotationZeroPoint = GetAdjustedMousePosition(event);
+                                       rotationZeroPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
                                        haveZeroPoint = true;
                                }
                                else
                                {
-                                       // 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);
+                                       // 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 currentPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                                       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);
+                                       s.sprintf("%.3f degrees", rotationAngle * RADIANS_TO_DEGREES);
+                                       Global::mainWindow->statusBar()->showMessage(s);
                                }
 
                                update();
                        }
                }
+               else if (tool == TOOLMultiSelect)
+               {
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                       selection.setBottomRight(QPoint(pt.x, pt.y));
+
+                       for(int i=0; i<pts.GetNumPoints(); i++)
+                       {
+                               if (selection.contains(QPoint(pts.GetX(i), pts.GetY(i))))
+                                       selectedPoints[i] = true;
+                               else
+                                       selectedPoints[i] = false;
+                       }
+
+                       update();
+               }
        }
        else if (event->buttons() == Qt::NoButton)
        {
@@ -525,13 +625,14 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt
                        || tool == TOOLPolySelect || tool == TOOLRotatePoly || tool == TOOLFlipWinding)
                {
-                       QPoint pt2 = GetAdjustedMousePosition(event);
+//                     QPoint pt2 = GetAdjustedMousePosition(event);
+                       Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
                        double closest = 1.0e+99;
 
                        for(int i=0; i<pts.GetNumPoints(); i++)
                        {
-                               double dist = ((pt2.x() - pts.GetX(i)) * (pt2.x() - pts.GetX(i)))
-                                       + ((pt2.y() - pts.GetY(i)) * (pt2.y() - pts.GetY(i)));
+                               double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))
+                                       + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));
 
                                if (dist < closest)
                                        closest = dist, ptHighlight = i;
@@ -543,15 +644,17 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                                update();
                        }
 
-                       // What follows here looks like voodoo, but is really simple. What we do is
-                       // check to see if the mouse point has a perpendicular intersection with any of
-                       // the line segments. If it does, calculate the length of the perpendicular
-                       // and choose the smallest length. If there is no perpendicular, then choose the
-                       // length of line connecting the closer of either the first endpoint or the
-                       // second and choose the smallest of those.
+                       // What follows here looks like voodoo, but is really simple. What
+                       // we do is check to see if the mouse point has a perpendicular
+                       // intersection with any of the line segments. If it does,
+                       // calculate the length of the perpendicular and choose the
+                       // smallest length. If there is no perpendicular, then choose the
+                       // length of line connecting the closer of either the first
+                       // endpoint or the second and choose the smallest of those.
 
-                       // There is one bit of math that looks like voodoo to me ATM--will explain once
-                       // I understand it better (the calculation of the length of the perpendicular).
+                       // There is one bit of math that looks like voodoo to me ATM--will
+                       // explain once I understand it better (the calculation of the
+                       // length of the perpendicular).
 
                        if (pts.GetNumPoints() > 1 && tool == TOOLAddPt)
                        {
@@ -559,16 +662,18 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
 
                                for(int i=0; i<pts.GetNumPoints(); i++)
                                {
-                                       int32 p1x = pts.GetX(i), p1y = pts.GetY(i),
+                                       int32_t 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),
-                                               v2(pt2.x(), pt2.y(), 0, p2x, p2y, 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.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.
+// 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.Magnitude();
@@ -579,12 +684,14 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
 
 //The answer to the above looks like it might be found here:
 //
-//If the segment endpoints are s and e, and the point is p, then the test for the perpendicular
-//intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and
-//{e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is
-//computed by first computing the area of the triangle the three points form, then dividing by the
-//length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the
-//triangle formed by three points is the determinant of the following matrix:
+//If the segment endpoints are s and e, and the point is p, then the test for
+//the perpendicular intercepting the segment is equivalent to insisting that
+//the two dot products {s-e}.{s-p} and {e-s}.{e-p} are both non-negative.
+//Perpendicular distance from the point to the segment is computed by first
+//computing the area of the triangle the three points form, then dividing by
+//the length of the segment.  Distances are done just by the Pythagorean
+//theorem. Twice the area of the triangle formed by three points is the
+//determinant of the following matrix:
 //
 //sx sy 1
 //ex ey 1
@@ -592,8 +699,9 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
 //
 //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!]
+//[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
@@ -613,7 +721,13 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                        }
                }
 
-               ptPrevious = event->pos();
+               ptPrevious = Vector(event->x(), event->y());
+               addPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+//handled by real key handlers now...
+//             addPointOnCurve = ((event->modifiers() == Qt::ShiftModifier) || (event->modifiers() == Qt::ControlModifier) ? false : true);
+
+               if (tool == TOOLAddPoly)
+                       update();
        }
 
        event->accept();
@@ -656,24 +770,101 @@ void EditWindow::mouseReleaseEvent(QMouseEvent * event)
                        haveZeroPoint = false;
 
                        if (tool == TOOLRotate)
-                               pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+                               pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x, rotationCenter.y));
                        else
                        {
-                               uint16 poly = pts.GetPolyForPointNumber(ptHighlight);
+                               uint16_t poly = pts.GetPolyForPointNumber(ptHighlight);
                                pts.RotatePolyAroundCentroid(poly, rotationAngle);
                        }
 
                        update();
-                       ((TTEdit *)qApp)->mainWindow->statusBar()->showMessage("");
+                       Global::mainWindow->statusBar()->showMessage("");
                }
 
 //             if (tool == TOOLScroll || tool == TOOLZoom)
 //                     ReleaseMouse();
 //this is prolly too much
-               ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&pts);
-               ((TTEdit *)qApp)->charWnd->update();
+               Global::charWnd->MakePathFromPoints(&pts);
+               Global::charWnd->update();
+
+               if (tool == TOOLMultiSelect)
+               {
+                       selectionInProgress = false;
+                       update();
+               }
+               else if (tool == TOOLAddPoly)   // "Add Poly" tool
+               {
+#ifdef DEBUGFOO
+WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());
+#endif
+                       if (polyFirstPoint)
+                       {
+                               polyFirstPoint = false;
+                               pts.AddNewPolyAtEnd();
+                       }
 
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+//printf("GetAdjustedMousePosition = %i, %i\n", pt.x(), pt.y());
+                       // Append a point to the end of the structure
+                       pts += IPoint(pt.x, pt.y, addPointOnCurve);
+//                     ptHighlight = pts.GetNumPoints() - 1;
+                       update();
+#ifdef DEBUGFOO
+WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints());
+#endif
+               }
        }
 
        event->accept();
 }
+
+
+void EditWindow::keyPressEvent(QKeyEvent * event)
+{
+       // We do this here because of the ptHighlight nonsense. If we're in
+       // the add poly tool, we'll never see this if it's under the 'sanity'
+       // check (which is needed for the arrow key shite, but still...)
+       if ((event->key() == Qt::Key_Shift) || (event->key() == Qt::Key_Control))
+       {
+               addPointOnCurve = false;
+               update();
+       }
+
+       // Sanity checking...
+       if (ptHighlight == -1)
+               return;
+
+       if (event->key() == Qt::Key_Up)
+       {
+               pts.SetXY(ptHighlight, pts.GetX(ptHighlight), pts.GetY(ptHighlight) + 1);
+       }
+       else if (event->key() == Qt::Key_Down)
+               pts.SetXY(ptHighlight, pts.GetX(ptHighlight), pts.GetY(ptHighlight) - 1);
+       else if (event->key() == Qt::Key_Right)
+               pts.SetXY(ptHighlight, pts.GetX(ptHighlight) + 1, pts.GetY(ptHighlight));
+       else if (event->key() == Qt::Key_Left)
+               pts.SetXY(ptHighlight, pts.GetX(ptHighlight) - 1, pts.GetY(ptHighlight));
+       else
+               return;
+
+//Not need but you need to call the base class for some reason??
+//     event->accept();
+       update();
+       Global::charWnd->MakePathFromPoints(&pts);
+       Global::charWnd->update();
+}
+
+
+void EditWindow::keyReleaseEvent(QKeyEvent * event)
+{
+       if ((event->key() == Qt::Key_Shift) || (event->key() == Qt::Key_Control))
+       {
+               addPointOnCurve = true;
+       }
+       else
+               return;
+
+       update();
+}
+