+ Global::fixedLength = fixLengthAct->isChecked();
+}
+
+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->select.size() > 0)
+ {
+ DeleteSelectedObjects(drawing->document.objects);
+ drawing->update();
+ deleteAct->setChecked(false);
+ return;
+ }
+
+ // Otherwise, toggle the state of the tool
+ ClearUIToolStatesExcept(deleteAct);
+ SetInternalToolStates();
+ Global::toolSuppressCrosshair = true;
+}
+
+void ApplicationWindow::DimensionTool(void)
+{
+ ClearUIToolStatesExcept(addDimensionAct);
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::RotateTool(void)
+{
+ ClearUIToolStatesExcept(rotateAct);
+
+ // Do tear-down if Rotate tool has been turned off
+ if (!rotateAct->isChecked())
+ drawing->RotateHandler(ToolCleanup, Point(0, 0));
+
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::MirrorTool(void)
+{
+ ClearUIToolStatesExcept(mirrorAct);
+
+ // Do tear-down if Rotate tool has been turned off
+ if (!mirrorAct->isChecked())
+ drawing->MirrorHandler(ToolCleanup, Point(0, 0));
+
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::TrimTool(void)
+{
+ ClearUIToolStatesExcept(trimAct);
+ SetInternalToolStates();
+ Global::toolSuppressCrosshair = true;
+}
+
+void ApplicationWindow::ParallelTool(void)
+{
+ ClearUIToolStatesExcept(parallelAct);
+ SetInternalToolStates();
+ Global::toolSuppressCrosshair = true;
+}
+
+void ApplicationWindow::TriangulateTool(void)
+{
+ ClearUIToolStatesExcept(triangulateAct);
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::AddLineTool(void)
+{
+ ClearUIToolStatesExcept(addLineAct);
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::AddCircleTool(void)
+{
+ ClearUIToolStatesExcept(addCircleAct);
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::AddArcTool(void)
+{
+ ClearUIToolStatesExcept(addArcAct);
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::AddPolygonTool(void)
+{
+ ClearUIToolStatesExcept(addPolygonAct);
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::AddSplineTool(void)
+{
+ ClearUIToolStatesExcept(addSplineAct);
+ SetInternalToolStates();
+}
+
+void ApplicationWindow::ZoomInTool(void)
+{
+ double zoomFactor = 1.20;
+ QSize size = drawing->size();
+ Vector center = Painter::QtToCartesianCoords(Vector(size.width() / 2.0, size.height() / 2.0));
+
+ Global::origin = center - ((center - Global::origin) / zoomFactor);
+ Global::zoom *= zoomFactor;
+
+ UpdateZoom();
+}
+
+void ApplicationWindow::ZoomOutTool(void)
+{
+ double zoomFactor = 1.20;
+ QSize size = drawing->size();
+ Vector center = Painter::QtToCartesianCoords(Vector(size.width() / 2.0, size.height() / 2.0));
+
+ Global::origin = center + ((Global::origin - center) * zoomFactor);
+ Global::zoom /= zoomFactor;
+
+ UpdateZoom();
+}
+
+void ApplicationWindow::UpdateZoom(void)
+{
+ // And now, a bunch of heuristics to select the right grid size--autogrid!
+ // :-P
+ if (Global::zoom < 0.25)
+ Global::gridSpacing = 48.0;
+ else if (Global::zoom >= 0.25 && Global::zoom < 0.50)
+ Global::gridSpacing = 36.0;
+ else if (Global::zoom >= 0.50 && Global::zoom < 1.00)
+ Global::gridSpacing = 24.0;
+ else if (Global::zoom >= 1.00 && Global::zoom < 2.00)
+ Global::gridSpacing = 12.0;
+ else if (Global::zoom >= 2.00 && Global::zoom < 4.00)
+ Global::gridSpacing = 6.0;
+ else if (Global::zoom >= 4.00 && Global::zoom < 8.00)
+ Global::gridSpacing = 3.0;
+ else if (Global::zoom >= 8.00 && Global::zoom < 16.00)
+ Global::gridSpacing = 1.0;
+ else if (Global::zoom >= 16.00 && Global::zoom < 32.00)
+ Global::gridSpacing = 0.5;
+ else if (Global::zoom >= 32.00 && Global::zoom < 64.00)
+ Global::gridSpacing = 0.25;
+ else if (Global::zoom >= 64.00 && Global::zoom < 128.00)
+ Global::gridSpacing = 0.125;
+ else if (Global::zoom >= 128.00 && Global::zoom < 256.00)
+ Global::gridSpacing = 0.0625;
+ else if (Global::zoom >= 256.00 && Global::zoom < 512.00)
+ Global::gridSpacing = 0.03125;
+ else
+ Global::gridSpacing = 0.015625;
+
+ drawing->update();
+
+ zoomIndicator->setText(QString("Zoom: %1% Grid: %2\" BU: Inch").arg(Global::zoom * 100.0).arg(Global::gridSpacing));
+
+ // This is the problem... Changing this causes the state to update itself again, screwing up the origin... !!! FIX !!! (commented out for now)
+// baseUnitInput->setText(QString("%1").arg(Global::gridSpacing));
+}
+
+void ApplicationWindow::ClearUIToolStatesExcept(QAction * exception)
+{
+ QAction * actionList[] = {
+ addArcAct, addLineAct, addCircleAct, addDimensionAct, addPolygonAct,
+ addSplineAct, deleteAct, rotateAct, mirrorAct, trimAct,
+ triangulateAct, parallelAct, 0
+ };
+
+ for(int i=0; actionList[i]!=0; i++)
+ {
+ if (actionList[i] != exception)
+ actionList[i]->setChecked(false);
+ }
+}
+
+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 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;
+ else if (addCircleAct->isChecked())
+ Global::tool = TTCircle;
+ else if (addArcAct->isChecked())
+ Global::tool = TTArc;
+ else if (addDimensionAct->isChecked())
+ Global::tool = TTDimension;
+ else if (addSplineAct->isChecked())
+ Global::tool = TTSpline;
+ else if (addPolygonAct->isChecked())
+ Global::tool = TTPolygon;
+ else if (deleteAct->isChecked())
+ Global::tool = TTDelete;
+ else if (mirrorAct->isChecked())
+ Global::tool = TTMirror;
+ else if (rotateAct->isChecked())
+ Global::tool = TTRotate;
+ else if (trimAct->isChecked())
+ Global::tool = TTTrim;
+ else if (parallelAct->isChecked())
+ Global::tool = TTParallel;
+ else if (triangulateAct->isChecked())
+ Global::tool = TTTriangulate;
+ else
+ Global::tool = TTNone;
+
+ cw->SetToolPrompt();//cw->cmdline);
+ drawing->update();
+}
+
+void ApplicationWindow::HelpAbout(void)
+{
+ aboutWin->show();
+}
+
+void ApplicationWindow::Settings(void)
+{
+ SettingsDialog dlg(this);
+ dlg.generalTab->antialiasChk->setChecked(drawing->useAntialiasing);
+
+ if (dlg.exec() == false)
+ return;
+
+ // Deal with stuff here (since user hit "OK" button...)
+ drawing->useAntialiasing = dlg.generalTab->antialiasChk->isChecked();
+ WriteSettings();
+}
+
+//
+// Group a bunch of selected objects (which can include other groups) together
+// or ungroup a selected group.
+//
+void ApplicationWindow::HandleGrouping(void)
+{
+ int numSelected = drawing->select.size();
+
+ // If nothing selected, do nothing
+ if (numSelected == 0)
+ {
+ statusBar()->showMessage(tr("No objects selected to make a group from."));
+ return;
+ }
+
+ // If it's a group that's selected, ungroup it and leave the objects in a
+ // selected state
+ if (numSelected == 1)
+ {
+ Object * obj = (Object *)drawing->select[0];
+
+ if (obj->type != OTContainer)
+ {
+ statusBar()->showMessage(tr("A group requires two or more selected objects."));
+ return;
+ }
+
+ // Need the parent of the group, we're assuming here that the parent is
+ // the drawing's document. Does it matter? Maybe...
+ // Could just stipulate that grouping like this only takes place where
+ // the parent of the group is the drawing's document. Makes life much
+ // simpler.
+ Container * c = (Container *)obj;
+ SelectAll(c->objects);
+ RemoveSelectedObjects(drawing->document.objects);
+ AddObjectsTo(drawing->document.objects, c->objects);
+ drawing->select.clear();
+ AddObjectsTo(drawing->select, c->objects);
+ delete c;
+ statusBar()->showMessage(tr("Objects ungrouped."));
+//printf("Ungroup: document size = %li\n", drawing->document.objects.size());
+ }
+ // Otherwise, if it's a group of 2 or more objects (which can be groups too)
+ // group them and select the group
+ else if (numSelected > 1)
+ {
+ Container * c = new Container();
+ MoveSelectedObjectsTo(c->objects, drawing->document.objects);
+ drawing->document.objects.push_back(c);
+ ClearSelected(c->objects);
+ c->selected = true;
+ c->layer = Global::activeLayer;
+
+ Rect r = drawing->GetObjectExtents((Object *)c);
+ c->p[0] = r.TopLeft();
+ c->p[1] = r.BottomRight();
+
+ drawing->select.clear();
+ drawing->select.push_back(c);
+ statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(numSelected));
+//printf("Group: document size = %li\n", drawing->document.objects.size());
+ }
+
+ drawing->update();
+}
+
+void ApplicationWindow::HandleConnection(void)
+{
+#if 0
+//double tt = Geometry::ParameterOfLineAndPoint(Vector(0, 0), Vector(10, 0), Vector(8, 2));
+//printf("Parameter of point @ (8,2) of line (0,0), (10,0): %lf\n", tt);
+ int itemsSelected = drawing->document.ItemsSelected();
+
+ // If nothing selected, do nothing
+ if (itemsSelected == 0)
+ {
+ statusBar()->showMessage(tr("No objects selected to connect."));
+ return;
+ }
+
+ // If one thing selected, do nothing
+ if (itemsSelected == 1)
+ {
+ statusBar()->showMessage(tr("Nothing to connect object to."));
+ return;
+ }
+
+ // This is O(n^2 / 2) :-P
+ for(int i=0; i<itemsSelected; i++)
+ {
+ Object * obj1 = drawing->document.SelectedItem(i);
+
+ for(int j=i+1; j<itemsSelected; j++)
+ {
+ Object * obj2 = drawing->document.SelectedItem(j);
+ double t, u, v, w;
+
+// if ((obj1->type != OTLine) || (obj2->type != OTLine))
+// continue;
+
+ if ((obj1->type == OTLine) && (obj2->type == OTLine))
+ {
+//printf("Testing objects for intersection (%X, %X)...\n", obj1, obj2);
+ int intersects = Geometry::Intersects((Line *)obj1, (Line *)obj2, &t, &u);
+//printf(" (%s) --> t=%lf, u=%lf\n", (intersects ? "true" : "FALSE"), t, u);
+
+ if (intersects)
+ {
+ //printf("Connecting objects (%X, %X)...\n", obj1, obj2);
+ obj1->Connect(obj2, u);
+ obj2->Connect(obj1, t);
+ }
+ }
+ else if (((obj1->type == OTLine) && (obj2->type == OTDimension))
+ || ((obj2->type == OTLine) && (obj1->type == OTDimension)))
+ {
+printf("Testing Line<->Dimension intersection...\n");
+ Line * line = (Line *)(obj1->type == OTLine ? obj1 : obj2);
+ Dimension * dim = (Dimension *)(obj1->type == OTDimension ? obj1 : obj2);
+
+ int intersects = Geometry::Intersects(line, dim, &t, &u);
+printf(" -> intersects = %i, t=%lf, u=%lf\n", intersects, t, u);
+
+ if (intersects)
+ {
+ obj1->Connect(obj2, u);
+ obj2->Connect(obj1, t);
+ }
+ }
+ }
+ }
+#else
+#endif
+}
+
+void ApplicationWindow::HandleDisconnection(void)
+{
+}
+
+void ApplicationWindow::HandleGridSizeInPixels(int /*size*/)
+{
+// drawing->SetGridSize((uint32_t)size);
+ drawing->update();
+}
+
+void ApplicationWindow::HandleGridSizeInBaseUnits(QString text)
+{
+ // Parse the text...
+ bool ok;
+ double value = text.toDouble(&ok);
+
+ // Nothing parsable to a double, so quit...
+ if (!ok || value == 0)
+ return;
+
+ Global::gridSpacing = value;
+ Global::zoom = drawing->gridPixels / Global::gridSpacing;
+ drawing->update();
+}
+
+void ApplicationWindow::HandleDimensionSize(QString text)
+{
+/*
+This is the third input on the view toolbar; not sure what it was supposed to do... (resize all dimensions in the drawing?)
+*/
+ // Parse the text...
+ bool ok;
+ double value = text.toDouble(&ok);
+
+ // Nothing parsable to a double, so quit...
+ if (!ok || value == 0)
+ return;
+
+// drawing->document.ResizeAllDimensions(value);
+ drawing->update();
+}
+
+void ApplicationWindow::EditCopy(void)
+{
+ if (drawing->select.size() > 0)
+ {
+ DeleteContents(clipboard);
+ clipboard = CopySelectedObjects(drawing->document.objects);
+ }
+}
+
+void ApplicationWindow::EditCut(void)
+{
+ if (drawing->select.size() > 0)
+ {
+ DeleteContents(clipboard);
+ clipboard = MoveSelectedObjectsFrom(drawing->document.objects);
+ drawing->update();
+ }
+}
+
+void ApplicationWindow::EditPaste(void)
+{
+ if (clipboard.size() > 0)
+ {
+ // We want to maybe make it so that the pasted objects are being moved in a "mouse drag" state...
+ ClearSelected(drawing->document.objects);
+ SelectAll(clipboard);
+ drawing->document.Add(CopyObjects(clipboard));
+ drawing->update();
+ }
+}
+
+//
+// Select all *visible* objects. If an object is on a layer that is not
+// visible, skip it.
+//
+void ApplicationWindow::SelectAllObjects(void)
+{
+ // Set object's state & update the drawing
+ SelectAll(drawing->document.objects);
+ drawing->update();