+ 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);
+ SetInternalToolStates();
+}
+
+
+void ApplicationWindow::TrimTool(void)
+{
+ ClearUIToolStatesExcept(trimAct);
+ SetInternalToolStates();
+}
+
+
+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 = 2.0;
+/*
+We need to find the center of the screen, then figure out where the new corner
+will be in the zoomed in window.
+
+So we know in Qt coords, the center is found via:
+size.width() / 2 --> xCenter
+size.height() / 2 --> yCenter
+
+transform x/yCenter to Cartesian coordinates. So far, so good.
+
+when zooming in, new origin will be (xCenter - origin.x) / 2, (yCenter - origin.y) / 2
+(after subtracting from center, that is...)
+*/
+ QSize size = drawing->size();
+ Vector center(size.width() / 2.0, size.height() / 2.0);
+//printf("Zoom in... Center=%.2f,%.2f; ", center.x, center.y);
+ center = Painter::QtToCartesianCoords(center);
+//printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
+ Vector newOrigin = center - ((center - Global::origin) / zoomFactor);
+//printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
+ Global::origin = newOrigin;
+
+//printf("Zoom in... level going from %02f to ", Painter::zoom);
+ // This just zooms leaving origin intact... should zoom in at the current
+ // center! [DONE]
+ Global::zoom *= zoomFactor;
+ Global::gridSpacing = drawing->gridPixels / Global::zoom;
+ drawing->UpdateGridBackground();
+ drawing->update();
+
+ zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Global::gridSpacing));
+ baseUnitInput->setText(QString("%1").arg(Global::gridSpacing));
+}
+
+
+void ApplicationWindow::ZoomOutTool(void)
+{
+/*
+Ok, real example.
+center = (436, 311)
+origin = (223, 160.5)
+newOrigin should be (-10, -10)
+Why isn't it?
+
+center - origin = (213, 150.5)
+origin - center = (-213, -150.5)
+x 2 = (-426, -301)
++ center = (-10, -10)
+
+*/
+ double zoomFactor = 2.0;
+ QSize size = drawing->size();
+ Vector center(size.width() / 2.0, size.height() / 2.0);
+//printf("Zoom out... Center=%.2f,%.2f; ", center.x, center.y);
+ center = Painter::QtToCartesianCoords(center);
+//printf("(%.2f,%.2f); origin=%.2f,%.2f; ", center.x, center.y, Painter::origin.x, Painter::origin.y);
+// Vector newOrigin = (center - Painter::origin) * zoomFactor;
+// Vector newOrigin = center - (Painter::origin * zoomFactor);
+ Vector newOrigin = center + ((Global::origin - center) * zoomFactor);
+//printf("newOrigin=%.2f,%.2f;\n", newOrigin.x, newOrigin.y);
+ Global::origin = newOrigin;
+//printf("Zoom out...\n");
+ // This just zooms leaving origin intact... should zoom out at the current
+ // center! [DONE]
+ Global::zoom /= zoomFactor;
+ Global::gridSpacing = drawing->gridPixels / Global::zoom;
+ drawing->UpdateGridBackground();
+ drawing->update();
+
+ zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Global::gridSpacing));
+ 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, 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 created. In either case, the
+ // old tool needs to be deleted.
+ Global::toolState = TSNone;
+
+ 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 (triangulateAct->isChecked())
+ Global::tool = TTTriangulate;
+ else
+ Global::tool = TTNone;
+
+ 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)
+{
+#if 0
+ int itemsSelected = drawing->document.ItemsSelected();
+
+ // If nothing selected, do nothing
+ if (itemsSelected == 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 (itemsSelected == 1)
+ {
+ Object * object = drawing->document.SelectedItem(0);
+
+#if 0
+if (object == NULL)
+ printf("SelectedItem = NULL!\n");
+else
+ printf("SelectedItem = %08X, type = %i\n", object, object->type);
+#endif
+
+ if (object == NULL || object->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 *)object)->SelectAll();
+ ((Container *)object)->MoveContentsTo(&(drawing->document));
+ drawing->document.Delete(object);
+ statusBar()->showMessage(tr("Objects ungrouped."));
+ }
+ // Otherwise, if it's a group of 2 or more objects (which can be groups too)
+ // group them and select the group
+ else if (itemsSelected > 1)
+ {
+ Container * container = new Container(Vector(), &(drawing->document));
+ drawing->document.MoveSelectedContentsTo(container);
+ drawing->document.Add(container);
+ container->DeselectAll();
+ container->state = OSSelected;
+ statusBar()->showMessage(QString(tr("Grouped %1 objects.")).arg(itemsSelected));
+ }
+#else
+#endif
+
+ 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)
+{