]> Shamusworld >> Repos - architektonas/commitdiff
More miscellaneous changes.
authorShamus Hammons <jlhamm@acm.org>
Mon, 6 Dec 2021 17:04:57 +0000 (11:04 -0600)
committerShamus Hammons <jlhamm@acm.org>
Mon, 6 Dec 2021 17:04:57 +0000 (11:04 -0600)
 - Implemented trim tool to work with line segments
 - Added delete tool
 - Added MRU list for files
 - Added ability to move objects to different layers
 - Fixed dimension tool to respect the line width when adding

src/applicationwindow.cpp
src/applicationwindow.h
src/drawingview.cpp
src/drawingview.h
src/geometry.cpp
src/global.cpp
src/global.h
src/mathconstants.h
src/utils.cpp
src/utils.h

index 2f78dfc61a6f92ac53229faba2091adea2ac1847..47f8149634a40942d86940167bb6afbd7b1eed86 100644 (file)
@@ -59,10 +59,8 @@ ApplicationWindow::ApplicationWindow():
 
        aboutWin = new AboutWindow(this);
 
-//     ((TTEdit *)qApp)->charWnd = new CharWindow(this);
-
        setWindowIcon(QIcon(":/res/atns-icon.png"));
-       setWindowTitle("Architektonas");
+//     setWindowTitle("Architektonas");
 
        CreateActions();
        CreateMenus();
@@ -98,6 +96,8 @@ ApplicationWindow::ApplicationWindow():
        statusBar()->showMessage(tr("Ready"));
 
        ReadSettings();
+       // Make sure the bottom left corner gets owned by the right side:
+       setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
        setUnifiedTitleAndToolBarOnMac(true);
        Global::font =  new QFont("Verdana", 15, QFont::Bold);
 
@@ -166,6 +166,21 @@ void ApplicationWindow::FileOpen(void)
        if (filename.isEmpty())
                return;
 
+       LoadFile(filename);
+}
+
+void ApplicationWindow::FileOpenRecent(void)
+{
+       QAction * action = qobject_cast<QAction *>(sender());
+
+       if (!action)
+               return;
+
+       LoadFile(action->data().toString());
+}
+
+void ApplicationWindow::LoadFile(QString filename)
+{
        FILE * file = fopen(filename.toUtf8().data(), "r");
 
        if (file == 0)
@@ -192,7 +207,6 @@ void ApplicationWindow::FileOpen(void)
                return;
        }
 
-//printf("FileOpen: container size = %li\n", container.objects.size());
        // Keep memory leaks from happening by getting rid of the old document
        DeleteContents(drawing->document.objects);
        emit ReloadLayers();
@@ -203,7 +217,8 @@ void ApplicationWindow::FileOpen(void)
        drawing->dirty = false;
        drawing->update();
        documentName = filename;
-       setWindowTitle(QString("Architektonas - %1").arg(documentName));
+//     setWindowTitle(QString("Architektonas - %1").arg(documentName));
+       AdjustMRU(filename);
        statusBar()->showMessage(tr("Drawing loaded."));
 }
 
@@ -241,7 +256,8 @@ void ApplicationWindow::FileSave(void)
        }
 
        drawing->dirty = false;
-       setWindowTitle(QString("Architektonas - %1").arg(documentName));
+//     setWindowTitle(QString("Architektonas - %1").arg(documentName));
+       AdjustMRU(documentName);
        statusBar()->showMessage(tr("Drawing saved."));
 }
 
@@ -305,16 +321,46 @@ void ApplicationWindow::HandlePrintRequest(QPrinter * printer)
        Global::screenSize = screenSizeSave;
 }
 
+//
+// Right-click menu
+//
 void ApplicationWindow::contextMenuEvent(QContextMenuEvent * event)
 {
        // Proof of concept, still need to code up the real thing
        QMenu menu(this);
+
+       VPVector hovered = drawing->GetHovered();
+
+       if ((drawing->select.size() > 0) || (hovered.size() > 0))
+       {
+               QMenu * layerMenu = menu.addMenu("To layer");
+
+               layerAct.clear();
+
+               for(int i=0; i<Global::numLayers; i++)
+               {
+                       QAction * act = new QAction(QIcon(), Global::layerName[i].c_str(), this);
+                       act->setData(i);
+                       layerMenu->addAction(act);
+                       layerAct.append(act);
+                       connect(act, SIGNAL(triggered()), this, SLOT(MoveToLayer()));
+               }
+       }
+
        menu.addAction(mirrorAct);
        menu.addAction(rotateAct);
        menu.addAction(trimAct);
        menu.exec(event->globalPos());
 }
 
+void ApplicationWindow::MoveToLayer(void)
+{
+       QAction * act = qobject_cast<QAction *>(sender());
+
+       drawing->MoveSelectedToLayer(act->data().toInt());
+       drawing->update();
+}
+
 void ApplicationWindow::SnapToGridTool(void)
 {
        Global::snapToGrid = snapToGridAct->isChecked();
@@ -334,7 +380,6 @@ void ApplicationWindow::DeleteTool(void)
 {
        // For this tool, we check first to see if anything is selected. If so, we
        // delete those and *don't* select the delete tool.
-//     if (drawing->numSelected > 0)
        if (drawing->select.size() > 0)
        {
                DeleteSelectedObjects(drawing->document.objects);
@@ -346,6 +391,7 @@ void ApplicationWindow::DeleteTool(void)
        // Otherwise, toggle the state of the tool
        ClearUIToolStatesExcept(deleteAct);
        SetInternalToolStates();
+       Global::toolSuppressCrosshair = true;
 }
 
 void ApplicationWindow::DimensionTool(void)
@@ -380,6 +426,7 @@ void ApplicationWindow::TrimTool(void)
 {
        ClearUIToolStatesExcept(trimAct);
        SetInternalToolStates();
+       Global::toolSuppressCrosshair = true;
 }
 
 void ApplicationWindow::ParallelTool(void)
@@ -479,7 +526,6 @@ void ApplicationWindow::UpdateZoom(void)
        else
                Global::gridSpacing = 0.015625;
 
-//     drawing->SetGridSize((double)(Global::gridSpacing * Global::zoom));
        drawing->update();
 
        zoomIndicator->setText(QString("Zoom: %1% Grid: %2\" BU: Inch").arg(Global::zoom * 100.0).arg(Global::gridSpacing));
@@ -506,9 +552,11 @@ void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
 void ApplicationWindow::SetInternalToolStates(void)
 {
        // We can be sure that if we've come here, then either an active tool is
-       // being deactivated, or a new tool is being created. In either case, the
-       // old tool needs to be deleted.
+       // being deactivated, or a new tool is being activated.  In either case,
+       // the tool state needs to be reset.  Also, we reset the crosshair
+       // suppression flag.
        Global::toolState = TSNone;
+       Global::toolSuppressCrosshair = false;
 
        if (addLineAct->isChecked())
                Global::tool = TTLine;
@@ -713,11 +761,8 @@ void ApplicationWindow::HandleGridSizeInBaseUnits(QString text)
        if (!ok || value == 0)
                return;
 
-//     drawing->gridSpacing = value;
-//     Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
        Global::gridSpacing = value;
        Global::zoom = drawing->gridPixels / Global::gridSpacing;
-//     drawing->UpdateGridBackground();
        drawing->update();
 }
 
@@ -891,6 +936,14 @@ void ApplicationWindow::CreateActions(void)
        group->addAction(addLineAct);
        group->addAction(addCircleAct);
        group->addAction(addArcAct);//*/
+
+       for(int i=0; i<MRU_MAX; i++)
+       {
+               QAction * rfa = new QAction(this);
+               rfa->setVisible(false);
+               connect(rfa, SIGNAL(triggered()), this, SLOT(FileOpenRecent()));
+               mruAct.append(rfa);
+       }
 }
 
 //
@@ -933,6 +986,14 @@ void ApplicationWindow::CreateMenus(void)
        QMenu * menu = menuBar()->addMenu(tr("&File"));
        menu->addAction(fileNewAct);
        menu->addAction(fileOpenAct);
+
+       QMenu * recentMenu = menu->addMenu(tr("Open &Recent"));
+
+       for(int i=0; i<MRU_MAX; i++)
+               recentMenu->addAction(mruAct.at(i));
+
+       UpdateMRUActionList();
+
        menu->addAction(fileSaveAct);
        menu->addAction(fileSaveAsAct);
        menu->addAction(fileCloseAct);
@@ -986,7 +1047,6 @@ void ApplicationWindow::CreateToolbars(void)
        toolbar->addAction(fileSaveAct);
        toolbar->addAction(fileSaveAsAct);
        toolbar->addAction(fileCloseAct);
-//     toolbar->addAction(exitAct);
 
        toolbar = addToolBar(tr("View"));
        toolbar->setObjectName("View");
@@ -995,7 +1055,6 @@ void ApplicationWindow::CreateToolbars(void)
 
        QSpinBox * spinbox = new QSpinBox;
        toolbar->addWidget(spinbox);
-//     QLineEdit * lineedit = new QLineEdit;
        toolbar->addWidget(baseUnitInput);
        toolbar->addWidget(dimensionSizeInput);
 
@@ -1039,7 +1098,6 @@ void ApplicationWindow::CreateToolbars(void)
        connect(pw, SIGNAL(WidthSelected(float)), drawing, SLOT(HandlePenWidth(float)));
        connect(pw, SIGNAL(StyleSelected(int)), drawing, SLOT(HandlePenStyle(int)));
        connect(pw, SIGNAL(ColorSelected(uint32_t)), drawing, SLOT(HandlePenColor(uint32_t)));
-//     connect(pw, SIGNAL(StampSelected(void)), drawing, SLOT(HandlePenStamp(QAction *)));
        connect(pw->tbStamp, SIGNAL(triggered(QAction *)), drawing, SLOT(HandlePenStamp(QAction *)));
        connect(pw->tbDropper, SIGNAL(triggered(QAction *)), drawing, SLOT(HandlePenDropper(QAction *)));
 }
@@ -1063,3 +1121,38 @@ void ApplicationWindow::WriteSettings(void)
        settings.setValue("useAntialiasing", drawing->useAntialiasing);
        settings.setValue("snapToGrid", snapToGridAct->isChecked());
 }
+
+void ApplicationWindow::UpdateMRUActionList(void)
+{
+       QStringList mruFilePaths = settings.value("recentFiles").toStringList();
+
+       int mruSize = (mruFilePaths.size() <= MRU_MAX ? mruFilePaths.size() : MRU_MAX);
+
+       for(int i=0; i<mruSize; i++)
+       {
+               QString filename = QFileInfo(mruFilePaths.at(i)).fileName();
+               mruAct.at(i)->setText(filename);
+               mruAct.at(i)->setData(mruFilePaths.at(i));
+               mruAct.at(i)->setVisible(true);
+       }
+
+       for(int i=mruSize; i<MRU_MAX; i++)
+               mruAct.at(i)->setVisible(false);
+}
+
+void ApplicationWindow::AdjustMRU(const QString & filePath)
+{
+       documentName = filePath;
+       setWindowFilePath(documentName);
+
+       QStringList mruFilePaths = settings.value("recentFiles").toStringList();
+       mruFilePaths.removeAll(filePath);
+       mruFilePaths.prepend(filePath);
+
+       while (mruFilePaths.size() > MRU_MAX)
+               mruFilePaths.removeLast();
+
+       settings.setValue("recentFiles", mruFilePaths);
+
+       UpdateMRUActionList();
+}
index a83e93722202aab35a421bccbdde683752d6d428..d5a9c08b2474572630066ce0af3fffdaec868803 100644 (file)
@@ -4,6 +4,10 @@
 #include <QtWidgets>
 #include <QPrinter>
 
+// Useful definitions
+
+#define MRU_MAX 10
+
 // Forward declarations
 
 class AboutWindow;
@@ -25,6 +29,7 @@ class ApplicationWindow: public QMainWindow
        private slots:
                void FileNew(void);
                void FileOpen(void);
+               void FileOpenRecent(void);
                void FileSave(void);
                void FileSaveAs(void);
                void PrintPreview(void);
@@ -59,11 +64,13 @@ class ApplicationWindow: public QMainWindow
                void EditPaste(void);
                void SelectAllObjects(void);
                void UpdateZoom(void);
+               void MoveToLayer(void);
 
        signals:
                void ReloadLayers(void);
 
        private:
+               void LoadFile(QString);
                void ClearUIToolStatesExcept(QAction *);
                void SetInternalToolStates(void);
                void CreateActions(void);
@@ -75,6 +82,8 @@ class ApplicationWindow: public QMainWindow
                void CreateToolbars(void);
                void ReadSettings(void);
                void WriteSettings(void);
+               void UpdateMRUActionList(void);
+               void AdjustMRU(const QString & filePath);
 
                AboutWindow * aboutWin;
                QLabel * zoomIndicator;
@@ -117,6 +126,9 @@ class ApplicationWindow: public QMainWindow
                QAction * editPasteAct;
                QAction * selectAllAct;
                QAction * printPreviewAct;
+//             QAction * moveToLayerAct;
+               QList<QAction *> layerAct;
+               QList<QAction *> mruAct;
 
                std::vector<void *> clipboard;
 
index 9acf00cd7e29fb1878b4c9c04a9c7d856c3fe68a..4ae021c6da555d0091cda947e9296638efb3e9c4 100644 (file)
@@ -159,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);
@@ -387,8 +387,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);
        }
 
@@ -773,6 +777,17 @@ VPVector DrawingView::GetHovered(bool exclude/*= false*/)
        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());
@@ -795,6 +810,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)
@@ -938,7 +955,7 @@ void DrawingView::ToolDraw(Painter * painter)
                                informativeText += " (Copy)";
                }
        }
-       if (Global::tool == TTDimension)
+       else if (Global::tool == TTDimension)
        {
                if (Global::toolState == TSNone)
                {
@@ -960,6 +977,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)
@@ -1489,7 +1520,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;
@@ -1497,7 +1528,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)
        {
@@ -1586,89 +1647,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.
-      Also: trim tool should ignore snap.
-*/
        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)
                {
@@ -1688,6 +1675,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)
@@ -1705,13 +1693,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:
@@ -1766,12 +1811,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;
                }
@@ -1779,7 +1818,6 @@ 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
@@ -1794,8 +1832,6 @@ void DrawingView::mousePressEvent(QMouseEvent * event)
 //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;
@@ -2081,16 +2117,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;
index 344428a804f65549c348eeb9ab3c43d612a7446f..136380c127960ae21fa626e04cc8a7beebf61e18 100644 (file)
@@ -25,6 +25,7 @@ class DrawingView: public QWidget
                void AddHoveredToSelection(void);
                VPVector GetSelection(void);
                VPVector GetHovered(bool exclude = false);
+               void MoveSelectedToLayer(int);
                void ToolHandler(int, Point);
                void ToolDraw(Painter *);
                void LineHandler(int, Point);
@@ -33,6 +34,7 @@ class DrawingView: public QWidget
                void RotateHandler(int, Point);
                void MirrorHandler(int, Point);
                void DimensionHandler(int, Point);
+               void DeleteHandler(int, Point);
                void TriangulateHandler(int, Point);
                void TrimHandler(int, Point);
                void ParallelHandler(int, Point);
@@ -110,6 +112,7 @@ class DrawingView: public QWidget
                VPVector toolScratch2;
                Point toolPoint[32];
                Object * toolObj[32];
+               double toolParam[32];
                Point intersectionPoint;
                Point hoverPoint;
                bool hoverPointValid;
index 86d1906f764851e7b28b5172292ab60aaac1b4f9..31c5257d8d0aa9f39c5924224f11d40359191d7e 100644 (file)
@@ -44,7 +44,7 @@ double Geometry::DistanceToLineFromPoint(Point tail, Point head, Point point)
        // Interpretation: given a line in the form x = a + tu, where u is the
        // unit vector of the line, a is the tail and t is a parameter which
        // describes the line, the distance of a point p to the line is given by:
-       // || (a - p) - ((a - p) . u) u ||
+       // || (a - p) - ((a - p)  u) u ||
        // We go an extra step: we set the sign to reflect which side of the line
        // it's on (+ == to the left if head points away from you, - == to the
        // right)
@@ -143,14 +143,37 @@ void Geometry::CheckLineToLineIntersection(Object * l1, Object * l2)
        double rxs = (r.x * s.y) - (s.x * r.y);
        double t, u;
 
+       // The angle is zero, so the lines probably overlap, or are parallel.  Either way, there is either INFINITE intersections, or zero.  Either way, the result is useless to us.  It does present a bit of an inconsistency though: lines connected at their endpoints that aren't at a zero angle will show as overlapping (the only case this could even REMOTELY be useful is when the angle between is 180°--not zero, as zero is the degenerate case).  :-P
        if (rxs == 0)
        {
-               double qpxr = (v1.x * r.y) - (r.x * v1.y);
+// WHY would you do this???  The lines overlap at an INFINITE number of points!
+// The assumption is that the angle is 180°, not 0°.
+               // If we want to detect the degenerate case, we can check the parameter of the endpoints of the one line to the other.  If any of the parameters are in (0, 1), then it's the degenerate case (we would check the endpoints of the shorter segment against the longer).
+/*             double qpxr = (v1.x * r.y) - (r.x * v1.y);
 
-               // Lines are parallel, so no intersection...
+               // Line segments are parallel, so no intersection...
                if (qpxr != 0)
                        return;
 
+               // Otherwise, the segments are colinear.  Need to check for the 0° (degenerate) vs the 180° (OK) case.
+               Object * larger = l1;
+               Object * smaller = l2;
+
+               if (r->Magnitude() < s->Magnitude())
+               {
+                       larger = l2;
+                       smaller = l1;
+               }
+
+               double param1 = ParameterOfLineAndPoint(larger->p[0], larger->p[1], smaller->p[0]);
+               double param2 = ParameterOfLineAndPoint(larger->p[0], larger->p[1], smaller->p[1]);
+
+               // Check for the degenerate case, and return if found
+               if ((param1 > 0 && param1 < 1.0) || (param2 > 0 && param2 < 1.0))
+                       return;
+
+////   or just use AngleBetween: Nah, won't work...
+
                // Check to see which endpoints are connected... Four possibilities:
                if (l1->p[0] == l2->p[0])
                        t = 0, u = 0;
@@ -160,7 +183,7 @@ void Geometry::CheckLineToLineIntersection(Object * l1, Object * l2)
                        t = 1.0, u = 0;
                else if (l1->p[1] == l2->p[1])
                        t = 1.0, u = 1.0;
-               else
+               else*/
                        return;
        }
        else
@@ -169,12 +192,24 @@ void Geometry::CheckLineToLineIntersection(Object * l1, Object * l2)
                u = ((v1.x * r.y) - (r.x * v1.y)) / rxs;
        }
 
+       // Check that the parameters are above the epsilon, otherwise clamp them to
+       // zero or one, as the case may be
+       if (fabs(t) < EPSILON)
+               t = 0;
+       else if (fabs(1.0 - t) < EPSILON)
+               t = 1.0;
+
+       if (fabs(u) < EPSILON)
+               u = 0;
+       else if (fabs(1.0 - u) < EPSILON)
+               u = 1.0;
+
        Global::intersectParam[0] = t;
        Global::intersectParam[1] = u;
 
        // If the parameters are in range, we have overlap!
        if ((t >= 0) && (t <= 1.0) && (u >= 0) && (u <= 1.0))
-               Global::numIntersectParams = 1;
+               Global::numIntersectParams = 2;
 }
 
 void Geometry::CheckCircleToCircleIntersection(Object * c1, Object * c2)
index 9ec2a7bba529187dd2040f1a6de2102a8a78a1dd..83236414a39fd1a4fdb2886891e1c493832b39db 100644 (file)
@@ -25,6 +25,7 @@ QRectF Global::selection;
 
 int Global::tool = TTNone;
 int Global::toolState = TSNone;
+bool Global::toolSuppressCrosshair = false;
 
 double Global::gridSpacing;
 Point Global::snapPoint;
index 796cc45944f8dd4bb2df10234554e29b199f39b3..18faa979093537e3a42e03201362220fa5ed3e56 100644 (file)
@@ -41,6 +41,7 @@ class Global
                static uint32_t objectID;
                static int tool;
                static int toolState;
+               static bool toolSuppressCrosshair;
 
                static Point origin;
                static double zoom;
index 2385861ea165d3b3db3a869a6f20ed4ce5398061..92afde1c147ad779de5a883ff475eaea5fadda7f 100644 (file)
@@ -27,3 +27,5 @@
 #define HALF_TAU           (TAU_2QTR)
 #define QTR_TAU            (TAU_1QTR)
 #define THREE_QTR_TAU      (TAU_3QTR)
+
+#define EPSILON            1e-6
index 53f5c73c75395c2d4094bc54953275b6f18038b5..c038f3670ee25598662841a19669e80956e5c9ac 100644 (file)
@@ -316,6 +316,25 @@ void RemoveSelectedObjects(VPVector & v)
        }
 }
 
+//
+// This is used to remove hovered objects from one container in order to delete
+// them from the same container.
+//
+void RemoveHoveredObjects(VPVector & v)
+{
+       VPVectorIter i = v.begin();
+
+       while (i != v.end())
+       {
+               Object * obj = (Object *)(*i);
+
+               if (obj->hovered)
+                       v.erase(i);
+               else
+                       i++;
+       }
+}
+
 void SavePointsFrom(VPVector & v, std::vector<Object> & save)
 {
        save.clear();
index 6fd59d0adaf3eca3bf93f99b47251b7f347f1bde..8c36c045bf917a7efe8f63e5d2e005b2c7e59f19 100644 (file)
@@ -18,6 +18,7 @@ void SelectAll(VPVector & v);
 void DeleteContents(VPVector & v);
 void DeleteSelectedObjects(VPVector & v);
 void RemoveSelectedObjects(VPVector & v);
+void RemoveHoveredObjects(VPVector & v);
 void SavePointsFrom(VPVector & v, std::vector<Object> & s);
 void RestorePointsTo(VPVector & v, std::vector<Object> & s);
 void RestorePointsTo(VPVector & v, VPVector & s);