+
+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();
+}
+
+
+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)
+{
+ 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(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;
+
+// drawing->gridSpacing = value;
+// Painter::zoom = drawing->gridPixels / drawing->gridSpacing;
+ Global::gridSpacing = value;
+ Global::zoom = drawing->gridPixels / Global::gridSpacing;
+ drawing->UpdateGridBackground();
+ drawing->update();
+}
+
+
+void ApplicationWindow::HandleDimensionSize(QString text)
+{
+/*
+This is the third input on the view toolbar; not sure what it was supposed to do...
+*/
+ // 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);
+ CopySelectedObjectsTo(clipboard, drawing->document.objects);
+ }
+}
+
+
+void ApplicationWindow::EditCut(void)
+{
+ if (drawing->select.size() > 0)
+ {
+ DeleteContents(clipboard);
+ MoveSelectedObjectsTo(clipboard, 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...
+ // This only moves the cut/copied from the clipboard to the drawing.
+// AddObjectsTo(drawing->document.objects, clipboard);
+ CopyObjects(clipboard, drawing->document.objects);
+ drawing->update();
+ }
+}
+
+