X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdrawingview.cpp;h=ca352c2cb7c8de575b6a59b2e3f250d609f89f27;hb=9bf789d643e1885fee526a1d4d1e2648f02bbd86;hp=f50fca562d11ce438a51c61d70ef16e689ba92e1;hpb=acd27aa62a4c78b6aeee523e3145a8aa53f4bcde;p=architektonas diff --git a/src/drawingview.cpp b/src/drawingview.cpp index f50fca5..ca352c2 100644 --- a/src/drawingview.cpp +++ b/src/drawingview.cpp @@ -1,7 +1,8 @@ +// // drawingview.cpp // // Part of the Architektonas Project -// (C) 2011 Underground Software +// (C) 2011-2020 Underground Software // See the README and GPLv3 files for licensing and warranty information // // JLH = James Hammons @@ -16,11 +17,14 @@ // // - Redo rendering code to *not* use Qt's transform functions, as they are tied // to a left-handed system and we need a right-handed one. [DONE] +// - Fixed length tool doesn't work on lines [DONE] // // STILL TO BE DONE: // // - Lots of stuff // - Layer locking (hiding works) +// - Fixed angle tool doesn't work on lines +// - Make it so "dirty" flag reflects drawing state // // Uncomment this for debugging... @@ -44,54 +48,31 @@ DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent), // The value in the settings file will override this. - useAntialiasing(true), /*numSelected(0),*/ numHovered(0), shiftDown(false), + useAntialiasing(true), numHovered(0), shiftDown(false), ctrlDown(false), altDown(false), gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE), scale(1.0), offsetX(-10), offsetY(-10), document(true), - gridPixels(0), collided(false), hoveringIntersection(false), - dragged(NULL), draggingObject(false), angleSnap(false) + gridPixels(0), collided(false), scrollDrag(false), hoverPointValid(false), + hoveringIntersection(false), dragged(NULL), draggingObject(false), + angleSnap(false), dirty(false) { //wtf? doesn't work except in c++11??? document = { 0 }; setBackgroundRole(QPalette::Base); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); Global::gridSpacing = 12.0; // In base units (inch is default) -#if 0 - Line * line = new Line(Vector(5, 5), Vector(50, 40), &document); + + Line * line = new Line(Vector(5, 5), Vector(50, 40), 2.0, 0xFF7F00, LSDash); document.Add(line); - document.Add(new Line(Vector(50, 40), Vector(10, 83), &document)); - document.Add(new Line(Vector(10, 83), Vector(17, 2), &document)); - document.Add(new Circle(Vector(100, 100), 36, &document)); - document.Add(new Circle(Vector(50, 150), 49, &document)); - document.Add(new Arc(Vector(300, 300), 32, PI / 4.0, PI * 1.3, &document)), - document.Add(new Arc(Vector(200, 200), 60, PI / 2.0, PI * 1.5, &document)); -#if 1 - Dimension * dimension = new Dimension(Vector(0, 0), Vector(0, 0), DTLinear, &document); - line->SetDimensionOnLine(dimension); - document.Add(dimension); -#else - // Alternate way to do the above... - line->SetDimensionOnLine(); -#endif -#else - Line * line = new Line;//(Vector(5, 5), Vector(50, 40), &document); - line->p[0] = Vector(5, 5); - line->p[1] = Vector(50, 40); - line->type = OTLine; - line->thickness = 2.0; - line->style = LSDash; - line->color = 0xFF7F00; - line->layer = 0; - document.objects.push_back(line); - document.objects.push_back(new Line(Vector(50, 40), Vector(10, 83))); - document.objects.push_back(new Line(Vector(10, 83), Vector(17, 2))); - document.objects.push_back(new Circle(Vector(100, 100), 36)); - document.objects.push_back(new Circle(Vector(50, 150), 49)); - document.objects.push_back(new Arc(Vector(300, 300), 32, TAU / 8.0, TAU * 0.65)), - document.objects.push_back(new Arc(Vector(200, 200), 60, TAU / 4.0, TAU * 0.75)); - document.objects.push_back(new Dimension(Vector(50, 40), Vector(5, 5))); - document.objects.push_back(new Text(Vector(10, 83), "Here is some awesome text!")); -#endif + document.Add(new Line(Vector(50, 40), Vector(10, 83))); + document.Add(new Line(Vector(10, 83), Vector(17, 2))); + document.Add(new Circle(Vector(100, 100), 36)); + document.Add(new Circle(Vector(50, 150), 49)); + document.Add(new Arc(Vector(300, 300), 32, TAU / 8.0, TAU * 0.65)), + document.Add(new Arc(Vector(200, 200), 60, TAU / 4.0, TAU * 0.75)); + document.Add(new Text(Vector(10, 83), "Here is some awesome text!")); + + AddDimensionTo(line); /* Here we set the grid size in pixels--12 in this case. Initially, we have our @@ -139,16 +120,84 @@ need a thickness parameter similar to the "size" param for dimensions. (And now we do! :-) */ - SetGridSize(12); // This is in pixels + gridPixels = 12; //tmp + SetGridSize(12.0); // This is in pixels +} + + +void DrawingView::DrawBackground(Painter * painter) +{ + Point ul = Painter::QtToCartesianCoords(Vector(0, 0)); + Point br = Painter::QtToCartesianCoords(Vector(Global::screenSize.x, Global::screenSize.y)); + + painter->SetBrush(0xF0F0F0); + painter->SetPen(0xF0F0F0, 1, 1); + painter->DrawRect(QRectF(QPointF(ul.x, ul.y), QPointF(br.x, br.y))); + + double spacing = Global::gridSpacing; + + if (spacing < 1.0) + spacing = 1.0; + + double leftx = floor(ul.x / spacing) * spacing; + double bottomy = floor(br.y / spacing) * spacing; + + double w = (br.x - ul.x) + Global::gridSpacing + 1.0; + double h = (ul.y - br.y) + Global::gridSpacing + 1.0; + + Vector start(leftx, bottomy), size(w, h); + + if (Global::gridSpacing <= 0.015625) + DrawSubGrid(painter, 0xFFD2D2, 0.015625, start, size); + + if (Global::gridSpacing <= 0.03125) + DrawSubGrid(painter, 0xFFD2D2, 0.03125, start, size); + + if (Global::gridSpacing <= 0.0625) + DrawSubGrid(painter, 0xB8ECFF, 0.0625, start, size); + + if (Global::gridSpacing <= 0.125) + DrawSubGrid(painter, 0xB8ECFF, 0.125, start, size); + + if (Global::gridSpacing <= 0.25) + DrawSubGrid(painter, 0xDBDBFF, 0.25, start, size); + + if (Global::gridSpacing <= 0.5) + DrawSubGrid(painter, 0xDBDBFF, 0.5, start, size); + + painter->SetPen(QPen(QColor(0xD2, 0xD2, 0xFF), 2.0, Qt::SolidLine)); + + for(double i=0; i<=w; i+=spacing) + painter->DrawVLine(leftx + i); + + for(double i=0; i<=h; i+=spacing) + painter->DrawHLine(bottomy + i); +} + + +void DrawingView::DrawSubGrid(Painter * painter, uint32_t color, double step, Vector start, Vector size) +{ + painter->SetPen(color, 1, 1); + + for(double i=-step; i<=size.x; i+=step*2.0) + painter->DrawVLine(start.x + i); + + for(double i=-step; i<=size.y; i+=step*2.0) + painter->DrawHLine(start.y + i); } void DrawingView::SetGridSize(uint32_t size) { +#if 0 // Sanity check if (size == gridPixels) return; + // tmp... + if (size <= 1) + return; + // Recreate the background bitmap gridPixels = size; QPainter pmp(&gridBackground); @@ -164,13 +213,16 @@ void DrawingView::SetGridSize(uint32_t size) pmp.end(); // Set up new BG brush & zoom level (pixels per base unit) - Global::zoom = gridPixels / Global::gridSpacing; +// This shouldn't be done here, because it fucks up the scrollwheel zooming... +// Global::zoom = gridPixels / Global::gridSpacing; UpdateGridBackground(); +#endif } void DrawingView::UpdateGridBackground(void) { +#if 0 // Transform the origin to Qt coordinates Vector pixmapOrigin = Painter::CartesianToQtCoords(Vector()); int x = (int)pixmapOrigin.x; @@ -245,6 +297,70 @@ zero; so we do another modulus operation on the result to achieve this. pal.setBrush(backgroundRole(), QBrush(pm)); setAutoFillBackground(true); setPalette(pal); +#endif +} + + +void DrawingView::SetGridSize(double size) +{ +#if 0 + // Sanity check + if (size == gridPixelsF) + return; + + // tmp... + if (size <= 1) + return; + + // Recreate the background bitmap + gridPixelsF = size; + QPainter pmp(&gridBackground); + pmp.fillRect(0, 0, BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE, QColor(240, 240, 240)); + pmp.setPen(QPen(QColor(210, 210, 255), 2.0, Qt::SolidLine)); + + for(double i=0; i<(BACKGROUND_MAX_SIZE-1); i+=gridPixelsF) + { + pmp.drawLine(i, 0, i, (double)(BACKGROUND_MAX_SIZE - 1)); + pmp.drawLine(0, i, (double)(BACKGROUND_MAX_SIZE - 1), i); + } + + pmp.end(); + + // Set up new BG brush & zoom level (pixels per base unit) +// This shouldn't be done here, because it fucks up the scrollwheel zooming... +// Global::zoom = gridPixels / Global::gridSpacing; + UpdateGridBackgroundF(); +#endif +} + + +void DrawingView::UpdateGridBackgroundF(void) +{ +#if 0 + // Transform the origin to Qt coordinates + Vector pixmapOrigin = Painter::CartesianToQtCoords(Vector()); + int x = 0;// (int)pixmapOrigin.x; + int y = 0;// (int)pixmapOrigin.y; + // Use mod arithmetic to grab the correct swatch of background + +/* if (x < 0) + x = -x % gridPixels; + else + x = (gridPixels - (x % gridPixels)) % gridPixels; + + if (y < 0) + y = -y % gridPixels; + else + y = (gridPixels - (y % gridPixels)) % gridPixels;*/ + + // Here we grab a section of the bigger pixmap, so that the background + // *looks* like it's scrolling... + QPixmap pm = gridBackground.copy(x, y, gridPixelsF, gridPixelsF); + QPalette pal = palette(); + pal.setBrush(backgroundRole(), QBrush(pm)); + setAutoFillBackground(true); + setPalette(pal); +#endif } @@ -258,7 +374,7 @@ zero; so we do another modulus operation on the result to achieve this. void DrawingView::DeleteCurrentLayer(int layer) { //printf("DrawingView::DeleteCurrentLayer(): currentLayer = %i\n", layer); - std::vector::iterator i = document.objects.begin(); + VPVectorIter i = document.objects.begin(); while (i != document.objects.end()) { @@ -296,10 +412,9 @@ void DrawingView::HandleLayerToggle(void) // void DrawingView::HandleLayerSwap(int layer1, int layer2) { +// !!! FIX !!! This doesn't properly handle container contents... //printf("DrawingView: Swapping layers %i and %i.\n", layer1, layer2); - std::vector::iterator i; - - for(i=document.objects.begin(); i!=document.objects.end(); i++) + for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++) { Object * obj = (Object *)(*i); @@ -313,9 +428,7 @@ void DrawingView::HandleLayerSwap(int layer1, int layer2) void DrawingView::HandlePenWidth(float width) { - std::vector::iterator i = select.begin(); - - for(; i!=select.end(); i++) + for(VPVectorIter i=select.begin(); i!=select.end(); i++) { Object * obj = (Object *)(*i); obj->thickness = width; @@ -325,9 +438,7 @@ void DrawingView::HandlePenWidth(float width) void DrawingView::HandlePenStyle(int style) { - std::vector::iterator i = select.begin(); - - for(; i!=select.end(); i++) + for(VPVectorIter i=select.begin(); i!=select.end(); i++) { Object * obj = (Object *)(*i); obj->style = style; @@ -337,9 +448,7 @@ void DrawingView::HandlePenStyle(int style) void DrawingView::HandlePenColor(uint32_t color) { - std::vector::iterator i = select.begin(); - - for(; i!=select.end(); i++) + for(VPVectorIter i=select.begin(); i!=select.end(); i++) { Object * obj = (Object *)(*i); obj->color = color; @@ -347,6 +456,25 @@ void DrawingView::HandlePenColor(uint32_t color) } +void DrawingView::HandlePenStamp(void) +{ + VPVector flat = Flatten(select); + + for(VPVectorIter i=flat.begin(); i!=flat.end(); i++) + { + Object * obj = (Object *)(*i); + + if (obj->type != OTText) + obj->thickness = Global::penWidth; + + obj->style = Global::penStyle; + obj->color = Global::penColor; + } + + update(); +} + + QPoint DrawingView::GetAdjustedMousePosition(QMouseEvent * event) { // This is undoing the transform, e.g. going from client coords to local @@ -365,6 +493,18 @@ QPoint DrawingView::GetAdjustedClientPosition(int x, int y) } +void DrawingView::focusOutEvent(QFocusEvent * /*event*/) +{ +// printf("DrawingView::focusOutEvent()...\n"); + // Make sure all modkeys being held are marked as released when the app + // loses focus (N.B.: This only works because the app sets the focus policy + // of this object to something other than Qt::NoFocus) + shiftDown = ctrlDown = altDown = false; + scrollDrag = false; + setCursor(Qt::ArrowCursor); +} + + void DrawingView::paintEvent(QPaintEvent * /*event*/) { QPainter qtPainter(this); @@ -375,6 +515,8 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/) Global::viewportHeight = size().height(); + DrawBackground(&painter); + // Draw coordinate axes painter.SetPen(QPen(Qt::blue, 1.0, Qt::DotLine)); painter.DrawLine(0, -16384, 0, 16384); @@ -406,6 +548,9 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/) if (hoveringIntersection) painter.DrawHandle(intersectionPoint); + if (hoverPointValid) + painter.DrawHandle(hoverPoint); + if (!informativeText.isEmpty()) painter.DrawInformativeText(informativeText); } @@ -414,11 +559,15 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/) // // Renders objects in the passed in vector // -void DrawingView::RenderObjects(Painter * painter, std::vector & v, int layer, bool ignoreLayer/*= false*/) +/* +N.B.: Since we have "hoverPointValid" drawing regular object handles above, + we can probably do away with a lot of them that are being done down below. + !!! FIX !!! + [Well, it seems to work OK *except* when you move one of the points, then you get to see nothing. Is it worth fixing there to get rid of problems here? Have to investigate...] +*/ +void DrawingView::RenderObjects(Painter * painter, VPVector & v, int layer, bool ignoreLayer/*= false*/) { - std::vector::iterator i; - - for(i=v.begin(); i!=v.end(); i++) + for(VPVectorIter i=v.begin(); i!=v.end(); i++) { Object * obj = (Object *)(*i); float scaledThickness = Global::scale * obj->thickness; @@ -451,7 +600,11 @@ void DrawingView::RenderObjects(Painter * painter, std::vector & v, int if (obj->hitPoint[1]) painter->DrawHandle(obj->p[1]); + if (obj->hitObject) + painter->DrawSmallHandle(Geometry::Midpoint((Line *)obj)); + break; + case OTCircle: painter->SetBrush(QBrush(Qt::NoBrush)); painter->DrawEllipse(obj->p[0], obj->radius[0], obj->radius[0]); @@ -460,6 +613,7 @@ void DrawingView::RenderObjects(Painter * painter, std::vector & v, int painter->DrawHandle(obj->p[0]); break; + case OTArc: painter->DrawArc(obj->p[0], obj->radius[0], obj->angle[0], obj->angle[1]); @@ -473,6 +627,7 @@ void DrawingView::RenderObjects(Painter * painter, std::vector & v, int painter->DrawHandle(obj->p[0] + (Vector(cos(obj->angle[0] + obj->angle[1]), sin(obj->angle[0] + obj->angle[1])) * obj->radius[0])); break; + case OTDimension: { Dimension * d = (Dimension *)obj; @@ -533,10 +688,10 @@ void DrawingView::RenderObjects(Painter * painter, std::vector & v, int unit = Vector(d->lp[0], d->lp[1]).Unit(); - Point p1 = d->lp[0] + (ortho * 10.0 * scaledThickness); - Point p2 = d->lp[1] + (ortho * 10.0 * scaledThickness); - Point p3 = d->lp[0] + (ortho * 16.0 * scaledThickness); - Point p4 = d->lp[1] + (ortho * 16.0 * scaledThickness); + Point p1 = d->lp[0] + (ortho * (d->offset + (10.0 * scaledThickness))); + Point p2 = d->lp[1] + (ortho * (d->offset + (10.0 * scaledThickness))); + Point p3 = d->lp[0] + (ortho * (d->offset + (16.0 * scaledThickness))); + Point p4 = d->lp[1] + (ortho * (d->offset + (16.0 * scaledThickness))); Point p5 = d->p[0] + (ortho * 4.0 * scaledThickness); Point p6 = d->p[1] + (ortho * 4.0 * scaledThickness); @@ -591,6 +746,9 @@ void DrawingView::RenderObjects(Painter * painter, std::vector & v, int dimText = QString("%1' %2\"").arg(feet).arg(inches); } +/* +Where is the text offset? It looks like it's drawing in the center, but obviously it isn't. It isn't here, it's in Painter::DrawAngledText(). +*/ painter->DrawAngledText(ctr, angle, dimText, scaledThickness); if (d->hitObject) @@ -640,6 +798,7 @@ void DrawingView::RenderObjects(Painter * painter, std::vector & v, int break; } + case OTText: { Text * t = (Text *)obj; @@ -653,30 +812,36 @@ void DrawingView::RenderObjects(Painter * painter, std::vector & v, int painter->DrawTextObject(t->p[0], t->s.c_str(), scaledThickness, t->angle[0]); break; } + case OTSpline: { break; } + case OTPolygon: { break; } + case OTContainer: { // Containers require recursive rendering... Container * c = (Container *)obj; - RenderObjects(painter, (*c).objects, layer); +printf("About to render container: # objs=%i, layer=%i\n", (*c).objects.size(), layer); + RenderObjects(painter, (*c).objects, layer, ignoreLayer); //printf("Container extents: <%lf, %lf>, <%lf, %lf>\nsize: %i\n", r.l, r.t, r.r, r.b, c->objects.size()); // Containers also have special indicators showing they are selected if (c->selected || c->hitObject) { - Rect r = GetObjectExtents(obj); - painter->DrawRectCorners(r); +// Rect r = GetObjectExtents(obj); +// painter->DrawRectCorners(r); + painter->DrawRectCorners(Rect(c->p[0], c->p[1])); } break; } + default: break; } @@ -684,44 +849,45 @@ void DrawingView::RenderObjects(Painter * painter, std::vector & v, int } +// +// This toggles the selection being hovered (typically, only 1 object) +// void DrawingView::AddHoveredToSelection(void) { - std::vector::iterator i; - - for(i=document.objects.begin(); i!=document.objects.end(); i++) + for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++) { if (((Object *)(*i))->hovered) - ((Object *)(*i))->selected = true; +// ((Object *)(*i))->selected = true; + ((Object *)(*i))->selected = !((Object *)(*i))->selected; } } -void DrawingView::GetSelection(std::vector & v) +VPVector DrawingView::GetSelection(void) { - v.clear(); - std::vector::iterator i; + VPVector v; - for(i=document.objects.begin(); i!=document.objects.end(); i++) + for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++) { if (((Object *)(*i))->selected) v.push_back(*i); } + + return v; } -void DrawingView::GetHovered(std::vector & v) +VPVector DrawingView::GetHovered(void) { - v.clear(); - std::vector::iterator i; + VPVector v; - for(i=document.objects.begin(); i!=document.objects.end(); i++) + for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++) { if (((Object *)(*i))->hovered) -// { -//printf("GetHovered: adding object (%X) to hover... hp1=%s, hp2=%s, hl=%s\n", (*i), (((Line *)(*i))->hitPoint[0] ? "true" : "false"), (((Line *)(*i))->hitPoint[1] ? "true" : "false"), (((Line *)(*i))->hitObject ? "true" : "false")); v.push_back(*i); -// } } + + return v; } @@ -749,6 +915,12 @@ void DrawingView::ToolHandler(int mode, Point p) MirrorHandler(mode, p); else if (Global::tool == TTDimension) DimensionHandler(mode, p); + else if (Global::tool == TTTriangulate) + TriangulateHandler(mode, p); + else if (Global::tool == TTTrim) + TrimHandler(mode, p); + else if (Global::tool == TTParallel) + ParallelHandler(mode, p); } @@ -923,6 +1095,7 @@ void DrawingView::LineHandler(int mode, Point p) toolPoint[1] = p; break; + case ToolMouseMove: if (Global::toolState == TSNone) toolPoint[0] = p; @@ -930,6 +1103,7 @@ void DrawingView::LineHandler(int mode, Point p) toolPoint[1] = p; break; + case ToolMouseUp: if (Global::toolState == TSNone) { @@ -965,6 +1139,7 @@ void DrawingView::CircleHandler(int mode, Point p) toolPoint[1] = p; break; + case ToolMouseMove: if (Global::toolState == TSNone) toolPoint[0] = p; @@ -972,6 +1147,7 @@ void DrawingView::CircleHandler(int mode, Point p) toolPoint[1] = p; break; + case ToolMouseUp: if (Global::toolState == TSNone) { @@ -1013,6 +1189,7 @@ void DrawingView::ArcHandler(int mode, Point p) toolPoint[3] = p; break; + case ToolMouseMove: if (Global::toolState == TSNone) toolPoint[0] = p; @@ -1030,6 +1207,7 @@ void DrawingView::ArcHandler(int mode, Point p) } break; + case ToolMouseUp: if (Global::toolState == TSNone) { @@ -1082,7 +1260,8 @@ void DrawingView::RotateHandler(int mode, Point p) if (Global::toolState == TSNone) { toolPoint[0] = p; - SavePointsFrom(select, toolScratch); +// SavePointsFrom(select, toolScratch); + CopyObjects(select, toolScratch2); Global::toolState = TSPoint1; } else if (Global::toolState == TSPoint1) @@ -1091,6 +1270,7 @@ void DrawingView::RotateHandler(int mode, Point p) toolPoint[1] = p; break; + case ToolMouseMove: if ((Global::toolState == TSPoint1) || (Global::toolState == TSNone)) toolPoint[0] = p; @@ -1103,29 +1283,70 @@ void DrawingView::RotateHandler(int mode, Point p) angleSnap = true; double angle = Vector(toolPoint[0], toolPoint[1]).Angle(); - std::vector::iterator j = select.begin(); - std::vector::iterator i = toolScratch.begin(); + VPVectorIter j = select.begin(); +// std::vector::iterator i = toolScratch.begin(); + VPVectorIter i = toolScratch2.begin(); - for(; i!=toolScratch.end(); i++, j++) +// for(; i!=toolScratch.end(); i++, j++) + for(; i!=toolScratch2.end(); i++, j++) { - Object obj = *i; - Point p1 = Geometry::RotatePointAroundPoint(obj.p[0], toolPoint[0], angle); - Point p2 = Geometry::RotatePointAroundPoint(obj.p[1], toolPoint[0], angle); - Object * obj2 = (Object *)(*j); - obj2->p[0] = p1; - obj2->p[1] = p2; +// Object objT = *i; +// Point p1 = Geometry::RotatePointAroundPoint(objT.p[0], toolPoint[0], angle); +// Point p2 = Geometry::RotatePointAroundPoint(objT.p[1], toolPoint[0], angle); + Object * objT = (Object *)(*i); + Object * objS = (Object *)(*j); - if (obj.type == OTArc) + Point p1 = Geometry::RotatePointAroundPoint(objT->p[0], toolPoint[0], angle); + Point p2 = Geometry::RotatePointAroundPoint(objT->p[1], toolPoint[0], angle); + + objS->p[0] = p1; + objS->p[1] = p2; + +// if (objT.type == OTArc || objT.type == OTText) + if (objT->type == OTArc || objT->type == OTText) { - obj2->angle[0] = obj.angle[0] + angle; +// objS->angle[0] = objT.angle[0] + angle; + objS->angle[0] = objT->angle[0] + angle; - if (obj2->angle[0] > TAU) - obj2->angle[0] -= TAU; + if (objS->angle[0] > TAU) + objS->angle[0] -= TAU; + } +// else if (objT.type == OTContainer) + else if (objT->type == OTContainer) + { + // OK, this doesn't work because toolScratch only has points and nothing in the containers... [ACTUALLY... toolScratch is is a vector of type Object... which DOESN'T have an objects vector in it...] +// Container * c = (Container *)&objT; + Container * c = (Container *)objT; + Container * c2 = (Container *)objS; + VPVectorIter l = c->objects.begin(); + // TODO: Rotate items in the container + // TODO: Make this recursive + for(VPVectorIter k=c2->objects.begin(); k!=c2->objects.end(); k++, l++) + { + Object * obj3 = (Object *)(*k); + Object * obj4 = (Object *)(*l); + + p1 = Geometry::RotatePointAroundPoint(obj4->p[0], toolPoint[0], angle); + p2 = Geometry::RotatePointAroundPoint(obj4->p[1], toolPoint[0], angle); + + obj3->p[0] = p1; + obj3->p[1] = p2; +// obj3->angle[0] = objT.angle[0] + angle; + obj3->angle[0] = obj4->angle[0] + angle; + + if (obj3->angle[0] > TAU) + obj3->angle[0] -= TAU; + } + + Rect r = GetObjectExtents(objS); + c2->p[0] = r.TopLeft(); + c2->p[1] = r.BottomRight(); } } } break; + case ToolMouseUp: if (Global::toolState == TSPoint1) { @@ -1145,34 +1366,43 @@ void DrawingView::RotateHandler(int mode, Point p) if (ctrlDown) { // Stamp a copy of the selection at the current rotation & bail - std::vector temp; + VPVector temp; CopyObjects(select, temp); ClearSelected(temp); AddObjectsTo(document.objects, temp); - RestorePointsTo(select, toolScratch); +// RestorePointsTo(select, toolScratch); + RestorePointsTo(select, toolScratch2); return; } toolPoint[0] = p; Global::toolState = TSPoint1; - SavePointsFrom(select, toolScratch); +// SavePointsFrom(select, toolScratch); + DeleteContents(toolScratch2); + CopyObjects(select, toolScratch2); } break; + case ToolKeyDown: // Reset the selection if shift held down... if (shiftDown) - RestorePointsTo(select, toolScratch); +// RestorePointsTo(select, toolScratch); + RestorePointsTo(select, toolScratch2); break; + case ToolKeyUp: // Reset selection when key is let up if (!shiftDown) RotateHandler(ToolMouseMove, toolPoint[1]); break; + case ToolCleanup: - RestorePointsTo(select, toolScratch); +// RestorePointsTo(select, toolScratch); + RestorePointsTo(select, toolScratch2); + DeleteContents(toolScratch2); } } @@ -1194,6 +1424,7 @@ void DrawingView::MirrorHandler(int mode, Point p) toolPoint[1] = p; break; + case ToolMouseMove: if ((Global::toolState == TSPoint1) || (Global::toolState == TSNone)) toolPoint[0] = p; @@ -1206,7 +1437,7 @@ void DrawingView::MirrorHandler(int mode, Point p) angleSnap = true; double angle = Vector(toolPoint[0], toolPoint[1]).Angle(); - std::vector::iterator j = select.begin(); + VPVectorIter j = select.begin(); std::vector::iterator i = toolScratch.begin(); for(; i!=toolScratch.end(); i++, j++) @@ -1218,6 +1449,11 @@ void DrawingView::MirrorHandler(int mode, Point p) obj2->p[0] = p1; obj2->p[1] = p2; +/* +N.B.: When mirroring an arc thru a horizontal axis, this causes the arc to have + a negative start angle which makes it impossible to interact with. + !!! FIX !!! +*/ if (obj.type == OTArc) { // This is 2*mirror angle - obj angle - obj span @@ -1230,6 +1466,7 @@ void DrawingView::MirrorHandler(int mode, Point p) } break; + case ToolMouseUp: if (Global::toolState == TSPoint1) { @@ -1249,7 +1486,7 @@ void DrawingView::MirrorHandler(int mode, Point p) if (ctrlDown) { // Stamp a copy of the selection at the current rotation & bail - std::vector temp; + VPVector temp; CopyObjects(select, temp); ClearSelected(temp); AddObjectsTo(document.objects, temp); @@ -1263,18 +1500,21 @@ void DrawingView::MirrorHandler(int mode, Point p) } break; + case ToolKeyDown: // Reset the selection if shift held down... if (shiftDown) RestorePointsTo(select, toolScratch); break; + case ToolKeyUp: // Reset selection when key is let up if (!shiftDown) MirrorHandler(ToolMouseMove, toolPoint[1]); break; + case ToolCleanup: RestorePointsTo(select, toolScratch); } @@ -1292,6 +1532,7 @@ void DrawingView::DimensionHandler(int mode, Point p) toolPoint[1] = p; break; + case ToolMouseMove: if (Global::toolState == TSNone) toolPoint[0] = p; @@ -1299,6 +1540,7 @@ void DrawingView::DimensionHandler(int mode, Point p) toolPoint[1] = p; break; + case ToolMouseUp: if (Global::toolState == TSNone) { @@ -1323,10 +1565,265 @@ void DrawingView::DimensionHandler(int mode, Point p) } +void DrawingView::TriangulateHandler(int mode, Point/*p*/) +{ + switch (mode) + { + case ToolMouseDown: + { + // Skip if nothing hovered... + if (numHovered != 1) + break; + + VPVector hover = GetHovered(); + Object * obj = (Object *)hover[0]; + + // Skip if it's not a line... + if (obj->type != OTLine) + break; + + if (Global::toolState == TSNone) + toolObj[0] = obj; + else if (Global::toolState == TSPoint2) + toolObj[1] = obj; + else + toolObj[2] = obj; + + break; + } +#if 0 + case ToolMouseMove: + if (Global::toolState == TSNone) + toolPoint[0] = p; + else if (Global::toolState == TSPoint2) + toolPoint[1] = p; + else if (Global::toolState == TSPoint3) + { + toolPoint[2] = p; + angleSnap = true; + } + else + { + toolPoint[3] = p; + angleSnap = true; + } + + break; +#endif + case ToolMouseUp: + if (Global::toolState == TSNone) + { + Global::toolState = TSPoint2; + } + else if (Global::toolState == TSPoint2) + { +/* if (shiftDown) + { + // Key override is telling us to start arc at new center, not + // continue the current one. + toolPoint[0] = toolPoint[1]; + return; + }*/ + + Global::toolState = TSPoint3; + } + else + { + double len2 = Vector::Magnitude(toolObj[1]->p[0], toolObj[1]->p[1]); + double len3 = Vector::Magnitude(toolObj[2]->p[0], toolObj[2]->p[1]); + + Circle c1(toolObj[0]->p[0], len2); + Circle c2(toolObj[0]->p[1], len3); + + Geometry::CheckCircleToCircleIntersection((Object *)&c1, (Object *)&c2); + + // Only move lines if the triangle formed by them is not degenerate + if (Global::numIntersectPoints > 0) + { + toolObj[1]->p[0] = toolObj[0]->p[0]; + toolObj[1]->p[1] = Global::intersectPoint[0]; + + toolObj[2]->p[0] = Global::intersectPoint[0]; + toolObj[2]->p[1] = toolObj[0]->p[1]; + } + + Global::toolState = TSNone; + } + } +} + + +void DrawingView::TrimHandler(int mode, Point p) +{ +/* +n.b.: this code is lifted straight out of the old oo code. needs to be updated. +*/ + switch (mode) + { + case ToolMouseDown: + { +#if 0 + Object * toTrim = doc->lastObjectHovered; + + if (toTrim == NULL) + return; + + Vector v(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint); + + // Check to see which case we have... + // We're trimming point #1... + if (t == 0) + { + ((Line *)toTrim)->position = ((Line *)toTrim)->position + (v * u); + } + else if (u == 1.0) + { + ((Line *)toTrim)->endpoint = ((Line *)toTrim)->position + (v * t); + } + else + { + Point p1 = ((Line *)toTrim)->position + (v * t); + Point p2 = ((Line *)toTrim)->position + (v * u); + Point p3 = ((Line *)toTrim)->endpoint; + ((Line *)toTrim)->endpoint = p1; + Line * line = new Line(p2, p3); + emit ObjectReady(line); + } + + doc->lastObjectHovered = NULL; +#endif + } + break; + + case ToolMouseMove: + { +#if 0 + Object * toTrim = doc->lastObjectHovered; + t = 0, u = 1.0; + + if (toTrim == NULL) + return; + + if (toTrim->type != OTLine) + return; + + double pointHoveredT = Geometry::ParameterOfLineAndPoint(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint, point); + + std::vector::iterator i; + + for(i=doc->objects.begin(); i!=doc->objects.end(); i++) + { + // Can't trim against yourself... :-P + if (*i == toTrim) + continue; + + Object * trimAgainst = *i; + double t1;//, u1; + + if ((toTrim->type != OTLine) || (trimAgainst->type != OTLine)) + continue; + + int intersects = Geometry::Intersects((Line *)toTrim, (Line *)trimAgainst, &t1);//, &u1); + + if (intersects) + { + // Now what? We don't know which side to trim! + // ... now we do, we know which side of the Line we're on! + if ((t1 > t) && (t1 < pointHoveredT)) + t = t1; + + if ((t1 < u) && (t1 > pointHoveredT)) + u = t1; + } + } +#endif + // Bail out if nothing hovered... + if (numHovered != 1) + { + toolObj[0] = NULL; + return; + } + + VPVector hover = GetHovered(); + Object * obj = (Object *)hover[0]; + + // Skip if it's not a line... + if (obj->type != OTLine) + { + toolObj[0] = NULL; + return; + } + + toolObj[0] = obj; + double hoveredParam = Geometry::ParameterOfLineAndPoint(obj->p[0], obj->p[1], p); + + // Currently only deal with line against line trimming, can expand to + // others as well (line/circle, circle/circle, line/arc, etc) + VPVectorIter i; + for(i=document.objects.begin(); i!=document.objects.end(); i++) + { + obj = (Object *)(*i); + + if (obj == toolObj[0]) + continue; + else if (obj->type != OTLine) + continue; + + Geometry::CheckLineToLineIntersection(toolObj[0], obj); + + if (Global::numIntersectParams > 0) + { + // Mark the line segment somehow (the side the mouse is on) so that it can be drawn & trimmed when we hit ToolMouseDown. + } + } + } + break; + + case ToolMouseUp: + break; + + case ToolKeyDown: + break; + + case ToolKeyUp: + break; + + case ToolCleanup: + break; + } +} + + +void DrawingView::ParallelHandler(int mode, Point /*p*/) +{ + switch (mode) + { + case ToolMouseDown: + break; + + case ToolMouseMove: + break; + + case ToolMouseUp: + break; + + case ToolKeyDown: + break; + + case ToolKeyUp: + break; + + case ToolCleanup: + break; + } +} + + void DrawingView::mousePressEvent(QMouseEvent * event) { if (event->button() == Qt::LeftButton) { +//printf("mousePressEvent::Qt::LeftButton numHovered=%li\n", numHovered); Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y())); // Handle tool processing, if any @@ -1334,6 +1831,8 @@ void DrawingView::mousePressEvent(QMouseEvent * event) { if (hoveringIntersection) point = intersectionPoint; + else if (hoverPointValid) + point = hoverPoint; else if (Global::snapToGrid) point = SnapPointToGrid(point); @@ -1358,12 +1857,14 @@ void DrawingView::mousePressEvent(QMouseEvent * event) { AddHoveredToSelection(); update(); // needed?? - GetHovered(hover); // prolly needed - dragged = (Object *)hover[0]; +// GetHovered(hover); // prolly needed + VPVector hover2 = GetHovered(); + dragged = (Object *)hover2[0]; draggingObject = true; +//printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged, objName[dragged->type]); // Alert the pen widget - emit(ObjectSelected(dragged)); + emit ObjectSelected(dragged); // See if anything is using just a straight click on a handle if (HandleObjectClicked()) @@ -1377,16 +1878,35 @@ void DrawingView::mousePressEvent(QMouseEvent * event) // We do it *after*... why? (doesn't seem to confer any advantage...) if (hoveringIntersection) oldPoint = intersectionPoint; + else if (hoverPointValid) + oldPoint = hoverPoint; else if (Global::snapToGrid) oldPoint = SnapPointToGrid(point); + // Needed for fixed length handling + if (Global::fixedLength) + { + if (dragged->type == OTLine) + { + dragged->length = Vector::Magnitude(dragged->p[0], dragged->p[1]); + } + } + + if (dragged->type == OTCircle) + { + // Save for informative text, uh, er, informing + dragged->length = dragged->radius[0]; + } + return; } - // Didn't hit any object and not using a tool, so do a selection rectangle + // Didn't hit any object and not using a tool, so do a selection + // rectangle Global::selectionInProgress = true; Global::selection.setTopLeft(QPointF(point.x, point.y)); Global::selection.setBottomRight(QPointF(point.x, point.y)); + select = GetSelection(); } else if (event->button() == Qt::MiddleButton) { @@ -1400,6 +1920,13 @@ void DrawingView::mousePressEvent(QMouseEvent * event) void DrawingView::mouseMoveEvent(QMouseEvent * event) { + // It seems that wheelEvent() triggers this for some reason... + if (scrollWheelSeen) + { + scrollWheelSeen = false; + return; + } + Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y())); Global::selection.setBottomRight(QPointF(point.x, point.y)); // Only needs to be done here, as mouse down is always preceded by movement @@ -1430,19 +1957,35 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event) if (Global::selectionInProgress) { CheckObjectBounds(); + + // Make sure previously selected objects stay selected (CTRL held) + for(VPVectorIter i=select.begin(); i!=select.end(); i++) + ((Object *)(*i))->selected = true; + update(); return; } // Do object hit testing... bool needUpdate = HitTestObjects(point); - GetHovered(hover); + VPVector hover2 = GetHovered(); +#if 0 +{ +if (needUpdate) +{ + printf("mouseMoveEvent:: numHovered=%li, hover2.size()=%li\n", numHovered, hover2.size()); + + if (hover2.size() > 0) + printf(" (hover2[0]=$%llX, type=%s)\n", hover2[0], objName[((Object *)hover2[0])->type]); +} +} +#endif // Check for multi-hover... if (numHovered > 1) { //need to check for case where hover is over 2 circles and a 3rd's center... - Object * obj1 = (Object *)hover[0], * obj2 = (Object *)hover[1]; + Object * obj1 = (Object *)hover2[0], * obj2 = (Object *)hover2[1]; Geometry::Intersects(obj1, obj2); int numIntersecting = Global::numIntersectParams; @@ -1480,6 +2023,29 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event) intersectionPoint = v1; } } + else if (numHovered == 1) + { + Object * obj = (Object *)hover2[0]; + + if (obj->type == OTLine) + { +/* +Not sure that this is the best way to handle this, but it works(TM)... +Except when lines are overlapping, then it doesn't work... !!! FIX !!! +*/ + Point midpoint = Geometry::Midpoint((Line *)obj); + Vector v1 = Vector::Magnitude(midpoint, point); + + if ((v1.Magnitude() * Global::zoom) < 8.0) + { + QString text = tr("Midpoint <%1, %2>"); + informativeText = text.arg(midpoint.x).arg(midpoint.y); + hoverPointValid = true; + hoverPoint = midpoint; + needUpdate = true; + } + } + } // Handle object movement (left button down & over an object) if ((event->buttons() & Qt::LeftButton) && draggingObject && !Global::tool) @@ -1542,23 +2108,17 @@ void DrawingView::mouseReleaseEvent(QMouseEvent * event) return; } - if (Global::selectionInProgress) +// if (Global::selectionInProgress) Global::selectionInProgress = false; informativeText.clear(); // Should we be doing this automagically? Hmm... // Clear our vectors - select.clear(); - hover.clear(); +// select.clear(); +//// hover.clear(); - // Scoop 'em up - std::vector::iterator i; - - for(i=document.objects.begin(); i!=document.objects.end(); i++) - { - if (((Object *)(*i))->selected) - select.push_back(*i); - } + // Scoop 'em up (do we need to??? Seems we do, because keyboard movement uses it. Also, tools use it too. But we can move it out of here) + select = GetSelection(); draggingObject = false; } @@ -1572,30 +2132,28 @@ void DrawingView::mouseReleaseEvent(QMouseEvent * event) void DrawingView::wheelEvent(QWheelEvent * event) { - double zoomFactor = 1.25; - QSize sizeWin = size(); - Vector center(sizeWin.width() / 2.0, sizeWin.height() / 2.0); - center = Painter::QtToCartesianCoords(center); + double zoomFactor = 1.20; + scrollWheelSeen = true; - // This is not centering for some reason. Need to figure out why. :-/ - if (event->delta() > 0) + if (event->angleDelta().y() < 0) { - Vector newOrigin = center - ((center - Global::origin) / zoomFactor); - Global::origin = newOrigin; + if (Global::zoom > 400.0) + return; + Global::zoom *= zoomFactor; } else { - Vector newOrigin = center + ((-center + Global::origin) * zoomFactor); - Global::origin = newOrigin; + if (Global::zoom < 0.125) + return; + Global::zoom /= zoomFactor; } -// Global::gridSpacing = gridPixels / Painter::zoom; -// UpdateGridBackground(); - SetGridSize(Global::gridSpacing * Global::zoom); - update(); -// zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Global::gridSpacing)); + Point np = Painter::QtToCartesianCoords(oldScrollPoint); + Global::origin += (oldPoint - np); + + emit(NeedZoomUpdate()); } @@ -1612,6 +2170,8 @@ void DrawingView::keyPressEvent(QKeyEvent * event) else if (event->key() == Qt::Key_Alt) altDown = true; + // If there's a change in any of the modifier key states, pass it on to + // the current tool's handler if ((oldShift != shiftDown) || (oldCtrl != ctrlDown)) { if (Global::tool) @@ -1624,7 +2184,6 @@ void DrawingView::keyPressEvent(QKeyEvent * event) { scrollDrag = true; setCursor(Qt::SizeAllCursor); -// oldPoint = Vector(); oldPoint = oldScrollPoint; } @@ -1791,7 +2350,7 @@ Rect DrawingView::GetObjectExtents(Object * obj) case OTContainer: { Container * c = (Container *)obj; - std::vector::iterator i = c->objects.begin(); + VPVectorIter i = c->objects.begin(); rect = GetObjectExtents((Object *)*i); i++; @@ -1809,7 +2368,7 @@ Rect DrawingView::GetObjectExtents(Object * obj) void DrawingView::CheckObjectBounds(void) { - std::vector::iterator i; + VPVectorIter i; for(i=document.objects.begin(); i!=document.objects.end(); i++) { @@ -1869,7 +2428,8 @@ void DrawingView::CheckObjectBounds(void) bounds = bounds.normalized(); #endif - // If the end of the arc is before the beginning, add 360 degrees to it + // If the end of the arc is before the beginning, add 360 degrees + // to it if (end < start) end += TAU; @@ -1916,16 +2476,26 @@ void DrawingView::CheckObjectBounds(void) break; } - default: + case OTContainer: + { + Container * c = (Container *)obj; + + if (Global::selection.contains(c->p[0].x, c->p[0].y) && Global::selection.contains(c->p[1].x, c->p[1].y)) + c->selected = true; + break; } + +// default: +// break; + } } } bool DrawingView::HitTestObjects(Point point) { - std::vector::iterator i; + VPVectorIter i; numHovered = 0; bool needUpdate = false; hoverPointValid = false; @@ -1938,14 +2508,14 @@ bool DrawingView::HitTestObjects(Point point) if (draggingObject && (obj == dragged)) continue; - if (HitTest(obj, point)) + if (HitTest(obj, point) == true) needUpdate = true; if (obj->hovered) { numHovered++; //printf("MouseMove: OBJECT HOVERED (numHovered = %i)\n", numHovered); - emit(ObjectHovered(obj)); + emit ObjectHovered(obj); } } @@ -2084,8 +2654,13 @@ bool DrawingView::HitTest(Object * obj, Point point) Vector orthogonal = Vector::Normal(d->lp[0], d->lp[1]); // Get our line parallel to our points float scaledThickness = Global::scale * obj->thickness; - Point p1 = d->lp[0] + (orthogonal * 10.0 * scaledThickness); - Point p2 = d->lp[1] + (orthogonal * 10.0 * scaledThickness); +#if 1 + Point p1 = d->lp[0] + (orthogonal * (d->offset + (10.0 * scaledThickness))); + Point p2 = d->lp[1] + (orthogonal * (d->offset + (10.0 * scaledThickness))); +#else + Point p1 = d->lp[0] + (orthogonal * (10.0 + d->offset) * scaledThickness); + Point p2 = d->lp[1] + (orthogonal * (10.0 + d->offset) * scaledThickness); +#endif Point p3(p1, point); Vector v1(d->p[0], point); @@ -2121,7 +2696,6 @@ bool DrawingView::HitTest(Object * obj, Point point) else if ((hCS2Point.Magnitude() * Global::zoom) < 8.0) obj->hitPoint[4] = true; -// return (hitPoint1 || hitPoint2 || hitLine || hitFlipSwitch || hitChangeSwitch1 || hitChangeSwitch2 ? true : false); obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitPoint[3] || obj->hitPoint[4] || obj->hitObject ? true : false); if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHP3 != obj->hitPoint[3]) || (oldHP4 != obj->hitPoint[4]) || (oldHO != obj->hitObject)) @@ -2152,24 +2726,76 @@ bool DrawingView::HitTest(Object * obj, Point point) case OTContainer: { - // Containers must be recursively tested... + // Containers must be recursively tested... Or do they??? +/* +So the idea here is to flatten the structure, *then* test the objects within. Flattening includes the Containers as well; we can do this because it's pointers all the way down. +*/ +// bool oldHitObj = c->hitObject, oldHovered = c->hovered; +// Object * oldClicked = c->clicked; +/* +still need to compare old state to new state, and set things up based upon that... +likely we can just rely on the object itself and steal its state like we have in the commented out portion below; can prolly rewrite the HitTest() portion to be one line: needUpdate = HitTest(cObj, point); +Well, you could if there was only one object in the Container. But since there isn't, we have to keep the if HitTest() == true then needUpdate = true bit. Because otherwise, a false result anywhere will kill the needed update elsewhere. +*/ Container * c = (Container *)obj; c->hitObject = false; c->hovered = false; - std::vector::iterator i; + c->clicked = NULL; + + VPVector flat = Flatten(c); - for(i=c->objects.begin(); i!=c->objects.end(); i++) +//printf("HitTest::OTContainer (size=%li)\n", flat.size()); + for(VPVectorIter i=flat.begin(); i!=flat.end(); i++) { - Object * cObj = (Object *)*i; + Object * cObj = (Object *)(*i); - if (HitTest(cObj, point)) + // Skip the flattened containers (if any)... + if (cObj->type == OTContainer) + continue; + + // We do it this way instead of needUpdate = HitTest() because we + // are checking more than one object, and that way of doing will + // not return consistent results. + if (HitTest(cObj, point) == true) +// { +//printf("HitTest::OTContainer, subobj ($%llX) hit!\n", cObj); needUpdate = true; +// c->hitObject = true; +// c->clicked = cObj; +// c->hovered = true; +// } + // Same reasons for doing it this way here apply. if (cObj->hitObject == true) + { +//printf("HitTest::cObj->hitObject == true! ($%llX)\n", cObj); c->hitObject = true; + c->clicked = cObj; + }//*/ + + if (cObj->hitPoint[0] == true) + { +//printf("HitTest::cObj->hitObject == true! ($%llX)\n", cObj); + c->hitPoint[0] = true; + c->clicked = cObj; + }//*/ + + if (cObj->hitPoint[1] == true) + { +//printf("HitTest::cObj->hitObject == true! ($%llX)\n", cObj); + c->hitPoint[1] = true; + c->clicked = cObj; + }//*/ + + if (cObj->hitPoint[2] == true) + { +//printf("HitTest::cObj->hitObject == true! ($%llX)\n", cObj); + c->hitPoint[2] = true; + c->clicked = cObj; + }//*/ if (cObj->hovered == true) - c->hovered = true; + c->hovered = true;//*/ } break; @@ -2240,9 +2866,27 @@ void DrawingView::HandleObjectMovement(Point point) { case OTLine: if (obj->hitPoint[0]) + { + if (Global::fixedLength) + { + Vector line = point - obj->p[1]; + Vector unit = line.Unit(); + point = obj->p[1] + (unit * obj->length); + } + obj->p[0] = point; + } else if (obj->hitPoint[1]) + { + if (Global::fixedLength) + { + Vector line = point - obj->p[0]; + Vector unit = line.Unit(); + point = obj->p[0] + (unit * obj->length); + } + obj->p[1] = point; + } else if (obj->hitObject) { obj->p[0] += delta; @@ -2256,12 +2900,11 @@ void DrawingView::HandleObjectMovement(Point point) obj->p[0] = point; else if (obj->hitObject) { -//this doesn't work. we need to save this on mouse down for this to work correctly! -// double oldRadius = obj->radius[0]; + double oldRadius = obj->length; obj->radius[0] = Vector::Magnitude(obj->p[0], point); - QString text = QObject::tr("Radius: %1");//\nScale: %2%"); - informativeText = text.arg(obj->radius[0], 0, 'd', 4);//.arg(obj->radius[0] / oldRadius * 100.0, 0, 'd', 0); + QString text = QObject::tr("Radius: %1\nScale: %2%"); + informativeText = text.arg(obj->radius[0], 0, 'd', 4).arg(obj->radius[0] / oldRadius * 100.0, 0, 'd', 0); } break; @@ -2342,8 +2985,24 @@ void DrawingView::HandleObjectMovement(Point point) obj->p[1] = point; else if (obj->hitObject) { - obj->p[0] += delta; - obj->p[1] += delta; + // Move measurement lines in/out + if (shiftDown) + { + Dimension * d = (Dimension *)obj; + double dist = Geometry::DistanceToLineFromPoint(d->lp[0], d->lp[1], point); + float scaledThickness = Global::scale * obj->thickness; + // Looks like offset is 0 to +MAX, but line is at 10.0. So + // anything less than 10.0 should set the offset to 0. + d->offset = 0; + + if (dist > (10.0 * scaledThickness)) + d->offset = dist - (10.0 * scaledThickness); + } + else + { + obj->p[0] += delta; + obj->p[1] += delta; + } } break; @@ -2357,7 +3016,11 @@ void DrawingView::HandleObjectMovement(Point point) case OTContainer: // This is shitty, but works for now until I can code up something // nicer :-) - TranslateObject(obj, delta); +/* +The idea is to make it so whichever point on the object in question is being dragged becomes the snap point for the container; shouldn't be too difficult to figure out how to do this. +*/ +// TranslateObject(obj, delta); + TranslateContainer((Container *)obj, point, delta); break; default: @@ -2365,3 +3028,24 @@ void DrawingView::HandleObjectMovement(Point point) } } + +void DrawingView::AddDimensionTo(void * o) +{ + Object * obj = (Object *)o; + + switch (obj->type) + { + case OTLine: + document.Add(new Dimension(obj->p[0], obj->p[1])); + break; + case OTCircle: + break; + case OTEllipse: + break; + case OTArc: + break; + case OTSpline: + break; + } +} +