2 // TTEDIT.CPP - The TrueType Editor
4 // (C) 2004 Underground Software
6 // JLH = James L. Hammons <jlhamm@acm.org>
9 // --- ---------- -----------------------------------------------------------
10 // JLH 08/28/2008 Created this file
11 // JLH 09/02/2008 Separated scrolling from dedicated tool to MMB drag
12 // JLH 03/13/2009 Converted from wxWidgets to Qt
21 // - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font
22 // - Fix zooming, settings (ini)
23 // - Fix point adding bug 1: should be able to add points to empty canvas
24 // - Fix point adding bug 2: should be able to add point successfully to single
26 // - Add poly multi-select
27 // - Add point multi-select
31 // Uncomment this for debugging...
33 #define DEBUGFOO // Various tool debugging...
34 #define DEBUGTP // Toolpalette debugging...
36 #include "editwindow.h"
37 #include "charwindow.h"
40 #include "mainwindow.h"
41 #include "mathconstants.h"
46 EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent),
47 tool(TOOLSelect), ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1),
48 oldPtNextHighlight(-1), polyFirstPoint(true), showRotationCenter(false),
49 haveZeroPoint(false), selectionInProgress(false)
51 setBackgroundRole(QPalette::Base);
52 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
54 toolPalette = new ToolWindow();
56 setCursor(cur[TOOLSelect]);
57 setMouseTracking(true);
62 QSize EditWindow::minimumSizeHint() const
68 QSize EditWindow::sizeHint() const
70 return QSize(400, 400);
74 void EditWindow::CreateCursors(void)
76 int hotx[12] = { 1, 1, 1, 15, 1, 1, 1, 1, 1, 1, 1, 11 };
77 int hoty[12] = { 1, 1, 1, 13, 1, 1, 1, 1, 1, 1, 1, 11 };
78 char cursorName[12][48] = { "select", "select-poly", "select-multi", "zoom",
79 "add-point", "add-poly", "del-point", "del-poly", "rotate", "rotate",
82 for(int i=0; i<12; i++)
84 QPixmap pmTmp(QString(":/res/cursor-%1.png").arg(cursorName[i]));
85 cur[i] = QCursor(pmTmp, hotx[i], hoty[i]);
92 o Different colors for polys on selected points
93 o Different colors for handles on non-selected polys
94 o Line of sight (dashed, dotted) for off-curve points
95 o Repaints for press/release of CTRL/SHIFT during point creation
97 void EditWindow::paintEvent(QPaintEvent * /*event*/)
100 Painter painter(&qtp);
101 painter.SetRenderHint(QPainter::Antialiasing);
103 Global::viewportHeight = size().height();
104 Global::screenSize = Vector(size().width(), size().height());
106 // Draw coordinate axes
108 painter.SetPen(QPen(Qt::blue, 1.0, Qt::DotLine));
109 painter.DrawLine(0, -16384, 0, 16384);
110 painter.DrawLine(-16384, 0, 16384, 0);
112 // Draw rotation center (if active)
114 if (showRotationCenter)
116 painter.SetPen(QPen(Qt::red, 2.0, Qt::SolidLine));
117 painter.DrawLine(rotationCenter.x + 7, rotationCenter.y, rotationCenter.x - 7, rotationCenter.y);
118 painter.DrawLine(rotationCenter.x, rotationCenter.y + 7, rotationCenter.x, rotationCenter.y - 7);
123 for(int i=0; i<pts.GetNumPoints(); i++)
125 /*if (tool == TOOLMultiSelect)
127 if (selectedPoints[i])
129 qtp.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
133 qtp.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
137 if (((i == ptHighlight) && (tool != TOOLMultiSelect)) || ((tool == TOOLMultiSelect) && selectedPoints[i]))
139 painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine));
141 if (pts.GetOnCurve(i))
143 painter.DrawSquareDotN(pts.GetXY(i), 7);
144 painter.DrawSquareDotN(pts.GetXY(i), 9);
148 painter.DrawRoundDotN(pts.GetXY(i), 7);
149 painter.DrawRoundDotN(pts.GetXY(i), 9);
152 else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt)
154 painter.SetPen(QPen(Qt::green, 1.0, Qt::SolidLine));
156 if (pts.GetOnCurve(i))
158 painter.DrawSquareDotN(pts.GetXY(i), 7);
159 painter.DrawSquareDotN(pts.GetXY(i), 9);
163 painter.DrawRoundDotN(pts.GetXY(i), 7);
164 painter.DrawRoundDotN(pts.GetXY(i), 9);
169 painter.SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
172 if (pts.GetOnCurve(i))
173 painter.DrawSquareDot(pts.GetXY(i));
175 painter.DrawRoundDot(pts.GetXY(i));
177 (pts.GetOnCurve(i) ? DrawSquareDot(p, pts.GetX(i), pts.GetY(i))
178 : DrawRoundDot(p, pts.GetX(i), pts.GetY(i)));
182 if (tool == TOOLDelPt && i == ptHighlight)
184 painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine));
185 painter.DrawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);
186 painter.DrawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);
190 // Draw highlighted point on poly add tool
191 if (tool == TOOLAddPoly)
193 painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine));
197 painter.DrawSquareDotN(addPoint, 7);
198 painter.DrawSquareDotN(addPoint, 9);
202 painter.DrawRoundDotN(addPoint, 7);
203 painter.DrawRoundDotN(addPoint, 9);
207 // Draw curve formed by points
209 painter.SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
210 DrawGlyph(painter, pts);
215 GlyphPoints rotated = pts;
217 if (tool == TOOLRotate)
218 rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x, rotationCenter.y));
219 else if (tool == TOOLRotatePoly)
221 uint16_t poly = rotated.GetPolyForPointNumber(ptHighlight);
222 rotated.RotatePolyAroundCentroid(poly, rotationAngle);
225 painter.SetPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
226 DrawGlyph(painter, rotated);
229 if (selectionInProgress)
231 painter.SetPen(QPen(QColor(255, 127, 0, 255)));
232 painter.SetBrush(QBrush(QColor(255, 127, 0, 100)));
233 painter.DrawRect(selection);
238 void EditWindow::DrawGlyph(Painter & p, GlyphPoints & glyph)
240 for(int poly=0; poly<glyph.GetNumPolys(); poly++)
243 if (glyph.GetNumPoints(poly) < 3)
246 // Initial move: If our start point is on curve, then go to it. Otherwise,
247 // check previous point. If it's on curve, go to it otherwise go the
248 // midpoint between start point and previous (since it's between two curve
250 IPoint pt = (glyph.GetOnCurve(poly, 0)
251 ? glyph.GetPoint(poly, 0) : (glyph.GetPrevOnCurve(poly, 0)
252 ? glyph.GetPrevPoint(poly, 0) : glyph.GetMidpointToPrev(poly, 0)));
254 // Need to add separate color handling here for polys that are being manipulated...
256 for(int i=0; i<glyph.GetNumPoints(poly); i++)
258 // If this point and then next are both on curve, we have a line...
259 if (glyph.GetOnCurve(poly, i) && glyph.GetNextOnCurve(poly, i))
261 IPoint pt2 = glyph.GetNextPoint(poly, i);
262 p.drawLine(pt.x, pt.y, pt2.x, pt2.y);
267 // Skip point if it's on curve (start of curve--it's already
268 // been plotted so we don't need to handle it...)
269 if (glyph.GetOnCurve(poly, i))
272 // We are now guaranteed that we are sitting on a curve control point
273 // (off curve). Figure the extent of the curve: If the following is a
274 // curve control point, then use the midpoint to it otherwise go to
275 // the next point since it's on curve.
276 IPoint pt2 = (glyph.GetNextOnCurve(poly, i)
277 ? glyph.GetNextPoint(poly, i) : glyph.GetMidpointToNext(poly, i));
279 Bezier(p, pt, glyph.GetPoint(poly, i), pt2);
284 DrawGlyphPoly(p, glyph, poly);
291 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
292 to change the color of the line(s) drawn to the point to signal to the user
293 that it isn't finalized until they click the button.
295 void EditWindow::DrawGlyphPoly(Painter & p, GlyphPoints & glyph, uint16_t poly)
298 if (glyph.GetNumPoints(poly) < 3)
301 IPoint p1 = glyph.GetPrevPoint(poly, 0);
302 IPoint p2 = glyph.GetPoint(poly, 0);
304 // Inject the new poly point into the current polygon
305 if ((tool == TOOLAddPoly) && (poly == (glyph.GetNumPolys() - 1)))
307 p1 = IPoint(addPoint.x, addPoint.y, addPointOnCurve);
310 for(int i=0; i<glyph.GetNumPoints(poly); i++)
312 IPoint p3 = glyph.GetNextPoint(poly, i);
314 if ((tool == TOOLAddPoly) && (poly == (glyph.GetNumPolys() - 1))
315 && (i == (glyph.GetNumPoints(poly) - 1)))
317 p3 = IPoint(addPoint.x, addPoint.y, addPointOnCurve);
318 p.SetPen(QPen(Qt::green, 1.0, Qt::SolidLine));
319 DrawGlyphSegment(p, p1, p2, p3);
322 p3 = glyph.GetNextPoint(poly, i);
325 DrawGlyphSegment(p, p1, p2, p3);
334 // Draw a glyph segment given 3 points
336 void EditWindow::DrawGlyphSegment(Painter & p, IPoint p1, IPoint p2, IPoint p3)
340 // Skip drawing if the middle point is on curve and the last is off
346 // The middle point is off curve, and so we need to draw a Bezier curve.
347 // Also, depending on whether or not the previous or follow points are
348 // off curve, we need to draw to the midpoints if so.
349 IPoint mid12 = IPoint((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
350 IPoint mid23 = IPoint((p2.x + p3.x) / 2, (p2.y + p3.y) / 2);
351 p.DrawBezier((p1.onCurve ? p1 : mid12), p2, (p3.onCurve ? p3 : mid23));
356 void EditWindow::ClearSelection(void)
358 for(int i=0; i<65536; i++)
359 selectedPoints[i] = false;
363 void EditWindow::mousePressEvent(QMouseEvent * event)
365 if (event->button() == Qt::RightButton)
367 toolPalette->move(event->globalPos());
368 toolPalette->setVisible(true);
369 setCursor(cur[TOOLSelect]);
370 toolPalette->prevTool = TOOLSelect;
372 else if (event->button() == Qt::MidButton)
376 ptPrevious = Vector(event->x(), event->y());
377 ptPrevious /= Global::zoom;
379 else if (event->button() == Qt::LeftButton)
381 if (tool == TOOLScroll || tool == TOOLZoom)
382 ;//meh CaptureMouse(); // Make sure we capture the mouse when in scroll/zoom mode
383 else if (tool == TOOLMultiSelect)
385 // QPoint pt = GetAdjustedMousePosition(event);
386 Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
387 selectionInProgress = true;
388 selection.setTopLeft(QPoint(pt.x, pt.y));
389 selection.setBottomRight(QPoint(pt.x, pt.y));
391 else if (tool == TOOLAddPt) // "Add Point" tool
393 // QPoint pt = GetAdjustedMousePosition(event);
394 Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
395 IPoint pointToAdd(pt.x, pt.y, ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
397 if (pts.GetNumPoints() < 2)
399 // pts += IPoint(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
401 ptHighlight = pts.GetNumPoints() - 1;
405 // QPoint pt = GetAdjustedMousePosition(event);
406 // pts.InsertPoint(pts.GetNext(ptHighlight), pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
407 pts.InsertPoint(pts.GetNext(ptHighlight), pointToAdd);
408 ptHighlight = ptNextHighlight;
414 // Moved to mouse up routine, so we can slide the point around
416 else if (tool == TOOLAddPoly) // "Add Poly" tool
419 WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());
423 polyFirstPoint = false;
424 pts.AddNewPolyAtEnd();
427 // QPoint pt = GetAdjustedMousePosition(event);
428 Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
429 //printf("GetAdjustedMousePosition = %i, %i\n", pt.x(), pt.y());
430 // Append a point to the end of the structure
431 pts += IPoint(pt.x, pt.y, ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
432 ptHighlight = pts.GetNumPoints() - 1;
435 WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints());
439 else if (tool == TOOLSelect || tool == TOOLPolySelect)
441 if (pts.GetNumPoints() > 0)
443 // pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
444 Vector pt = Painter::CartesianToQtCoords(Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight)));
445 //printf("GetAdjustedClientPosition = %lf, %lf\n", pt.x, pt.y);
446 QPoint warp(pt.x, pt.y);
447 QCursor::setPos(mapToGlobal(warp));
449 if (event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier)
451 pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight));
456 else if (tool == TOOLDelPt)
458 if (pts.GetNumPoints() > 0)
460 // if (ptHighlight != -1)
462 //This assumes that WM_MOUSEMOVE happens before this!
463 //The above commented out line should take care of this contingency... !!! FIX !!!
464 pts.DeletePoint(ptHighlight);
468 else if (tool == TOOLRotate)
470 // I think what's needed here is to keep the initial mouse click,
471 // paint the rotation center, then use the 1st mouse move event to
472 // establish the rotation "zero line", which becomes the line of
473 // reference to all subsequent mouse moves.
474 // rotationCenter = GetAdjustedMousePosition(event);
475 rotationCenter = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
476 showRotationCenter = true;
477 haveZeroPoint = false;
481 else if (tool == TOOLRotatePoly)
483 IPoint centroid = pts.GetPolyCentroid(pts.GetPolyForPointNumber(ptHighlight));
484 rotationCenter = Vector(centroid.x, centroid.y);
485 showRotationCenter = true;
486 // pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
487 Vector pt = Painter::CartesianToQtCoords(Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight)));
488 QCursor::setPos(mapToGlobal(QPoint(pt.x, pt.y)));
489 rotationZeroPoint = Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
490 haveZeroPoint = true;
494 else if (tool == TOOLFlipWinding)
496 pts.InvertPolyDrawSequence(pts.GetPolyForPointNumber(ptHighlight));
497 // pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
498 Vector pt = Painter::CartesianToQtCoords(Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight)));
499 QCursor::setPos(mapToGlobal(QPoint(pt.x, pt.y)));
508 void EditWindow::mouseMoveEvent(QMouseEvent * event)
510 if (event->buttons() == Qt::RightButton)
512 ToolType newTool = toolPalette->FindSelectedTool();
514 if (newTool != toolPalette->prevTool)
516 toolPalette->prevTool = newTool;
517 toolPalette->repaint();
520 else if (event->buttons() == Qt::MidButton)
522 // Calc offset from previous point
523 Vector pt(event->x(), event->y());
525 ptOffset = Vector(pt.x - ptPrevious.x, -(pt.y - ptPrevious.y));
527 // Then multiply it by the scaling factor. Whee!
528 // This looks wacky because we're using screen coords for the offset...
529 // Otherwise, we would subtract both offsets!
530 // offsetX -= ptOffset.x, offsetY += ptOffset.y;
531 Global::origin -= ptOffset;
535 else if (event->buttons() == Qt::LeftButton)
537 if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect)
539 // Bail out if we have the select tool and no points yet...
540 if ((tool == TOOLSelect) && (pts.GetNumPoints() == 0))
543 // QPoint pt2 = GetAdjustedMousePosition(event);
544 Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
546 if (tool != TOOLSelect)
550 // Prolly should move this to the key handlers below...
552 // addPointOnCurve = ((event->modifiers() == Qt::ShiftModifier) || (event->modifiers() == Qt::ControlModifier) ? false : true);
555 pts.SetXY(ptHighlight, pt2.x, pt2.y);
559 else if (tool == TOOLPolySelect)
561 if (pts.GetNumPoints() > 0)
563 // QPoint pt2 = GetAdjustedMousePosition(event);
564 Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
565 // Should also set onCurve here as well, depending on keystate
567 //Would be nice, but we'd need to trap the keyPressEvent() as well, otherwise pressing/releasing
568 //the hotkey would show no change until the user moved their mouse.
569 pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));
573 else if (tool == TOOLRotate || tool == TOOLRotatePoly)
575 if (pts.GetNumPoints() > 0)
579 // rotationZeroPoint = GetAdjustedMousePosition(event);
580 rotationZeroPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
581 haveZeroPoint = true;
585 // Figure out the angle between the "zero" vector and the
586 // current one, then rotate all points relative to the
587 // "zero" vector (done by paint())
588 // QPoint currentPoint = GetAdjustedMousePosition(event);
589 Vector currentPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
590 Vector v1(rotationZeroPoint.x, rotationZeroPoint.y, 0,
591 rotationCenter.x, rotationCenter.y, 0);
592 Vector v2(currentPoint.x, currentPoint.y, 0,
593 rotationCenter.x, rotationCenter.y, 0);
594 // rotationAngle = v1.Angle(v2);
595 rotationAngle = v2.Angle(v1);
598 s.sprintf("%.3f degrees", rotationAngle * RADIANS_TO_DEGREES);
599 Global::mainWindow->statusBar()->showMessage(s);
605 else if (tool == TOOLMultiSelect)
607 // QPoint pt = GetAdjustedMousePosition(event);
608 Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
609 selection.setBottomRight(QPoint(pt.x, pt.y));
611 for(int i=0; i<pts.GetNumPoints(); i++)
613 if (selection.contains(QPoint(pts.GetX(i), pts.GetY(i))))
614 selectedPoints[i] = true;
616 selectedPoints[i] = false;
622 else if (event->buttons() == Qt::NoButton)
624 // Moving, not dragging...
625 if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt
626 || tool == TOOLPolySelect || tool == TOOLRotatePoly || tool == TOOLFlipWinding)
628 // QPoint pt2 = GetAdjustedMousePosition(event);
629 Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
630 double closest = 1.0e+99;
632 for(int i=0; i<pts.GetNumPoints(); i++)
634 double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))
635 + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));
638 closest = dist, ptHighlight = i;
641 if (ptHighlight != oldPtHighlight)
643 oldPtHighlight = ptHighlight;
647 // What follows here looks like voodoo, but is really simple. What
648 // we do is check to see if the mouse point has a perpendicular
649 // intersection with any of the line segments. If it does,
650 // calculate the length of the perpendicular and choose the
651 // smallest length. If there is no perpendicular, then choose the
652 // length of line connecting the closer of either the first
653 // endpoint or the second and choose the smallest of those.
655 // There is one bit of math that looks like voodoo to me ATM--will
656 // explain once I understand it better (the calculation of the
657 // length of the perpendicular).
659 if (pts.GetNumPoints() > 1 && tool == TOOLAddPt)
661 double smallest = 1.0e+99;
663 for(int i=0; i<pts.GetNumPoints(); i++)
665 int32_t p1x = pts.GetX(i), p1y = pts.GetY(i),
666 p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i));
668 Vector ls(p2x, p2y, 0, p1x, p1y, 0),
669 v1(pt2.x, pt2.y, 0, p1x, p1y, 0),
670 v2(pt2.x, pt2.y, 0, p2x, p2y, 0);
671 double pp = ls.Dot(v1) / ls.Magnitude(), dist;
672 // Geometric interpretation:
673 // pp is the paremeterized point on the vector ls where the perpendicular
674 // intersects ls. If pp < 0, then the perpendicular lies beyond the 1st
675 // endpoint. If pp > length of ls, then the perpendicular lies beyond the 2nd
679 dist = v1.Magnitude();
680 else if (pp > ls.Magnitude())
681 dist = v2.Magnitude();
682 else // distance = ?Det?(ls, v1) / |ls|
683 dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.Magnitude());
685 //The answer to the above looks like it might be found here:
687 //If the segment endpoints are s and e, and the point is p, then the test for
688 //the perpendicular intercepting the segment is equivalent to insisting that
689 //the two dot products {s-e}.{s-p} and {e-s}.{e-p} are both non-negative.
690 //Perpendicular distance from the point to the segment is computed by first
691 //computing the area of the triangle the three points form, then dividing by
692 //the length of the segment. Distances are done just by the Pythagorean
693 //theorem. Twice the area of the triangle formed by three points is the
694 //determinant of the following matrix:
700 //By translating the start point to the origin, this can be rewritten as:
701 //By subtracting row 1 from all rows, you get the following:
702 //[because sx = sy = 0. you could leave out the -sx/y terms below. because we
703 //subtracted row 1 from all rows (including row 1) row 1 turns out to be zero.
707 //(ex - sx) (ey - sy) 0
708 //(px - sx) (py - sy) 0
710 //which greatly simplifies the calculation of the determinant.
713 smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i;
716 if (ptNextHighlight != oldPtNextHighlight)
718 oldPtNextHighlight = ptNextHighlight;
724 ptPrevious = Vector(event->x(), event->y());
725 addPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
726 //handled by real key handlers now...
727 // addPointOnCurve = ((event->modifiers() == Qt::ShiftModifier) || (event->modifiers() == Qt::ControlModifier) ? false : true);
729 if (tool == TOOLAddPoly)
737 void EditWindow::mouseReleaseEvent(QMouseEvent * event)
739 if (event->button() == Qt::RightButton)
741 ToolType newTool = toolPalette->FindSelectedTool();
743 // We only change the tool if a new one was actually selected. Otherwise, we do nothing.
744 if (newTool != TOOLNone)
748 if (tool == TOOLScroll || tool == TOOLZoom || tool == TOOLAddPoly
749 || tool == TOOLDelPoly)
752 if (tool == TOOLAddPoly)
753 polyFirstPoint = true;
756 toolPalette->setVisible(false);
757 setCursor(cur[tool]);
758 // Just in case we changed highlighting style with the new tool...
761 else if (event->button() == Qt::MidButton)
763 setCursor(cur[tool]); // Restore previous cursor
765 else if (event->button() == Qt::LeftButton)
767 if (showRotationCenter)
769 showRotationCenter = false;
770 haveZeroPoint = false;
772 if (tool == TOOLRotate)
773 pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x, rotationCenter.y));
776 uint16_t poly = pts.GetPolyForPointNumber(ptHighlight);
777 pts.RotatePolyAroundCentroid(poly, rotationAngle);
781 Global::mainWindow->statusBar()->showMessage("");
784 // if (tool == TOOLScroll || tool == TOOLZoom)
786 //this is prolly too much
787 Global::charWnd->MakePathFromPoints(&pts);
788 Global::charWnd->update();
790 if (tool == TOOLMultiSelect)
792 selectionInProgress = false;
795 else if (tool == TOOLAddPoly) // "Add Poly" tool
798 WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints());
802 polyFirstPoint = false;
803 pts.AddNewPolyAtEnd();
806 // QPoint pt = GetAdjustedMousePosition(event);
807 Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
808 //printf("GetAdjustedMousePosition = %i, %i\n", pt.x(), pt.y());
809 // Append a point to the end of the structure
810 pts += IPoint(pt.x, pt.y, addPointOnCurve);
811 // ptHighlight = pts.GetNumPoints() - 1;
814 WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints());
823 void EditWindow::keyPressEvent(QKeyEvent * event)
825 // We do this here because of the ptHighlight nonsense. If we're in
826 // the add poly tool, we'll never see this if it's under the 'sanity'
827 // check (which is needed for the arrow key shite, but still...)
828 if ((event->key() == Qt::Key_Shift) || (event->key() == Qt::Key_Control))
830 addPointOnCurve = false;
834 // Sanity checking...
835 if (ptHighlight == -1)
838 if (event->key() == Qt::Key_Up)
840 pts.SetXY(ptHighlight, pts.GetX(ptHighlight), pts.GetY(ptHighlight) + 1);
842 else if (event->key() == Qt::Key_Down)
843 pts.SetXY(ptHighlight, pts.GetX(ptHighlight), pts.GetY(ptHighlight) - 1);
844 else if (event->key() == Qt::Key_Right)
845 pts.SetXY(ptHighlight, pts.GetX(ptHighlight) + 1, pts.GetY(ptHighlight));
846 else if (event->key() == Qt::Key_Left)
847 pts.SetXY(ptHighlight, pts.GetX(ptHighlight) - 1, pts.GetY(ptHighlight));
851 //Not need but you need to call the base class for some reason??
854 Global::charWnd->MakePathFromPoints(&pts);
855 Global::charWnd->update();
859 void EditWindow::keyReleaseEvent(QKeyEvent * event)
861 if ((event->key() == Qt::Key_Shift) || (event->key() == Qt::Key_Control))
863 addPointOnCurve = true;