X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Feditwindow.cpp;fp=src%2Feditwindow.cpp;h=b0952ca6ded33e365a448da5b487dc8050a49f19;hb=3599953dec39d0ae662b039378a0b3eda39424e8;hp=a115f9682faab0043f9ae2b77434fb4d121ba07d;hpb=72ee24a9cf364cfbf32b878172eea5f6ad2676c3;p=ttedit diff --git a/src/editwindow.cpp b/src/editwindow.cpp index a115f96..b0952ca 100755 --- a/src/editwindow.cpp +++ b/src/editwindow.cpp @@ -9,6 +9,7 @@ // --- ---------- ------------------------------------------------------------- // 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: @@ -32,6 +33,522 @@ #define DEBUGFOO // Various tool debugging... #define DEBUGTP // Toolpalette debugging... +#include "editwindow.h" +//#include +#include "graphicprimitives.h" +#include "debug.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) +{ + setBackgroundRole(QPalette::Base); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + toolPalette = new ToolWindow(); + CreateCursors(); + setCursor(cur[TOOLSelect]); + setMouseTracking(true); +} + +QSize EditWindow::minimumSizeHint() const +{ + return QSize(50, 50); +} + +QSize EditWindow::sizeHint() const +{ + return QSize(400, 400); +} + +void EditWindow::CreateCursors(void) +{ + int hotx[8] = { 1, 1, 11, 15, 1, 1, 1, 1 }; + int hoty[8] = { 1, 1, 11, 13, 1, 1, 1, 1 }; + + for(int i=0; i<8; i++) + { + QString s; + s.sprintf(":/res/cursor%u.png", i+1); + QPixmap pmTmp(s); + 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); +} + +void EditWindow::paintEvent(QPaintEvent * /*event*/) +{ + QPainter p(this); +//hm, causes lockup +// p.setRenderHint(QPainter::Antialiasing); +//Doesn't do crap! +//dc.SetBackground(*wxWHITE_BRUSH); + +// Due to the screwiness of wxWidgets coord system, the origin is ALWAYS +// the upper left corner--regardless of axis orientation, etc... +// int width, height; +// dc.GetSize(&width, &height); + QSize winSize = size(); + +// dc.SetDeviceOrigin(-offsetX, height - (-offsetY)); +// dc.SetAxisOrientation(true, true); + p.translate(QPoint(-offsetX, winSize.height() - (-offsetY))); + p.scale(1.0, -1.0); + +// 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... + +// dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0xFF), 1, wxDOT))); +//// dc.DrawLine(0, 0, 10, 10); + p.setPen(QPen(Qt::blue, 1.0, Qt::DotLine)); + + // Draw coordinate axes + +// dc.CrossHair(0, 0); + p.drawLine(0, -16384, 0, 16384); + p.drawLine(-16384, 0, 16384, 0); + + // Draw points + + for(int i=0; iFindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID))); +//// SelectObject(hdc, hRedPen1); + p.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); + } + else + { + DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 7); + DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 9); + } + } + else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt) + { +// dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0xAF, 0x00), 1, wxSOLID))); +//// SelectObject(hdc, hGreenPen1); + p.setPen(QPen(Qt::green, 1.0, Qt::SolidLine)); + + if (pts.GetOnCurve(i)) + { + DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 7); + DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 9); + } + else + { + DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 7); + DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 9); + } + } + else + { +// dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID))); +//// SelectObject(hdc, hBlackPen1); + p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine)); + + if (pts.GetOnCurve(i)) + DrawSquareDot(p, pts.GetX(i), pts.GetY(i)); + else + DrawRoundDot(p, pts.GetX(i), pts.GetY(i)); + } + + if (tool == TOOLDelPt && i == ptHighlight) + { +#if 0 + dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID))); +// SelectObject(hdc, hRedPen1); +// MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL); +// LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5); +// LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness! +// MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL); +// LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5); +// LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!! +#endif + p.setPen(QPen(Qt::red, 1.0, Qt::SolidLine)); + p.drawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5); + p.drawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5); + } + } + +//// SelectObject(hdc, hBlackPen1); +// dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID))); + p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine)); + + // Draw curve formed by points + + for(int poly=0; poly 2) + { + // Initial move... + // If it's not on curve, then move to it, otherwise move to last point... + + int x, y; + + if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1)) + x = (int)pts.GetX(poly, pts.GetNumPoints(poly) - 1), y = (int)pts.GetY(poly, pts.GetNumPoints(poly) - 1); + else + x = (int)pts.GetX(poly, 0), y = (int)pts.GetY(poly, 0); + + for(int i=0; ibutton() == Qt::RightButton) + { + toolPalette->move(event->globalPos()); + toolPalette->setVisible(true); + setCursor(cur[TOOLSelect]); + toolPalette->prevTool = TOOLSelect; + } + else if (event->button() == Qt::MidButton) + { + setCursor(cur[2]); // Scrolling cursor + } + 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 == TOOLAddPt) // "Add Point" tool + { + if (pts.GetNumPoints() > 0) + { + QPoint pt = GetAdjustedMousePosition(event); + pts.InsertPoint(pts.GetNext(ptHighlight), pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true)); + ptHighlight = ptNextHighlight; + 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); +//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)); + ptHighlight = pts.GetNumPoints() - 1; + update(); +#ifdef DEBUGFOO +WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints()); +#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)); + + if (event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) + { + pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight)); + update(); + } + } + } + else if (tool == 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); + update(); + } + } + } + + event->accept(); +} + +void EditWindow::mouseMoveEvent(QMouseEvent * event) +{ + if (event->buttons() == Qt::RightButton) + { + ToolType newTool = toolPalette->FindSelectedTool(); + + if (newTool != toolPalette->prevTool) + { + toolPalette->prevTool = newTool; + toolPalette->repaint(); + } + } + else if (event->buttons() == Qt::MidButton) + { + // Calc offset from previous point + pt = event->pos(); + ptOffset = QPoint(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(); + ptPrevious = pt; + } + else if (event->buttons() == Qt::LeftButton) + { +#if 0 + if (tool == TOOLScroll) + { + // Extract current point from lParam/calc offset from previous point + + pt = e.GetPosition(); + ptOffset.x = pt.x - ptPrevious.x, + ptOffset.y = pt.y - ptPrevious.y; + + // NOTE: OffsetViewportOrg operates in DEVICE UNITS... + +//Seems there's no equivalent for this in wxWidgets...! +//!!! FIX !!! +// hdc = GetDC(hWnd); +// OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL); +// ReleaseDC(hWnd, hdc); + +// 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(); + } + else +#endif + if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect) + { + if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch. + { +//temporary, for testing. BTW, Select drag bug is here...! +#if 1 + QPoint pt2 = GetAdjustedMousePosition(event); + pts.SetXY(ptHighlight, pt2.x(), pt2.y()); + update(); +#endif + } + } + else if (tool == TOOLPolySelect) + { + if (pts.GetNumPoints() > 0) + { + QPoint pt2 = GetAdjustedMousePosition(event); + // Should also set onCurve here as well, depending on keystate +//Or should we? + pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight)); + update(); + } + } + } + else if (event->buttons() == Qt::NoButton) + { + // Moving, not dragging... + if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt + || tool == TOOLPolySelect)// || tool == TOOLAddPoly) + { + QPoint pt2 = GetAdjustedMousePosition(event); + double closest = 1.0e+99; + + for(int i=0; i 1 && tool == 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 = fabs((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; + update(); + } + } + } + + ptPrevious = event->pos(); + } + + event->accept(); +} + +void EditWindow::mouseReleaseEvent(QMouseEvent * event) +{ + if (event->button() == Qt::RightButton) + { + ToolType newTool = toolPalette->FindSelectedTool(); + + // We only change the tool if a new one was actually selected. Otherwise, we do nothing. + if (newTool != TOOLNone) + { + tool = newTool; + + if (tool == TOOLScroll || tool == TOOLZoom || tool == TOOLAddPoly + || tool == TOOLDelPoly) + ptHighlight = -1; + + if (tool == TOOLAddPoly) + polyFirstPoint = true; + } + + 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 (tool == TOOLScroll || tool == TOOLZoom) +// ReleaseMouse(); + } + + event->accept(); +} + + + +#if 0 #include "editwindow.h" #include "graphicprimitives.h" #include "toolwindow.h" @@ -49,7 +566,7 @@ TTEditWindow::TTEditWindow(wxFrame * parent, const wxPoint &pos, const wxSize &s 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)); @@ -167,12 +684,12 @@ void TTEditWindow::OnPaint(wxPaintEvent &e) // If it's not on curve, then move to it, otherwise move to last point... 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); else x = (wxCoord)pts.GetX(poly, 0), y = (wxCoord)pts.GetY(poly, 0); - + for(int i=0; i