]> Shamusworld >> Repos - architektonas/blobdiff - src/drawingview.cpp
Fixed click selection and pen functionality.
[architektonas] / src / drawingview.cpp
index 5b0eeeef6b214c5d4ef4b67f8f87b6af9c2c195c..d8726fed5d91d82d86e2616877306ba2a1401cb6 100644 (file)
@@ -121,10 +121,7 @@ scaled the same way as the arrowheads.
 Need a way to scale line widths as well. :-/ Shouldn't be too difficult, just
 need a thickness parameter similar to the "size" param for dimensions. (And now
 we do! :-)
-
 */
-//     gridPixels = 12; //tmp???
-//     SetGridSize(12.0);      // This is in pixels
 }
 
 void DrawingView::DrawBackground(Painter * painter)
@@ -162,12 +159,12 @@ void DrawingView::DrawBackground(Painter * painter)
                DrawSubGrid(painter, 0xB8ECFF, 0.125, start, size);
 
        if (Global::gridSpacing <= 0.25)
-               DrawSubGrid(painter, 0xDBDBFF, 0.25, start, size);
+               DrawSubGrid(painter, 0xE6E6FF, 0.25, start, size);
 
        if (Global::gridSpacing <= 0.5)
-               DrawSubGrid(painter, 0xDBDBFF, 0.5, start, size);
+               DrawSubGrid(painter, 0xE6E6FF, 0.5, start, size);
 
-       painter->SetPen(QPen(QColor(0xD2, 0xD2, 0xFF), 2.0, Qt::SolidLine));
+       painter->SetPen(QPen(QColor(0xE0, 0xE0, 0xFF), 2.0, Qt::SolidLine));
 
        for(double i=0; i<=w; i+=spacing)
                painter->DrawVLine(leftx + i);
@@ -187,182 +184,6 @@ void DrawingView::DrawSubGrid(Painter * painter, uint32_t color, double step, Ve
                painter->DrawHLine(start.y + i);
 }
 
-#if 0
-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);
-       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(int i=0; i<(BACKGROUND_MAX_SIZE-1); i+=gridPixels)
-       {
-               pmp.drawLine(i, 0, i, BACKGROUND_MAX_SIZE - 1);
-               pmp.drawLine(0, i, 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;
-       UpdateGridBackground();
-#endif
-}
-
-void DrawingView::UpdateGridBackground(void)
-{
-#if 0
-       // Transform the origin to Qt coordinates
-       Vector pixmapOrigin = Painter::CartesianToQtCoords(Vector());
-       int x = (int)pixmapOrigin.x;
-       int y = (int)pixmapOrigin.y;
-       // Use mod arithmetic to grab the correct swatch of background
-/*
-Negative numbers still screw it up... Need to think about what we're
-trying to do here. The fact that it worked with 72 seems to have been pure luck.
-It seems the problem is negative numbers: We can't let that happen.
-When taking away the zero, it pops over 1 px at zero, then goes about 1/2 a
-grid at x<0.
-
-The bitmap looks like this:
-
-+---+---+---+---+---
-|   |   |   |   |
-|   |   |   |   |
-+---+---+---+---+---
-|   |   |   |   |
-|   |   |   |   |
-|   |   |   |   |
-
-@ x = 1, we want it to look like:
-
--+---+---+---+---+---
- |   |   |   |   |
- |   |   |   |   |
--+---+---+---+---+---
- |   |   |   |   |
- |   |   |   |   |
- |   |   |   |   |
-
-Which means we need to grab the sample from x = 3. @ x = -1:
-
----+---+---+---+---
-   |   |   |   |
-   |   |   |   |
----+---+---+---+---
-   |   |   |   |
-   |   |   |   |
-   |   |   |   |
-
-Which means we need to grab the sample from x = 1. Which means we have to take
-the mirror of the modulus of gridPixels.
-
-Doing a mod of a negative number is problematic: 1st, the compiler converts the
-negative number to an unsigned int, then it does the mod. Gets you wrong answers
-most of the time, unless you use a power of 2. :-P So what we do here is just
-take the modulus of the negation, which means we don't have to worry about
-mirroring it later.
-
-The positive case looks gruesome (and it is) but it boils down to this: We take
-the modulus of the X coordinate, then mirror it by subtraction from the
-maximum (in this case, gridPixels). This gives us a number in the range of 1 to
-gridPixels. But we need the case where the result equalling gridPixels to be
-zero; so we do another modulus operation on the result to achieve this.
-*/
-       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, gridPixels, gridPixels);
-       QPalette pal = palette();
-       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
-}
-#endif
-
 //
 // Basically, we just make a single pass through the Container. If the layer #
 // is less than the layer # being deleted, then do nothing. If the layer # is
@@ -372,7 +193,6 @@ void DrawingView::UpdateGridBackgroundF(void)
 //
 void DrawingView::DeleteCurrentLayer(int layer)
 {
-//printf("DrawingView::DeleteCurrentLayer(): currentLayer = %i\n", layer);
        VPVectorIter i = document.objects.begin();
 
        while (i != document.objects.end())
@@ -409,7 +229,6 @@ void DrawingView::HandleLayerToggle(void)
 //
 void DrawingView::HandleLayerSwap(int layer1, int layer2)
 {
-//printf("DrawingView: Swapping layers %i and %i.\n", layer1, layer2);
        HandleLayerSwap(layer1, layer2, document.objects);
 }
 
@@ -432,42 +251,6 @@ void DrawingView::HandleLayerSwap(int layer1, int layer2, VPVector & v)
        }
 }
 
-void DrawingView::HandlePenWidth(float width)
-{
-       for(VPVectorIter i=select.begin(); i!=select.end(); i++)
-       {
-               Object * obj = (Object *)(*i);
-               obj->thickness = width;
-       }
-
-       supressSelected = true;
-       update();
-}
-
-void DrawingView::HandlePenStyle(int style)
-{
-       for(VPVectorIter i=select.begin(); i!=select.end(); i++)
-       {
-               Object * obj = (Object *)(*i);
-               obj->style = style;
-       }
-
-       supressSelected = true;
-       update();
-}
-
-void DrawingView::HandlePenColor(uint32_t color)
-{
-       for(VPVectorIter i=select.begin(); i!=select.end(); i++)
-       {
-               Object * obj = (Object *)(*i);
-               obj->color = color;
-       }
-
-       supressSelected = true;
-       update();
-}
-
 void DrawingView::HandlePenStamp(QAction * action)
 {
        PenWidget * pw = (PenWidget *)action->parentWidget();
@@ -519,7 +302,6 @@ 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)
@@ -534,9 +316,6 @@ void DrawingView::focusInEvent(QFocusEvent * /*event*/)
                setCursor(curMarker);
        else if (Global::penDropper)
                setCursor(curDropper);
-//FocusOut already set this...
-//     else
-//             setCursor(Qt::ArrowCursor);
 }
 
 void DrawingView::paintEvent(QPaintEvent * /*event*/)
@@ -566,8 +345,12 @@ void DrawingView::paintEvent(QPaintEvent * /*event*/)
        // Do tool rendering, if any...
        if (Global::tool)
        {
-               painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine));
-               painter.DrawCrosshair(oldPoint);
+               if (Global::toolSuppressCrosshair == false)
+               {
+                       painter.SetPen(QPen(QColor(200, 100, 0, 255), 1.0, Qt::DashLine));
+                       painter.DrawCrosshair(oldPoint);
+               }
+
                ToolDraw(&painter);
        }
 
@@ -865,6 +648,11 @@ Where is the text offset?  It looks like it's drawing in the center, but obvious
                        break;
                }
 
+               case OTPolyline:
+               {
+                       break;
+               }
+
                case OTContainer:
                {
                        // Containers require recursive rendering...
@@ -893,16 +681,45 @@ Where is the text offset?  It looks like it's drawing in the center, but obvious
 }
 
 //
-// This toggles the selection being hovered (typically, only 1 object)
+// This toggles the selection being hovered (typically, only 1 object).  We
+// toggle because the CTRL key might be held, in which case, we want to
+// deselect a selected object.
 //
-void DrawingView::AddHoveredToSelection(void)
+void DrawingView::HandleSelectionClick(VPVector & v)
 {
-       for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
+       if (ctrlDown)
+       {
+               for(VPVectorIter i=v.begin(); i!=v.end(); i++)
+               {
+                       Object * obj = (Object *)(*i);
+
+                       if (obj->hovered)
+                               obj->selected = !obj->selected;
+               }
+
+               return;
+       }
+
+       for(VPVectorIter i=v.begin(); i!=v.end(); i++)
+               ((Object *)(*i))->selected = false;
+
+       // Check if the hover changed, and if so, reset the selection stack
+       if (oldHover.size() != v.size())
+       {
+               oldHover = v;
+               currentSelect = 0;
+       }
+       else
        {
-               if (((Object *)(*i))->hovered)
-//                     ((Object *)(*i))->selected = true;
-                       ((Object *)(*i))->selected = !((Object *)(*i))->selected;
+               // Select next object in the stack under the cursor
+               currentSelect++;
+
+               if (currentSelect >= v.size())
+                       currentSelect = 0;
        }
+
+       dragged = (Object *)v[currentSelect];
+       dragged->selected = true;
 }
 
 VPVector DrawingView::GetSelection(void)
@@ -918,23 +735,49 @@ VPVector DrawingView::GetSelection(void)
        return v;
 }
 
-VPVector DrawingView::GetHovered(void)
+//
+// When testing for hovered intersections, we need to be able to exclude some
+// objects which have funky characteristics or handles; so we allow for that
+// here.
+//
+VPVector DrawingView::GetHovered(bool exclude/*= false*/)
 {
        VPVector v;
 
        for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
        {
-               if (((Object *)(*i))->hovered)
+               Object * obj = (Object *)(*i);
+
+               if (obj->hovered)
+               {
+                       if (exclude
+                               && ((obj->type == OTDimension)
+                                       || ((obj->type == OTCircle) && (obj->hitPoint[0] == true))
+                                       || ((obj->type == OTArc) && (obj->hitPoint[0] == true))
+                                       || (draggingObject && (obj == dragged))))
+                               continue;
+
                        v.push_back(*i);
+               }
        }
 
        return v;
 }
 
+void DrawingView::MoveSelectedToLayer(int layer)
+{
+       for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
+       {
+               Object * obj = (Object *)(*i);
+
+               if (obj->selected || obj->hovered)
+                       obj->layer = layer;
+       }
+}
+
 void DrawingView::resizeEvent(QResizeEvent * /*event*/)
 {
        Global::screenSize = Vector(size().width(), size().height());
-//     UpdateGridBackground();
 }
 
 void DrawingView::ToolHandler(int mode, Point p)
@@ -954,6 +797,8 @@ void DrawingView::ToolHandler(int mode, Point p)
                MirrorHandler(mode, p);
        else if (Global::tool == TTDimension)
                DimensionHandler(mode, p);
+       else if (Global::tool == TTDelete)
+               DeleteHandler(mode, p);
        else if (Global::tool == TTTriangulate)
                TriangulateHandler(mode, p);
        else if (Global::tool == TTTrim)
@@ -1097,7 +942,7 @@ void DrawingView::ToolDraw(Painter * painter)
                                informativeText += " (Copy)";
                }
        }
-       if (Global::tool == TTDimension)
+       else if (Global::tool == TTDimension)
        {
                if (Global::toolState == TSNone)
                {
@@ -1119,6 +964,20 @@ void DrawingView::ToolDraw(Painter * painter)
                        informativeText = text.arg(absLength).arg(absAngle);
                }
        }
+       else if (Global::tool == TTTrim)
+       {
+               if (toolObj[0] != NULL)
+               {
+                       // We're assuming ATM it's just a line...
+                       painter->SetPen(0xAF0000, 3.0, LSSolid);
+                       painter->DrawLine(toolPoint[0], toolPoint[1]);
+//                     QString text = tr("Arc span: %1") + QChar(0x00B0);
+//                     informativeText = text.arg(RADIANS_TO_DEGREES * span);
+               }
+       }
+       else if (Global::tool == TTParallel)
+       {
+       }
 }
 
 void DrawingView::LineHandler(int mode, Point p)
@@ -1126,6 +985,19 @@ void DrawingView::LineHandler(int mode, Point p)
        switch (mode)
        {
        case ToolMouseDown:
+/*             toolObj[0] = NULL;
+
+               // Check to see if we can do a circle tangent snap
+               if (numHovered == 1)
+               {
+                       VPVector hover = GetHovered();
+                       Object * obj = (Object *)hover[0];
+
+                       // Save for later if the object clicked was a circle (need to check that it wasn't the center clicked on, because that will fuck up connecting centers of circles with lines... and now we do! :-)
+                       if ((obj->type == OTCircle) && (obj->hitPoint[0] == false))
+                               toolObj[0] = obj;
+               }*/
+
                if (Global::toolState == TSNone)
                        toolPoint[0] = p;
                else
@@ -1137,7 +1009,54 @@ void DrawingView::LineHandler(int mode, Point p)
                if (Global::toolState == TSNone)
                        toolPoint[0] = p;
                else
+               {
                        toolPoint[1] = p;
+/*                     bool isCircle = false;
+
+                       if (numHovered == 1)
+                       {
+                               VPVector hover = GetHovered();
+                               Object * obj = (Object *)hover[0];
+
+                               if ((obj->type == OTCircle) && (obj->hitPoint[0] == false))
+                               {
+                                       isCircle = true;
+                                       toolObj[1] = obj;
+                               }
+                       }
+
+                       // Adjust initial point if it's on a circle (tangent point)
+                       if (toolObj[0] != NULL)
+                       {
+                               if (isCircle)
+                               {
+                                       Geometry::FindTangents(toolObj[0], toolObj[1]);
+
+                                       if (Global::numIntersectPoints > 0)
+                                       {
+                                               toolPoint[0] = Global::intersectPoint[0];
+                                               toolPoint[1] = Global::intersectPoint[1];
+                                       }
+                               }
+                               else
+                               {
+                                       Geometry::FindTangents(toolObj[0], p);
+
+                                       if (Global::numIntersectPoints > 0)
+                                               toolPoint[0] = Global::intersectPoint[0];
+                               }
+                       }
+                       else
+                       {
+                               if (isCircle)
+                               {
+                                       Geometry::FindTangents(toolObj[1], toolPoint[0]);
+
+                                       if (Global::numIntersectPoints > 0)
+                                               toolPoint[1] = Global::intersectPoint[0];
+                               }
+                       }*/
+               }
 
                break;
 
@@ -1588,7 +1507,7 @@ void DrawingView::DimensionHandler(int mode, Point p)
                }
                else
                {
-                       Dimension * d = new Dimension(toolPoint[0], toolPoint[1], DTLinear);
+                       Dimension * d = new Dimension(toolPoint[0], toolPoint[1], DTLinear, 0, Global::penWidth);
                        d->layer = Global::activeLayer;
                        document.objects.push_back(d);
                        Global::toolState = TSNone;
@@ -1596,7 +1515,37 @@ void DrawingView::DimensionHandler(int mode, Point p)
        }
 }
 
-void DrawingView::TriangulateHandler(int mode, Point/*p*/)
+void DrawingView::DeleteHandler(int mode, Point /*p*/)
+{
+       switch (mode)
+       {
+       case ToolMouseDown:
+       {
+               VPVector hovered = GetHovered();
+
+               RemoveHoveredObjects(document.objects);
+               DeleteContents(hovered);
+       }
+               break;
+
+       case ToolMouseMove:
+               break;
+
+       case ToolMouseUp:
+               break;
+
+       case ToolKeyDown:
+               break;
+
+       case ToolKeyUp:
+               break;
+
+       case ToolCleanup:
+               break;
+       }
+}
+
+void DrawingView::TriangulateHandler(int mode, Point /*p*/)
 {
        switch (mode)
        {
@@ -1685,88 +1634,15 @@ void DrawingView::TriangulateHandler(int mode, Point/*p*/)
 
 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<Object *>::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)
                {
@@ -1786,6 +1662,7 @@ n.b.: this code is lifted straight out of the old oo code.  needs to be updated.
 
                toolObj[0] = obj;
                double hoveredParam = Geometry::ParameterOfLineAndPoint(obj->p[0], obj->p[1], p);
+               double t = 0, u = 1.0;
 
                // Currently only deal with line against line trimming, can expand to
                // others as well (line/circle, circle/circle, line/arc, etc)
@@ -1803,13 +1680,70 @@ n.b.: this code is lifted straight out of the old oo code.  needs to be updated.
 
                        if (Global::numIntersectParams > 0)
                        {
+                               // Skip endpoint-endpoint intersections
+                               if ((Global::numIntersectParams == 2)
+                                       && (Global::intersectParam[0] == 0
+                                               || Global::intersectParam[0] == 1.0)
+                                       && (Global::intersectParam[1] == 0
+                                               || Global::intersectParam[1] == 1.0))
+                                       continue;
+
                                // Mark the line segment somehow (the side the mouse is on) so that it can be drawn & trimmed when we hit ToolMouseDown.
+                               if ((Global::intersectParam[0] > t) && (Global::intersectParam[0] < hoveredParam))
+                                       t = Global::intersectParam[0];
+
+                               if ((Global::intersectParam[0] < u) && (Global::intersectParam[0] > hoveredParam))
+                                       u = Global::intersectParam[0];
                        }
                }
+
+               toolParam[0] = t;
+               toolParam[1] = u;
+               toolPoint[0] = Geometry::GetPointForParameter(toolObj[0], t);
+               toolPoint[1] = Geometry::GetPointForParameter(toolObj[0], u);
        }
                break;
 
        case ToolMouseUp:
+       {
+               // Bail out if there's no object to trim
+               if (toolObj[0] == NULL)
+                       return;
+
+               Vector v(toolObj[0]->p[0], toolObj[0]->p[1]);
+
+               // Check to see which case we have.
+               if ((toolParam[0] == 0) && (toolParam[1] == 1.0))
+               {
+                       // There was no intersection, so delete the object
+                       toolObj[0]->selected = true;
+                       DeleteSelectedObjects(document.objects);
+               }
+               else if (toolParam[0] == 0)
+               {
+                       // We delete the end near point #1
+                       toolObj[0]->p[0] = toolObj[0]->p[0] + (v * toolParam[1]);
+               }
+               else if (toolParam[1] == 1.0)
+               {
+                       // We delete the end near point #2
+                       toolObj[0]->p[1] = toolObj[0]->p[0] + (v * toolParam[0]);
+               }
+               else
+               {
+                       // We delete the segment in between, and create a new line in the process
+                       Point p1 = toolObj[0]->p[0] + (v * toolParam[0]);
+                       Point p2 = toolObj[0]->p[0] + (v * toolParam[1]);
+                       Point p3 = toolObj[0]->p[1];
+                       toolObj[0]->p[1] = p1;
+                       Line * l = new Line(p2, p3, toolObj[0]->thickness, toolObj[0]->color, toolObj[0]->style);
+                       document.objects.push_back(l);
+//                     Global::toolState = TSNone;
+               }
+
+               toolObj[0]->hitObject = toolObj[0]->hitPoint[0] = toolObj[0]->hitPoint[1] = false;
+               toolObj[0] = NULL;
+       }
                break;
 
        case ToolKeyDown:
@@ -1851,7 +1785,6 @@ 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
@@ -1864,12 +1797,6 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
                        else if (Global::snapToGrid)
                                point = SnapPointToGrid(point);
 
-                       //Also, may want to figure out if hovering over a snap point on an
-                       //object, snap to grid if not.
-                       // Snap to object point if valid...
-//                     if (Global::snapPointIsValid)
-//                             point = Global::snapPoint;
-
                        ToolHandler(ToolMouseDown, point);
                        return;
                }
@@ -1877,49 +1804,41 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
                // Clear the selection only if CTRL isn't being held on click
                if (!ctrlDown)
                        ClearSelected(document.objects);
-//                     ClearSelection();
 
-               // If any objects are being hovered on click, add them to the selection
-               // & return
+               // If any objects are being hovered on click, deal with 'em
                if (numHovered > 0)
                {
-                       AddHoveredToSelection();
-                       update();       // needed??
-//                     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
-// Maybe do this with an eyedropper tool on the pen bar?  [YES]
-//                     emit ObjectSelected(dragged);
                        if (Global::penDropper)
                        {
                                Global::penColor = dragged->color;
                                Global::penWidth = dragged->thickness;
                                Global::penStyle = dragged->style;
                                emit ObjectSelected(dragged);
-                               ClearSelected(document.objects);
                                return;
                        }
-
-                       if (Global::penStamp)
+                       else if (Global::penStamp)
                        {
                                dragged->color = Global::penColor;
                                dragged->thickness = Global::penWidth;
                                dragged->style = Global::penStyle;
                                return;
                        }
-
-                       // See if anything is using just a straight click on a handle
-                       if (HandleObjectClicked())
+                       // See if anything is using just a straight click on a custom
+                       // object handle (like Dimension objects)
+                       else if (HandleObjectClicked())
                        {
-                               draggingObject = false;
                                update();
                                return;
                        }
 
+                       draggingObject = true;
+                       HandleSelectionClick(hover2);
+                       update();       // needed??
+
                        // Needed for grab & moving objects
                        // We do it *after*... why? (doesn't seem to confer any advantage...)
                        if (hoveringIntersection)
@@ -2017,7 +1936,7 @@ void DrawingView::mouseMoveEvent(QMouseEvent * event)
 
        // Do object hit testing...
        bool needUpdate = HitTestObjects(point);
-       VPVector hover2 = GetHovered();
+       VPVector hover2 = GetHovered(true); // Exclude dimension objects and circle centers (probably need to add arc centers too) from hover (also dragged objects...)
 #if 0
 {
 if (needUpdate)
@@ -2031,9 +1950,9 @@ if (needUpdate)
 #endif
 
        // Check for multi-hover...
-       if (numHovered > 1)
+       if (hover2.size() > 1)
        {
-//need to check for case where hover is over 2 circles and a 3rd's center...
+//need to check for case where hover is over 2 circles and a 3rd's center (no longer a problem, I think)...
                Object * obj1 = (Object *)hover2[0], * obj2 = (Object *)hover2[1];
 
                Geometry::Intersects(obj1, obj2);
@@ -2072,7 +1991,7 @@ if (needUpdate)
                        intersectionPoint = v1;
                }
        }
-       else if (numHovered == 1)
+       else if (hover2.size() == 1)
        {
                Object * obj = (Object *)hover2[0];
 
@@ -2080,7 +1999,6 @@ if (needUpdate)
                {
 /*
 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);
@@ -2094,6 +2012,30 @@ Except when lines are overlapping, then it doesn't work... !!! FIX !!!
                                needUpdate = true;
                        }
                }
+               else if (obj->type == OTCircle)
+               {
+                       if ((draggingObject && (dragged->type == OTLine)) && (dragged->hitPoint[0] || dragged->hitPoint[1]))
+                       {
+                               Point p = (dragged->hitPoint[0] ? dragged->p[1] : dragged->p[0]);
+                               Geometry::FindTangents(obj, p);
+
+                               if (Global::numIntersectPoints > 0)
+                               {
+                                       hoveringIntersection = true;
+                                       intersectionPoint = Geometry::NearestTo(point, Global::intersectPoint[0], Global::intersectPoint[1]);
+                               }
+                       }
+                       else if ((Global::tool == TTLine) && (Global::toolState == TSPoint2))
+                       {
+                               Geometry::FindTangents(obj, toolPoint[0]);
+
+                               if (Global::numIntersectPoints > 0)
+                               {
+                                       hoveringIntersection = true;
+                                       intersectionPoint = Geometry::NearestTo(point, Global::intersectPoint[0], Global::intersectPoint[1]);
+                               }
+                       }
+               }
        }
 
        // Handle object movement (left button down & over an object)
@@ -2156,16 +2098,15 @@ void DrawingView::mouseReleaseEvent(QMouseEvent * event)
                        return;
                }
 
-//             if (Global::selectionInProgress)
-                       Global::selectionInProgress = false;
-
+               Global::selectionInProgress = false;
                informativeText.clear();
+
 // Should we be doing this automagically? Hmm...
                // Clear our vectors
 //             select.clear();
 ////           hover.clear();
 
-               // 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)
+               // 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 [where to???])
                select = GetSelection();
 
                draggingObject = false;
@@ -2434,7 +2375,7 @@ void DrawingView::CheckObjectBounds(void)
                switch (obj->type)
                {
                case OTLine:
-               case OTDimension:
+               case OTDimension: // N.B.: We don't check this properly...
                {
                        Line * l = (Line *)obj;