]> Shamusworld >> Repos - architektonas/blobdiff - src/drawingview.cpp
Fix scrollwheel zooming from walking all over the screen.
[architektonas] / src / drawingview.cpp
index 842c5b382fefd3a88f9e2936550a2fc3bd7ce95a..dc6853203769404357e2ac7ca05c5e57f9c7329f 100644 (file)
@@ -48,7 +48,7 @@
 
 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),
@@ -145,7 +145,8 @@ 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();
 }
 
@@ -239,7 +240,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<void *>::iterator i = document.objects.begin();
+       VPVectorIter i = document.objects.begin();
 
        while (i != document.objects.end())
        {
@@ -277,10 +278,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<void *>::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);
 
@@ -294,9 +294,7 @@ void DrawingView::HandleLayerSwap(int layer1, int layer2)
 
 void DrawingView::HandlePenWidth(float width)
 {
-       std::vector<void *>::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;
@@ -306,9 +304,7 @@ void DrawingView::HandlePenWidth(float width)
 
 void DrawingView::HandlePenStyle(int style)
 {
-       std::vector<void *>::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;
@@ -318,9 +314,7 @@ void DrawingView::HandlePenStyle(int style)
 
 void DrawingView::HandlePenColor(uint32_t color)
 {
-       std::vector<void *>::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;
@@ -328,6 +322,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
@@ -416,11 +429,9 @@ N.B.: Since we have "hoverPointValid" drawing regular object handles above,
       !!! 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, std::vector<void *> & v, int layer, bool ignoreLayer/*= false*/)
+void DrawingView::RenderObjects(Painter * painter, VPVector & v, int layer, bool ignoreLayer/*= false*/)
 {
-       std::vector<void *>::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;
@@ -541,10 +552,10 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int
 
                        unit = Vector(d->lp[0], d->lp[1]).Unit();
 
-                       Point p1 = d->lp[0] + (ortho * (10.0 + d->offset) * scaledThickness);
-                       Point p2 = d->lp[1] + (ortho * (10.0 + d->offset) * scaledThickness);
-                       Point p3 = d->lp[0] + (ortho * (16.0 + d->offset) * scaledThickness);
-                       Point p4 = d->lp[1] + (ortho * (16.0 + d->offset) * 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);
 
@@ -599,6 +610,9 @@ void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & 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)
@@ -699,61 +713,42 @@ printf("About to render container: # objs=%i, layer=%i\n", (*c).objects.size(),
 }
 
 
+//
+// This toggles the selection being hovered (typically, only 1 object)
+//
 void DrawingView::AddHoveredToSelection(void)
 {
-       std::vector<void *>::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<void *> & v)
+VPVector DrawingView::GetSelection(void)
 {
-       v.clear();
-       std::vector<void *>::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);
        }
-}
-
 
-#if 0
-void DrawingView::GetHovered(std::vector<void *> & v)
-{
-       v.clear();
-       std::vector<void *>::iterator i;
-
-       for(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;
 }
-#endif
 
 
-std::vector<void *> DrawingView::GetHovered(void)
+VPVector DrawingView::GetHovered(void)
 {
-       std::vector<void *> v;
-       std::vector<void *>::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;
@@ -1152,9 +1147,9 @@ void DrawingView::RotateHandler(int mode, Point p)
 
                        angleSnap = true;
                        double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
-                       std::vector<void *>::iterator j = select.begin();
+                       VPVectorIter j = select.begin();
 //                     std::vector<Object>::iterator i = toolScratch.begin();
-                       std::vector<void *>::iterator i = toolScratch2.begin();
+                       VPVectorIter i = toolScratch2.begin();
 
 //                     for(; i!=toolScratch.end(); i++, j++)
                        for(; i!=toolScratch2.end(); i++, j++)
@@ -1187,10 +1182,10 @@ void DrawingView::RotateHandler(int mode, Point p)
 //                                     Container * c = (Container *)&objT;
                                        Container * c = (Container *)objT;
                                        Container * c2 = (Container *)objS;
-                                       std::vector<void *>::iterator l = c->objects.begin();
+                                       VPVectorIter l = c->objects.begin();
                                        // TODO: Rotate items in the container
                                        // TODO: Make this recursive
-                                       for(std::vector<void *>::iterator k=c2->objects.begin(); k!=c2->objects.end(); k++, l++)
+                                       for(VPVectorIter k=c2->objects.begin(); k!=c2->objects.end(); k++, l++)
                                        {
                                                Object * obj3 = (Object *)(*k);
                                                Object * obj4 = (Object *)(*l);
@@ -1235,7 +1230,7 @@ void DrawingView::RotateHandler(int mode, Point p)
                        if (ctrlDown)
                        {
                                // Stamp a copy of the selection at the current rotation & bail
-                               std::vector<void *> temp;
+                               VPVector temp;
                                CopyObjects(select, temp);
                                ClearSelected(temp);
                                AddObjectsTo(document.objects, temp);
@@ -1306,7 +1301,7 @@ void DrawingView::MirrorHandler(int mode, Point p)
 
                        angleSnap = true;
                        double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
-                       std::vector<void *>::iterator j = select.begin();
+                       VPVectorIter j = select.begin();
                        std::vector<Object>::iterator i = toolScratch.begin();
 
                        for(; i!=toolScratch.end(); i++, j++)
@@ -1355,7 +1350,7 @@ N.B.: When mirroring an arc thru a horizontal axis, this causes the arc to have
                        if (ctrlDown)
                        {
                                // Stamp a copy of the selection at the current rotation & bail
-                               std::vector<void *> temp;
+                               VPVector temp;
                                CopyObjects(select, temp);
                                ClearSelected(temp);
                                AddObjectsTo(document.objects, temp);
@@ -1444,7 +1439,7 @@ void DrawingView::TriangulateHandler(int mode, Point/*p*/)
                if (numHovered != 1)
                        break;
 
-               std::vector<void *> hover = GetHovered();
+               VPVector hover = GetHovered();
                Object * obj = (Object *)hover[0];
 
                // Skip if it's not a line...
@@ -1613,7 +1608,7 @@ n.b.: this code is lifted straight out of the old oo code.  needs to be updated.
                        return;
                }
 
-               std::vector<void *> hover = GetHovered();
+               VPVector hover = GetHovered();
                Object * obj = (Object *)hover[0];
 
                // Skip if it's not a line...
@@ -1628,7 +1623,7 @@ n.b.: this code is lifted straight out of the old oo code.  needs to be updated.
 
                // Currently only deal with line against line trimming, can expand to
                // others as well (line/circle, circle/circle, line/arc, etc)
-               std::vector<void *>::iterator i;
+               VPVectorIter i;
                for(i=document.objects.begin(); i!=document.objects.end(); i++)
                {
                        obj = (Object *)(*i);
@@ -1692,7 +1687,7 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::LeftButton)
        {
-printf("mousePressEvent::Qt::LeftButton numHovered=%li\n", numHovered);
+//printf("mousePressEvent::Qt::LeftButton numHovered=%li\n", numHovered);
                Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
 
                // Handle tool processing, if any
@@ -1727,10 +1722,10 @@ printf("mousePressEvent::Qt::LeftButton numHovered=%li\n", numHovered);
                        AddHoveredToSelection();
                        update();       // needed??
 //                     GetHovered(hover);      // prolly needed
-                       std::vector<void *> hover2 = GetHovered();
+                       VPVector hover2 = GetHovered();
                        dragged = (Object *)hover2[0];
                        draggingObject = true;
-printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged, objName[dragged->type]);
+//printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged, objName[dragged->type]);
 
                        // Alert the pen widget
                        emit ObjectSelected(dragged);
@@ -1770,10 +1765,12 @@ printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged,
                        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)
        {
@@ -1787,6 +1784,13 @@ printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged,
 
 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
@@ -1817,14 +1821,19 @@ 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);
-       std::vector<void *> hover2 = GetHovered();
+       VPVector hover2 = GetHovered();
+#if 0
 {
 if (needUpdate)
 {
@@ -1834,6 +1843,7 @@ if (needUpdate)
                printf("                 (hover2[0]=$%llX, type=%s)\n", hover2[0], objName[((Object *)hover2[0])->type]);
 }
 }
+#endif
 
        // Check for multi-hover...
        if (numHovered > 1)
@@ -1962,23 +1972,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();
-
-               // Scoop 'em up
-               std::vector<void *>::iterator i;
+//             select.clear();
+////           hover.clear();
 
-               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;
        }
@@ -1993,26 +1997,31 @@ 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);
+       scrollWheelSeen = true;
 
-       // This is not centering for some reason. Need to figure out why. :-/
-       if (event->delta() > 0)
+       if (event->delta() < 0)
        {
-               Vector newOrigin = center - ((center - Global::origin) / zoomFactor);
-               Global::origin = newOrigin;
+               if (Global::zoom > 20.0)
+                       return;
+
                Global::zoom *= zoomFactor;
+//             Point np = Painter::QtToCartesianCoords(oldScrollPoint);
+//             Global::origin += (oldPoint - np);
        }
        else
        {
-               Vector newOrigin = center + ((-center + Global::origin) * zoomFactor);
-               Global::origin = newOrigin;
+               if (Global::zoom < 0.25)
+                       return;
+
                Global::zoom /= zoomFactor;
+//             Point np = Painter::QtToCartesianCoords(oldScrollPoint);
+//             Global::origin += (oldPoint - np);
        }
 
+       Point np = Painter::QtToCartesianCoords(oldScrollPoint);
+       Global::origin += (oldPoint - np);
+
 //     Global::gridSpacing = gridPixels / Painter::zoom;
-//     UpdateGridBackground();
        SetGridSize(Global::gridSpacing * Global::zoom);
        update();
 //     zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Global::gridSpacing));
@@ -2032,6 +2041,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)
@@ -2210,7 +2221,7 @@ Rect DrawingView::GetObjectExtents(Object * obj)
        case OTContainer:
        {
                Container * c = (Container *)obj;
-               std::vector<void *>::iterator i = c->objects.begin();
+               VPVectorIter i = c->objects.begin();
                rect = GetObjectExtents((Object *)*i);
                i++;
 
@@ -2228,7 +2239,7 @@ Rect DrawingView::GetObjectExtents(Object * obj)
 
 void DrawingView::CheckObjectBounds(void)
 {
-       std::vector<void *>::iterator i;
+       VPVectorIter i;
 
        for(i=document.objects.begin(); i!=document.objects.end(); i++)
        {
@@ -2355,7 +2366,7 @@ void DrawingView::CheckObjectBounds(void)
 
 bool DrawingView::HitTestObjects(Point point)
 {
-       std::vector<void *>::iterator i;
+       VPVectorIter i;
        numHovered = 0;
        bool needUpdate = false;
        hoverPointValid = false;
@@ -2514,8 +2525,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;
+#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);
@@ -2592,16 +2608,15 @@ 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;
                c->clicked = NULL;
 
-               std::vector<void *> flat = Flatten(c);
+               VPVector flat = Flatten(c);
 
 //printf("HitTest::OTContainer (size=%li)\n", flat.size());
-               for(std::vector<void *>::iterator i=flat.begin(); i!=flat.end(); i++)
+               for(VPVectorIter i=flat.begin(); i!=flat.end(); i++)
                {
                        Object * cObj = (Object *)(*i);
 
@@ -2643,6 +2658,13 @@ Well, you could if there was only one object in the Container.  But since there
                                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;//*/
                }
@@ -2834,8 +2856,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;