X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Feditwindow.cpp;h=dac63c28c736d5d3b2cf8bb8d9e8f151684bccec;hb=c7d608c4fcdd370274964cc861b674c2fae69468;hp=34b1a06c59c5e15a7065e6d7b6d788d079a06de4;hpb=c84263bb8b0d16e4c6da49aa0b7d0bc904ae02b1;p=ttedit diff --git a/src/editwindow.cpp b/src/editwindow.cpp old mode 100755 new mode 100644 index 34b1a06..dac63c2 --- a/src/editwindow.cpp +++ b/src/editwindow.cpp @@ -6,16 +6,26 @@ // JLH = James L. Hammons // // 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 // // FIXED: // +// - Fixed scrolling +// // STILL TO BE DONE: // // - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font -// - Fix scrolling, zooming, settings (ini) +// - Fix zooming, settings (ini) +// - Fix point adding bug 1: should be able to add points to empty canvas +// - Fix point adding bug 2: should be able to add point successfully to single +// point on screen +// - Add poly multi-select +// - Add point multi-select +// - Undo system // // Uncomment this for debugging... @@ -24,237 +34,385 @@ #define DEBUGTP // Toolpalette debugging... #include "editwindow.h" -#include "graphicprimitives.h" -#include "toolwindow.h" +#include "charwindow.h" #include "debug.h" +#include "global.h" +#include "mainwindow.h" +#include "mathconstants.h" +#include "ttedit.h" #include "vector.h" -BEGIN_EVENT_TABLE(TTEditWindow, wxWindow) - EVT_PAINT(TTEditWindow::OnPaint) - EVT_MOUSE_EVENTS(TTEditWindow::OnMouseEvent) -END_EVENT_TABLE() +EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent), + 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); + + toolPalette = new ToolWindow(); + CreateCursors(); + setCursor(cur[TOOLSelect]); + setMouseTracking(true); + ClearSelection(); +} -TTEditWindow::TTEditWindow(wxFrame * parent, const wxPoint &pos, const wxSize &size, long style): - wxWindow(parent, -1, pos, size, style | wxFULL_REPAINT_ON_RESIZE), - app(wxGetApp()), scale(1.0), offsetX(-10), offsetY(-10), tool(TOOLSelect), - ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1), oldPtNextHighlight(-1), - polyFirstPoint(true), bmp(NULL) -{ - SetCursor(*(app.cur[tool])); - SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF)); - wxString s; - s.Printf(_("Zoom: %.2f%%"), scale * 100.0); - parent->SetStatusText(s, 1); +QSize EditWindow::minimumSizeHint() const +{ + return QSize(50, 50); } -TTEditWindow::~TTEditWindow(void) + +QSize EditWindow::sizeHint() const { - if (bmp) - delete bmp; + return QSize(400, 400); } -void TTEditWindow::OnPaint(wxPaintEvent &e) + +void EditWindow::CreateCursors(void) { - wxPaintDC dc(this); -//Doesn't do crap! -//dc.SetBackground(*wxWHITE_BRUSH); + 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<12; i++) + { + QPixmap pmTmp(QString(":/res/cursor-%1.png").arg(cursorName[i])); + cur[i] = QCursor(pmTmp, hotx[i], hoty[i]); + } +} -// Due to the screwiness of wxWidgets coord system, the origin is ALWAYS -// the upper left corner--regardless of axis orientation, etc... - wxCoord width, height; - dc.GetSize(&width, &height); - dc.SetDeviceOrigin(-offsetX, height - (-offsetY)); - dc.SetAxisOrientation(true, true); +/* +TODO: + o Different colors for polys on selected points + o Different colors for handles on non-selected polys + o Line of sight (dashed, dotted) for off-curve points + o Repaints for press/release of CTRL/SHIFT during point creation +*/ +void EditWindow::paintEvent(QPaintEvent * /*event*/) +{ + QPainter qtp(this); + Painter painter(&qtp); + painter.SetRenderHint(QPainter::Antialiasing); + + Global::viewportHeight = size().height(); + Global::screenSize = Vector(size().width(), size().height()); -// 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... + // Draw coordinate axes - dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0xFF), 1, wxDOT))); -// dc.DrawLine(0, 0, 10, 10); + painter.SetPen(QPen(Qt::blue, 1.0, Qt::DotLine)); + painter.DrawLine(0, -16384, 0, 16384); + painter.DrawLine(-16384, 0, 16384, 0); - // Draw coordinate axes + // Draw rotation center (if active) - dc.CrossHair(0, 0); + if (showRotationCenter) + { + 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 + // Draw points for(int i=0; iFindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID))); -// SelectObject(hdc, hRedPen1); + painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine)); if (pts.GetOnCurve(i)) { - DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7); - DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9); + painter.DrawSquareDotN(pts.GetXY(i), 7); + painter.DrawSquareDotN(pts.GetXY(i), 9); } else { - DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7); - DrawRoundDotN(dc, 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) { - dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0xAF, 0x00), 1, wxSOLID))); -// SelectObject(hdc, hGreenPen1); + painter.SetPen(QPen(Qt::green, 1.0, Qt::SolidLine)); if (pts.GetOnCurve(i)) { - DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7); - DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9); + painter.DrawSquareDotN(pts.GetXY(i), 7); + painter.DrawSquareDotN(pts.GetXY(i), 9); } else { - DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7); - DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9); + painter.DrawRoundDotN(pts.GetXY(i), 7); + painter.DrawRoundDotN(pts.GetXY(i), 9); } } else { - dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID))); -// SelectObject(hdc, hBlackPen1); + painter.SetPen(QPen(Qt::black, 1.0, Qt::SolidLine)); +#if 1 if (pts.GetOnCurve(i)) - DrawSquareDot(dc, pts.GetX(i), pts.GetY(i)); + painter.DrawSquareDot(pts.GetXY(i)); else - DrawRoundDot(dc, 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) { - 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!! - dc.DrawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5); - dc.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); } } -// SelectObject(hdc, hBlackPen1); - dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID))); + // 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 - for(int poly=0; 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_t poly = rotated.GetPolyForPointNumber(ptHighlight); + rotated.RotatePolyAroundCentroid(poly, rotationAngle); + } + + 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); + } +} + - wxCoord x, y; - - if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1)) - x = (wxCoord)pts.GetX(poly, pts.GetNumPoints(poly) - 1), y = (wxCoord)pts.GetY(poly, pts.GetNumPoints(poly) - 1); +void EditWindow::DrawGlyph(Painter & p, GlyphPoints & glyph) +{ + for(int poly=0; polyMove(pt); - app.toolPalette->Show(true); - SetCursor(*wxSTANDARD_CURSOR); - app.toolPalette->SetCursor(*wxSTANDARD_CURSOR); - app.toolPalette->prevTool = TOOLSelect; - app.toolPalette->Refresh(false); - CaptureMouse(); + p1 = IPoint(addPoint.x, addPoint.y, addPointOnCurve); } - else if (e.RightUp()) + + for(int i=0; iFindSelectedTool();//, oldTool = tool; + IPoint p3 = glyph.GetNextPoint(poly, i); - // We only change the tool if a new one was actually selected. Otherwise, we do nothing. - if (newTool != TOOLNone) + if ((tool == TOOLAddPoly) && (poly == (glyph.GetNumPolys() - 1)) + && (i == (glyph.GetNumPoints(poly) - 1))) { - tool = newTool; + 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); + } - if (tool == TOOLScroll || tool == TOOLZoom || tool == TOOLAddPoly - || tool == TOOLDelPoly) - ptHighlight = -1; + DrawGlyphSegment(p, p1, p2, p3); - if (tool == TOOLAddPoly) - polyFirstPoint = true; - } + 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; +} - ReleaseMouse(); - app.toolPalette->Show(false); - SetCursor(*(app.cur[tool])); + +void EditWindow::mousePressEvent(QMouseEvent * event) +{ + if (event->button() == Qt::RightButton) + { + toolPalette->move(event->globalPos()); + toolPalette->setVisible(true); + setCursor(cur[TOOLSelect]); + toolPalette->prevTool = TOOLSelect; + } + else if (event->button() == Qt::MidButton) + { + // Scrolling cursor + setCursor(cur[11]); + ptPrevious = Vector(event->x(), event->y()); + ptPrevious /= Global::zoom; } - else if (e.LeftDown()) + else if (event->button() == Qt::LeftButton) { if (tool == TOOLScroll || tool == TOOLZoom) - CaptureMouse(); // Make sure we capture the mouse when in scroll/zoom mode +;//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 { - if (pts.GetNumPoints() > 0) +// 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) + { +// pts += IPoint(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true)); + pts += pointToAdd; + ptHighlight = pts.GetNumPoints() - 1; + } + else { - wxPoint pt = GetAdjustedMousePosition(e); - pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true)); +// 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; - Refresh(); +// update(); } + + update(); } +// Moved to mouse up routine, so we can slide the point around +#if 0 else if (tool == TOOLAddPoly) // "Add Poly" tool { #ifdef DEBUGFOO @@ -266,24 +424,33 @@ WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts. pts.AddNewPolyAtEnd(); } - wxPoint pt = GetAdjustedMousePosition(e); +// 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, (e.ShiftDown() | e.ControlDown() ? false : true)); + pts += IPoint(pt.x, pt.y, ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true)); ptHighlight = pts.GetNumPoints() - 1; - Refresh(); + 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)); - WarpPointer(pt.x, pt.y); +// 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 (e.ShiftDown() | e.ControlDown()) + if (event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) + { pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight)); + update(); + } } } else if (tool == TOOLDelPt) @@ -295,179 +462,246 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP //This assumes that WM_MOUSEMOVE happens before this! //The above commented out line should take care of this contingency... !!! FIX !!! pts.DeletePoint(ptHighlight); - Refresh(); + 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); + rotationCenter = Painter::QtToCartesianCoords(Vector(event->x(), event->y())); + showRotationCenter = true; + haveZeroPoint = false; + rotationAngle = 0; + update(); + } + else if (tool == TOOLRotatePoly) + { + IPoint centroid = pts.GetPolyCentroid(pts.GetPolyForPointNumber(ptHighlight)); + rotationCenter = Vector(centroid.x, centroid.y); + showRotationCenter = true; +// 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(); + } + else if (tool == TOOLFlipWinding) + { + pts.InvertPolyDrawSequence(pts.GetPolyForPointNumber(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))); + update(); + } } - else if (e.LeftUp()) + + event->accept(); +} + + +void EditWindow::mouseMoveEvent(QMouseEvent * event) +{ + if (event->buttons() == Qt::RightButton) { -// mouseDown = false; + ToolType newTool = toolPalette->FindSelectedTool(); - if (tool == TOOLScroll || tool == TOOLZoom) - ReleaseMouse(); + if (newTool != toolPalette->prevTool) + { + toolPalette->prevTool = newTool; + toolPalette->repaint(); + } + } + else if (event->buttons() == Qt::MidButton) + { + // Calc offset from previous point + 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; + Global::origin -= ptOffset; + ptPrevious = pt; + update(); } - else if (e.Dragging()) + else if (event->buttons() == Qt::LeftButton) { - if (e.RightIsDown()) + if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect) { - ToolType newTool = app.toolPalette->FindSelectedTool(); + // Bail out if we have the select tool and no points yet... + if ((tool == TOOLSelect) && (pts.GetNumPoints() == 0)) + return; + +// QPoint pt2 = GetAdjustedMousePosition(event); + Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y())); - if (newTool != app.toolPalette->prevTool) + if (tool != TOOLSelect) { - app.toolPalette->prevTool = newTool; - app.toolPalette->Refresh(false); + 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); - return; + update(); } - - if (e.MiddleIsDown()) + else if (tool == TOOLPolySelect) { - // Calc offset from previous point - pt = e.GetPosition(); - ptOffset.x = pt.x - ptPrevious.x, - ptOffset.y = 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; - Refresh(); - - return; - } - -// if (e.LeftIsDown()) -// { -#if 0 - if (tool == TOOLScroll) + if (pts.GetNumPoints() > 0) { - // 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); - -// 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); + 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)); + 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 0 - wxPoint pt2 = GetAdjustedMousePosition(e); - pts.SetXY(ptHighlight, pt2.x, pt2.y); - Refresh(); -#endif +// rotationZeroPoint = GetAdjustedMousePosition(event); + rotationZeroPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y())); + haveZeroPoint = true; } - } - else if (tool == TOOLPolySelect) - { - if (pts.GetNumPoints() > 0) + else { - wxPoint pt2 = GetAdjustedMousePosition(e); - // 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)); - Refresh(); + // 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 * 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)); - ptPrevious = pt; + for(int i=0; ibuttons() == Qt::NoButton) { -// else // Moving, not dragging... -// { - if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt - || tool == TOOLPolySelect)// || tool == TOOLAddPoly) + // Moving, not dragging... + if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt + || tool == TOOLPolySelect || tool == TOOLRotatePoly || tool == TOOLFlipWinding) + { +// QPoint pt2 = GetAdjustedMousePosition(event); + Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y())); + double closest = 1.0e+99; + + for(int i=0; i 1 && tool == TOOLAddPt) + { + double smallest = 1.0e+99; - if (pts.GetNumPoints() > 1 && tool == TOOLAddPt) + for(int i=0; i 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(); - else // distance = ?Det?(ls, v1) / |ls| - dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.length()); +// 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(); + 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.Magnitude()); //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 //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 @@ -475,1141 +709,162 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP // //which greatly simplifies the calculation of the determinant. - if (dist < smallest) - smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i; - } + if (dist < smallest) + smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i; + } - if (ptNextHighlight != oldPtNextHighlight) - { - oldPtNextHighlight = ptNextHighlight; - Refresh(); - } + if (ptNextHighlight != oldPtNextHighlight) + { + oldPtNextHighlight = ptNextHighlight; + update(); } } -// } - - ptPrevious = e.GetPosition(); - } -} - -wxPoint TTEditWindow::GetAdjustedMousePosition(wxMouseEvent &e) -{ - wxCoord width, height; - wxClientDC dc(this); - - dc.GetSize(&width, &height); - dc.SetDeviceOrigin(-offsetX, height - (-offsetY)); - dc.SetAxisOrientation(true, true); - -#if 0 -wxStatusBar * sb = ((wxFrame *)GetParent())->GetStatusBar(); -wxString s; -s.Printf("Logical mouse pos: %d, %d (%d, %d)", pt.x, pt.y, width, height); -sb->SetStatusText(s); -#endif - - return e.GetLogicalPosition(dc); -} + } -wxPoint TTEditWindow::GetAdjustedClientPosition(wxCoord x, wxCoord y) -{ - wxCoord width, height; - wxClientDC dc(this); + 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); - dc.GetSize(&width, &height); - dc.SetDeviceOrigin(-offsetX, height - (-offsetY)); - dc.SetAxisOrientation(true, true); + if (tool == TOOLAddPoly) + update(); + } - return wxPoint(dc.LogicalToDeviceX(x), dc.LogicalToDeviceY(y)); + event->accept(); } -#if 0 - -!!! OLD STUFF !!! - - -LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) +void EditWindow::mouseReleaseEvent(QMouseEvent * event) { - RECT rc1, rc2; - HDC hdc; - POINT pt, ptOffset; - SIZE sz; - PAINTSTRUCT ps; - - switch (msgID) + if (event->button() == Qt::RightButton) { - case WM_CREATE: - - MiscCenterWnd(hWnd, GetDesktopWindow()); - InitCommonControls(); - hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, statusBarTxt, hWnd, ID_STATUSBAR); - - if (!hStatusBar) - return -1; - -// clean this crap up! -// well, the only crappy thing here is using a POINT as an int array, but otherwise, this is OK - wsprintf(strBuf, zoom, 1000); - hdc = GetDC(hWnd); - GetTextExtentPoint32(hdc, strBuf, lstrlen(strBuf), &sz); - ReleaseDC(hWnd, hdc); - zoomWndWidth = sz.cx; - wsprintf(strBuf, zoom, 100); - - GetClientRect(hWnd, &rc1); - pt.x = rc1.right - zoomWndWidth, pt.y = -1; - SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&pt); - SendMessage(hStatusBar, SB_SETTEXT, (0 | SBT_NOBORDERS), (LPARAM)statusBarTxt); - SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM)strBuf); - - hToolBar = CreateToolbarEx(hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, - IDR_TOOLBAR1, 3, hInst, IDB_TOOLBAR1, tbButtons, 4, 16, 16, 16, 16, sizeof(TBBUTTON)); - - if (!hToolBar) - return -1; - - CreateNewDoc(); - -// The following can only be done because we use a private DC (using "CS_OWNDC") -// (Is that true???) -// Set the mapping to draw the character so it fits in the viewport... - hdc = GetDC(hWnd); - GetClientRect(hWnd, &rc1); - GetClientRect(hStatusBar, &rc2); - rc1.bottom -= rc2.bottom; - SetMapMode(hdc, MM_ISOTROPIC); - SetWindowExtEx(hdc, rc1.right, rc1.bottom, NULL); - SetViewportExtEx(hdc, rc1.right, -rc1.bottom, NULL); - SetViewportOrgEx(hdc, 0, rc1.bottom, NULL); - ReleaseDC(hWnd, hdc); - break; - - case WM_CLOSE: - - if (SaveChanges()) - { - wpM.length = wpC.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(hMainWnd, &wpM); - GetWindowPlacement(hCharWnd, &wpC); + ToolType newTool = toolPalette->FindSelectedTool(); - if (!IsWindowVisible(hCharWnd)) // Needed because Windows lies about visibility - wpC.showCmd = SW_HIDE; + // We only change the tool if a new one was actually selected. Otherwise, we do nothing. + if (newTool != TOOLNone) + { + tool = newTool; - hdc = GetDC(hWnd); - GetViewportOrgEx(hdc, &ptVPM); - ReleaseDC(hWnd, hdc); + if (tool == TOOLScroll || tool == TOOLZoom || tool == TOOLAddPoly + || tool == TOOLDelPoly) + ptHighlight = -1; - DestroyWindow(hWnd); + if (tool == TOOLAddPoly) + polyFirstPoint = true; } - break; + toolPalette->setVisible(false); + setCursor(cur[tool]); + // Just in case we changed highlighting style with the new tool... + update(); + } + else if (event->button() == Qt::MidButton) + { + setCursor(cur[tool]); // Restore previous cursor + } + else if (event->button() == Qt::LeftButton) + { + if (showRotationCenter) + { + showRotationCenter = false; + haveZeroPoint = false; - case WM_DESTROY: + if (tool == TOOLRotate) + pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x, rotationCenter.y)); + else + { + uint16_t poly = pts.GetPolyForPointNumber(ptHighlight); + pts.RotatePolyAroundCentroid(poly, rotationAngle); + } - PostQuitMessage(0); - break; + update(); + Global::mainWindow->statusBar()->showMessage(""); + } - case WM_NCLBUTTONDOWN: +// if (tool == TOOLScroll || tool == TOOLZoom) +// ReleaseMouse(); +//this is prolly too much + Global::charWnd->MakePathFromPoints(&pts); + Global::charWnd->update(); - if (wParam == HTCAPTION) + if (tool == TOOLMultiSelect) { - NCMouseDown = true; - GetWindowRect(hMainWnd, &rc1); - GetWindowRect(hCharWnd, &rc2); - ptWinOffset.x = rc2.left - rc1.left; - ptWinOffset.y = rc2.top - rc1.top; + selectionInProgress = false; + update(); } - - // Let Windows do its thing with this msg, or weird things will happen... - - DefWindowProc(hWnd, msgID, wParam, lParam); - NCMouseDown = false; - break; - - case WM_WINDOWPOSCHANGING: - - if (NCMouseDown) + else if (tool == TOOLAddPoly) // "Add Poly" tool { - WINDOWPOS * wp = (WINDOWPOS *)lParam; +#ifdef DEBUGFOO +WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints()); +#endif + if (polyFirstPoint) + { + polyFirstPoint = false; + pts.AddNewPolyAtEnd(); + } - if (wp->hwnd == hMainWnd && !(wp->flags & SWP_NOMOVE)) - SetWindowPos(hCharWnd, 0, wp->x + ptWinOffset.x, wp->y + ptWinOffset.y, - 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); +// 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 } + } - return DefWindowProc(hWnd, msgID, wParam, lParam); // Seems this is needed... Bleah! - - case WM_PAINT: - { - hdc = BeginPaint(hWnd, &ps); + event->accept(); +} -// 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! - // Apparently, you *must* save the individual object types (pen, brush, etc.) +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(); + } - HGDIOBJ oldPen = SelectObject(hdc, hBluePen1), - oldBrush = SelectObject(hdc, hNullBrush); + // Sanity checking... + if (ptHighlight == -1) + return; - // Draw coordinate axes + 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; - MoveToEx(hdc, 0, -32000, NULL); - LineTo(hdc, 0, 32000); - MoveToEx(hdc, -32000, 0, NULL); - LineTo(hdc, 32000, 0); +//Not need but you need to call the base class for some reason?? +// event->accept(); + update(); + Global::charWnd->MakePathFromPoints(&pts); + Global::charWnd->update(); +} - // Draw points - for(int i=0; ikey() == Qt::Key_Shift) || (event->key() == Qt::Key_Control)) + { + addPointOnCurve = true; + } + else + return; - if (pts.GetOnCurve(i)) - { - DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 7); - DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 9); - } - else - { - DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 7); - DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 9); - } - } - else if ((i == ptHighlight || i == ptNextHighlight) && currentTool == TOOLAddPt) - { - SelectObject(hdc, hGreenPen1); + update(); +} - if (pts.GetOnCurve(i)) - { - DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 7); - DrawSquareDotN(hdc, pts.GetX(i), pts.GetY(i), 9); - } - else - { - DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 7); - DrawRoundDotN(hdc, pts.GetX(i), pts.GetY(i), 9); - } - } - else - { - SelectObject(hdc, hBlackPen1); - - if (pts.GetOnCurve(i)) - DrawSquareDot(hdc, pts.GetX(i), pts.GetY(i)); - else - DrawRoundDot(hdc, pts.GetX(i), pts.GetY(i)); - } - - if (currentTool == TOOLDelPt && i == ptHighlight) - { - 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!! - } - } - - SelectObject(hdc, hBlackPen1); - - // Draw curve formed by points - - for(int poly=0; poly 2) - { - // Initial move... - // If it's not on curve, then move to it, otherwise move to last point... - - if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1)) - MoveToEx(hdc, pts.GetX(poly, pts.GetNumPoints(poly) - 1), pts.GetY(poly, pts.GetNumPoints(poly) - 1), NULL); - else - MoveToEx(hdc, pts.GetX(poly, 0), pts.GetY(poly, 0), NULL); - - for(int i=0; i 0) - { -//Do we really need to put a cap on this??? -//Maybe... -// if (pts.GetNumPoints() < 16) -// { - pt.x = lParam & 0xFFFF, pt.y = lParam >> 16; - hdc = GetDC(hWnd); - DPtoLP(hdc, &pt, 1); - pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true)); - ptHighlight = ptNextHighlight; - ReleaseDC(hWnd, hdc); - InvalidateRect(hWnd, NULL, TRUE); -// } - } - } - else if (currentTool == TOOLAddPoly) // "Add Poly" tool - { -#ifdef DEBUGFOO -wsprintf(strBuf, "Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints()); -WriteLogMsg(strBuf); -#endif - if (polyFirstPoint) - { - polyFirstPoint = false; - pts.AddNewPolyAtEnd(); - } - -//Do we really need to put a cap on this??? -//Maybe... -// if (pts.GetNumPoints() < 16) -// { - pt.x = lParam & 0xFFFF, pt.y = lParam >> 16; - hdc = GetDC(hWnd); - DPtoLP(hdc, &pt, 1); - ReleaseDC(hWnd, hdc); - // Append a point to the end of the structure - pts += IPoint(pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true)); -ptHighlight = pts.GetNumPoints() - 1; - InvalidateRect(hWnd, NULL, TRUE); -// } -#ifdef DEBUGFOO -wsprintf(strBuf, " --> [# polys: %u, # points: %u]\xD\xA", pts.GetNumPolys(), pts.GetNumPoints()); -WriteLogMsg(strBuf); -#endif - } - else if (currentTool == TOOLSelect || currentTool == TOOLPolySelect) - { - if (pts.GetNumPoints() > 0) - { - pt.x = pts.GetX(ptHighlight), pt.y = pts.GetY(ptHighlight); - hdc = GetDC(hWnd); - LPtoDP(hdc, &pt, 1); - ClientToScreen(hWnd, &pt); - SetCursorPos(pt.x, pt.y); - ReleaseDC(hWnd, hdc); - - if (wParam & (MK_SHIFT | MK_CONTROL)) - pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight)); - } - } - else if (currentTool == TOOLDelPt) - { - if (pts.GetNumPoints() > 0) -//Or could use: -// if (ptHighlight != -1) - { -//This assumes that WM_MOUSEMOVE happens before this! -//The above commented out line should take care of this contingency... !!! FIX !!! - pts.DeletePoint(ptHighlight); - InvalidateRect(hWnd, NULL, TRUE); - } - } - - break; - - case WM_LBUTTONUP: - - mouseDown = false; - - if (currentTool == TOOLScroll || currentTool == TOOLZoom) - ReleaseCapture(); - - break; - - case WM_MOUSEMOVE: - - SetCursor(hCur[currentTool]); - - // Extract current point from lParam/calc offset from previous point - - pt.x = lParam & 0xFFFF, pt.y = lParam >> 16; - ptOffset.x = pt.x - ptPrevious.x, - ptOffset.y = pt.y - ptPrevious.y; - - if (mouseDown) - { - if (currentTool == TOOLScroll) - { - // NOTE: OffsetViewportOrg operates in DEVICE UNITS... - - hdc = GetDC(hWnd); - OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL); - ReleaseDC(hWnd, hdc); - -// 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! - - InvalidateRect(hWnd, NULL, TRUE); -// SendMessage(hWnd, WM_PAINT, NULL, NULL); - } - else if (currentTool == TOOLAddPt || currentTool == TOOLAddPoly || currentTool == TOOLSelect) - { - if (currentTool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch. - { - POINT pt2; - pt2.x = pt.x, pt2.y = pt.y; - // Should also set onCurve here as well, depending on keystate -//Or should we? - hdc = GetDC(hWnd); - DPtoLP(hdc, &pt2, 1); - pts.SetXY(ptHighlight, pt2.x, pt2.y); - ReleaseDC(hWnd, hdc); - InvalidateRect(hWnd, NULL, TRUE); - } - } - else if (currentTool == TOOLPolySelect) - { - if (pts.GetNumPoints() > 0) - { - POINT pt2; - pt2.x = pt.x, pt2.y = pt.y; - // Should also set onCurve here as well, depending on keystate -//Or should we? - hdc = GetDC(hWnd); - DPtoLP(hdc, &pt2, 1); - pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight)); - ReleaseDC(hWnd, hdc); - InvalidateRect(hWnd, NULL, TRUE); - } - } - } - else - { - if (currentTool == TOOLSelect || currentTool == TOOLDelPt || currentTool == TOOLAddPt - || currentTool == TOOLPolySelect)// || currentTool == TOOLAddPoly) - { - POINT pt2; - pt2.x = pt.x, pt2.y = pt.y; - hdc = GetDC(hWnd); - DPtoLP(hdc, &pt2, 1); - ReleaseDC(hWnd, hdc); - - double closest = 1.0e+99; - - for(int i=0; i 1 && currentTool == TOOLAddPt) - { - double smallest = 1.0e+99; - - for(int i=0; i 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(); - else // distance = ?Det?(ls, v1) / |ls| - dist = abs((ls.x * v1.y - v1.x * ls.y) / ls.length()); - -//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: -// -//sx sy 1 -//ex ey 1 -//px py 1 -// -//(???) By translating the start point to the origin, this can be rewritten as: -//By subtracting row 1 from all rows, you get the following: -// -//0 0 0 -//(ex - sx) (ey - sy) 0 -//(px - sx) (py - sy) 0 -// -//which greatly simplifies the calculation of the determinant. - - if (dist < smallest) - smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i; - } - - if (ptNextHighlight != oldPtNextHighlight) - { - oldPtNextHighlight = ptNextHighlight; - InvalidateRect(hWnd, NULL, TRUE); - } - } - } - } - - ptPrevious.x = pt.x, ptPrevious.y = pt.y; - - break; - - case WM_NOTIFY: - - if (((NMHDR *)lParam)->code == TTN_NEEDTEXT) - { - LoadString(hInst, ((TOOLTIPTEXT *)lParam)->hdr.idFrom + 0x80, toolTipTxt, 16); - ((TOOLTIPTEXT *)lParam)->lpszText = toolTipTxt; - } - - break; - - case WM_MENUSELECT: - { - statusBarTxt[0] = 0; // Clear status bar text - uint16 flags = wParam >> 16; // Extract flags - - if (!(flags & MFT_SEPARATOR)) - { - uint16 id = wParam & 0xFFFF; - - if (flags & MF_POPUP) - { - if (flags & MF_SYSMENU) - id = IDS_SYSMENU; - else - id = IDM_FILEMENU + wParam; - } - - LoadString(hInst, id, statusBarTxt, 64); - } - - SendMessage(hStatusBar, SB_SETTEXT, 0 + SBT_NOBORDERS, (LPARAM)statusBarTxt); - break; - } - case WM_COMMAND: - { - uint16 cmd = wParam & 0xFFFF; - - if (cmd == IDM_NEW) - { -// call CmdIDM_NEW - } - else if (cmd == IDM_OPEN) - { -// call SaveChanges -// .IF (eax) -// movmov ofn.hwndOwner, eax, hMainWnd -// mov ofn.Flags, OFN_PATHMUSTEXIST + OFN_FILEMUSTEXIST -// invoke GetOpenFileName, ADDR ofn -// .IF (eax) -//////// -//jmp @F -//szDMsg1a BYTE "Could not open the file (GetOpenFileName)...", 0 -//szDMsg1b BYTE "Open error!", 0 -//szDMsg1c BYTE "About to attempt to open file...", 0 -//@@: -////invoke MessageBox, hWnd, ADDR szDMsg1a, ADDR szDMsg1b, MB_ICONERROR or MB_OK -//invoke MessageBox, hMainWnd, ADDR szDMsg1c, ADDR szFile, MB_ICONERROR or MB_OK -// invoke LoadTTF, ADDR szFile -// -////// -// // <<< FILE OPEN CODE HERE >>> -// or fFileStatus, NAMEDbit -// and fFileStatus, NOT CHANGEDbit -// call NewWindowName -// mov eax, TRUE // return TRUE -// jmp Return -// //�������������������������������������� -//OpenError: invoke GetLastError -// // <<< FILE OPEN ERROR CODE HERE >>> -// .ENDIF -// zero eax // return FALSE -// .ENDIF - } - else if (cmd == IDM_SAVEAS) - { -// and fFileStatus, NOT NAMEDbit -// call CmdIDM_SAVE - } - else if (cmd == IDM_SAVE) - { -// call CmdIDM_SAVE - } - else if (cmd == IDM_ABOUT) - DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ABOUT), hMainWnd, AboutProc, NULL); - else if (cmd == IDM_EXIT) - SendMessage(hWnd, WM_CLOSE, 0, 0); - else if (cmd == ID_TBCHARWIN) - { - ShowWindow(hCharWnd, (IsWindowVisible(hCharWnd) ? SW_HIDE : SW_SHOWNOACTIVATE)); - -#ifdef DEBUGFOO -wpC.length = sizeof(WINDOWPLACEMENT); -GetWindowPlacement(hCharWnd, &wpC); -wsprintf(strBuf, "Char window showCmd = %08X...\n", wpC.showCmd); -WriteLogMsg(strBuf); -#endif - } - else - return DefWindowProc(hWnd, msgID, wParam, lParam); - - break; - } - default: - return DefWindowProc(hWnd, msgID, wParam, lParam); - } - - return 0; -} - -// -// Initialize TTF data -// -void CreateNewDoc(void) -{ -} - -// -// Save changes to document before quitting -// -bool SaveChanges(void) -{ - return true; -} - - - -// -// ABOUT Dialog WndProc -// -BOOL CALLBACK AboutProc(HWND hDlg, UINT msgID, WPARAM wParam, LPARAM lParam) -{ - switch (msgID) - { - case WM_INITDIALOG: - - MiscCenterWnd(hDlg, hMainWnd); - break; - - case WM_COMMAND: - - if (wParam == IDOK || wParam == IDCANCEL) - EndDialog(hDlg, TRUE); - - break; - - default: - return FALSE; - } - - return TRUE; -} - -// -// Character Window WndProc -// -WndProcCW PROC STDCALL, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM - - mov eax, uMsg // pickup our message - .IF (eax == WM_PAINT) - mov eax, 0 // Non-sense... (placeholder!) -// Scan conversion etc. goes here... - .ELSEIF (eax == WM_LBUTTONDOWN) - invoke SetCapture, hCharWnd - .ELSEIF (eax == WM_LBUTTONUP) - invoke ReleaseCapture - invoke SetFocus, hMainWnd // Make sure the main wnd keeps focus! - .ELSEIF (eax == WM_NCLBUTTONDOWN) - invoke DefWindowProc, hWnd, uMsg, wParam, lParam // Let it do its thing - invoke SetFocus, hMainWnd // Make sure the main wnd keeps focus! - .ELSE -DefProc: invoke DefWindowProc, hWnd, uMsg, wParam, lParam - .ENDIF - ret - -WndProcCW ENDP - -// -// Character Window WndProc -// -LRESULT CALLBACK WndProcCW(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) -{ - switch (msgID) - { - default: - return DefWindowProc(hWnd, msgID, wParam, lParam); - } - - return 0; -} - - -// Function prototypes - -int32 FindSelectedTool(void); - -// -// Tool Palette WndProc -// -LRESULT CALLBACK WndProcTP(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) -{ - PAINTSTRUCT ps; - HDC hdc; - POINT pt; - static uint32 prevTool = -1; - - switch (msgID) - { - case WM_PAINT: - { - hdc = BeginPaint(hWnd, &ps); - HDC newDC = CreateCompatibleDC(NULL); - SelectObject(newDC, hBMToolPal1); - BitBlt(hdc, 0, 0, sizeTPBM.x, sizeTPBM.y, newDC, 0, 0, SRCCOPY); - DeleteDC(newDC); - -// This is crappy. Find some way to tighten this up! - int32 tool = FindSelectedTool(); - - if (tool != -1) - { - newDC = CreateCompatibleDC(NULL); - SelectObject(newDC, hBMToolPal1); - //need ul corner of bitmap, ul corner of dest, width/height - pt.x = sizeStamp.x * (tool & 0x03), pt.y = sizeStamp.y * (tool >> 2); - BitBlt(hdc, pt.x, pt.y, sizeStamp.x, sizeStamp.y, newDC, pt.x, pt.y, NOTSRCCOPY); - DeleteDC(newDC); - } - - EndPaint(hWnd, &ps); - break; - } - case WM_MOUSEMOVE: - { - int32 tool = FindSelectedTool(); - - if (tool != prevTool) - { - prevTool = tool; - InvalidateRect(hWnd, NULL, FALSE); - } - - break; - } - case WM_RBUTTONUP: - { - int32 tool = FindSelectedTool(), oldTool = currentTool; - - if (tool != -1) - currentTool = tool; - - if (currentTool != TOOLSelect && currentTool != TOOLDelPt && currentTool != TOOLAddPt - && currentTool != TOOLPolySelect) - ptHighlight = -1; - - if (currentTool != oldTool) - InvalidateRect(hMainWnd, NULL, TRUE); - - if (currentTool == TOOLAddPoly) -#ifdef DEBUGFOO -{ -#endif - polyFirstPoint = true; -#ifdef DEBUGFOO -wsprintf(strBuf, "--> Selected poly tool, polyFirstPoint is %s\n", polyFirstPoint ? "true" : "false"); -WriteLogMsg(strBuf); -} -#endif - - ReleaseCapture(); - ShowWindow(hToolPalWnd, SW_HIDE); - SetFocus(hMainWnd); // Make sure the main wnd keeps focus! - - break; - } - default: - return DefWindowProc(hWnd, msgID, wParam, lParam); - } - - return 0; -} - -// -// Find which tool we're pointing at -// Use: xcoord = mouse.x / (bmsize.x/4), ycoord = mouse.y / (bmsize.y/2) -// -int32 FindSelectedTool(void) -{ - POINT pt; - - GetCursorPos(&pt); - ScreenToClient(hToolPalWnd, &pt); - - uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y, tool = -1; - - if (x < 4 && y < 2) -// { - tool = (y * 4) + x; - -// if (tool == 7) -// tool = -1; // 7 has no tool... -// } - - return tool; -} - - -// -// Misc center window -// -void MiscCenterWnd(HWND hChild, HWND hParent) -{ - RECT parent, child; - - if (!GetWindowRect(hParent, &parent) || !GetWindowRect(hChild, &child)) - return; - - int32 x = parent.left + (((parent.right - parent.left) - (child.right - child.left)) / 2), - y = parent.top + (((parent.bottom - parent.top) - (child.bottom - child.top)) / 2); - - if (x < 0) - x = 0; - else if (x > GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left)) - x = GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left); - - if (y < 0) - y = 0; - else if (y > GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top)) - y = GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top); - - SetWindowPos(hChild, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); -} - -// -// Allow only one instance -// -bool OnlyOneInstance(void) -{ - HWND window = FindWindow(className, NULL); - - if (window == NULL) - return true; - - ShowWindow(window, SW_SHOWNORMAL); - SetWindowPos(window, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); - - return false; -} - -// -// Load/Allocate all resources -// -bool LoadResources(void) -{ - hCur[0] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR1)); - hCur[1] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR2)); - hCur[2] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR3)); - hCur[3] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR4)); - hCur[4] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR5)); - hCur[5] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR6)); - hCur[6] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR7)); - hCur[7] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR8)); - - BITMAP bm; - - hBMToolPal1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_TOOLPAL1)); - GetObject(hBMToolPal1, sizeof(bm), &bm); - - // Set up sizes - - sizeTPBM.x = bm.bmWidth, sizeTPBM.y = bm.bmHeight; - sizeStamp.x = bm.bmWidth / 4, sizeStamp.y = bm.bmHeight / 2; - - hBluePen1 = CreatePen(PS_DOT, 1, 0x00FF0000); - hRedPen1 = CreatePen(PS_SOLID, 1, 0x000000FF); - hGreenPen1 = CreatePen(PS_SOLID, 1, 0x0000AF00); - hBlackPen1 = CreatePen(PS_SOLID, 1, 0x00000000); - - LOGBRUSH lb = { BS_NULL, 0, 0 }; - - hNullBrush = CreateBrushIndirect(&lb); - - return true; -} - -// -// Deallocate all resources -// -void DeallocateResources(void) -{ - DeleteObject(hBMToolPal1); - DeleteObject(hBluePen1); - DeleteObject(hRedPen1); - DeleteObject(hGreenPen1); - DeleteObject(hBlackPen1); - DeleteObject(hNullBrush); -} - -// -// Save all application specific data, so we can pick up where we last left off... -// -void SaveAppState(void) -{ - SetINIInt("Main", "flags", wpM.flags); - SetINIInt("Main", "showCmd", wpM.showCmd); - SetINIInt("Main", "x1", wpM.rcNormalPosition.left); - SetINIInt("Main", "y1", wpM.rcNormalPosition.top); - SetINIInt("Main", "x2", wpM.rcNormalPosition.right); - SetINIInt("Main", "y2", wpM.rcNormalPosition.bottom); - - SetINIInt("Main", "vpx", ptVPM.x); - SetINIInt("Main", "vpy", ptVPM.y); - - SetINIInt("Char", "flags", wpC.flags); - SetINIInt("Char", "showCmd", wpC.showCmd); - SetINIInt("Char", "x1", wpC.rcNormalPosition.left); - SetINIInt("Char", "y1", wpC.rcNormalPosition.top); - SetINIInt("Char", "x2", wpC.rcNormalPosition.right); - SetINIInt("Char", "y2", wpC.rcNormalPosition.bottom); - - // Need to write out currently opened font, character looking at, other misc. crap -// SetINIString("Main", "currentFile", pDoc->GetPathName()); -// SetINIInt("Main", "currentChar", pDoc->character_num); -} - -// -// Restore all application specific data previously saved -// -bool RestoreAppState(void) -{ - InitINIFile(); - - WINDOWPLACEMENT wp; - wp.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(hMainWnd, &wp); - - wp.flags = GetINIInt("Main", "flags", wp.flags); - wp.showCmd = GetINIInt("Main", "showCmd", wp.showCmd); - wp.rcNormalPosition.left = GetINIInt("Main", "x1", wp.rcNormalPosition.left); - wp.rcNormalPosition.top = GetINIInt("Main", "y1", wp.rcNormalPosition.top); - wp.rcNormalPosition.right = GetINIInt("Main", "x2", wp.rcNormalPosition.right); - wp.rcNormalPosition.bottom = GetINIInt("Main", "y2", wp.rcNormalPosition.bottom); - - SetWindowPlacement(hMainWnd, &wp); - - HDC hdc; - POINT pt; - hdc = GetDC(hMainWnd); - GetViewportOrgEx(hdc, &pt); - - pt.x = GetINIInt("Main", "vpx", pt.x); - pt.y = GetINIInt("Main", "vpy", pt.y); - - SetViewportOrgEx(hdc, pt.x, pt.y, NULL); - ReleaseDC(hMainWnd, hdc); - - GetWindowPlacement(hCharWnd, &wp); - - wp.flags = GetINIInt("Char", "flags", wp.flags); - wp.showCmd = GetINIInt("Char", "showCmd", wp.showCmd); - wp.rcNormalPosition.left = GetINIInt("Char", "x1", wp.rcNormalPosition.left); - wp.rcNormalPosition.top = GetINIInt("Char", "y1", wp.rcNormalPosition.top); - wp.rcNormalPosition.right = GetINIInt("Char", "x2", wp.rcNormalPosition.right); - wp.rcNormalPosition.bottom = GetINIInt("Char", "y2", wp.rcNormalPosition.bottom); - - SetWindowPlacement(hCharWnd, &wp); - - if (wp.showCmd == SW_HIDE) - SendMessage(hToolBar, TB_SETSTATE, ID_TBCHARWIN, MAKELONG(TBSTATE_ENABLED, 0)); - -// CString lastFile = theApplicationObject.GetProfileString(version, "currentFile", ""); -// int lastChar = theApplicationObject.GetProfileInt(version, "currentChar", 0); -// if (lastFile.GetLength()) -// { -// // Attempt to restore the last session by open the last file used, etc... -// if (!pDoc->m_myFont.Load(lastFile)) -// { -// // Err, make sure you can support any allegations you make below, buddy! -// AfxMessageBox("The last file opened with TTF Edit\n\rseems to have been moved or deleted."); -// } -// else -// { -// pDoc->m_myFont.SetGlyph(lastChar); // Set TTF object to last used char -// pDoc->character_num = lastChar; -// pDoc->SetPathName(lastFile); -// -// BYTE name[512]; -// pDoc->m_myFont.GetCharName(lastChar, name); -// m_wndOwned.SetWindowText((char *)name); -// } -// } - - return true; -} - -// -// Initialization -// -bool Initialization(void) -{ - WNDCLASSEX wcex; - - if (!LoadResources()) - return false; - - RtlFillMemory(&wcex, sizeof(WNDCLASSEX), 0); - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wcex.lpfnWndProc = WndProc; - wcex.hInstance = hInst; - wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON)); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wcex.lpszMenuName = MAKEINTRESOURCE(IDM_MENU); - wcex.lpszClassName = className; - wcex.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, NULL); - - if (!RegisterClassEx(&wcex)) - return false; - - hMainWnd = CreateWindowEx(NULL, className, className, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - 0, 0, 0x1A0, 0x180, NULL, NULL, hInst, NULL); - - if (!hMainWnd) - return false; - - ShowWindow(hMainWnd, nCmdShow); - UpdateWindow(hMainWnd); - - // Character window creation - - wcex.lpfnWndProc = WndProcCW; - wcex.lpszMenuName = NULL; - wcex.lpszClassName = CNCharWin; - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // Owned windows have "regular" cursors - - if (!RegisterClassEx(&wcex)) - return false; - - hCharWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW, CNCharWin, - curCharName, WS_POPUP | WS_CAPTION | WS_VISIBLE | WS_THICKFRAME, - 100, 100, 120, 120, hMainWnd, NULL, hInst, NULL); - - if (!hCharWnd) - return false; - - ShowWindow(hCharWnd, SW_SHOWNORMAL); - UpdateWindow(hCharWnd); - SetFocus(hMainWnd); // Make sure main wnd has focus! - - // Tool palette window creation - - wcex.lpfnWndProc = WndProcTP; - wcex.lpszClassName = CNToolPal; - - if (!RegisterClassEx(&wcex)) - return false; - - hToolPalWnd = CreateWindowEx(WS_EX_WINDOWEDGE, CNToolPal, NULL, WS_POPUP, - 0, 0, sizeTPBM.x, sizeTPBM.y, hMainWnd, NULL, hInst, NULL); - - if (!hToolPalWnd) - return false; - -// Note: A better way to handle this would be to have a sub that registers ALL -// classes beforehand and passes a TRUE/FALSE back depending on whether or not -// all the classes were able to be registered or not, THEN create the windows -// and controls... - - RestoreAppState(); // Restore app related stuff - - return true; -} - -#endif