+ UpdateGridBackground();
+ update();
+ oldPoint = point;
+ return;
+ }
+
+ // If we're doing a selection rect, see if any objects are engulfed by it
+ // (implies left mouse button held down)
+ if (Global::selectionInProgress)
+ {
+ CheckObjectBounds();
+ update();
+ return;
+ }
+
+ // Handle object movement (left button down & over an object)
+ if ((event->buttons() & Qt::LeftButton) && numHovered && !Global::tool)
+ {
+ if (Global::snapToGrid)
+ point = SnapPointToGrid(point);
+
+ HandleObjectMovement(point);
+ update();
+ oldPoint = point;
+ return;
+ }
+
+ // Do object hit testing...
+ bool needUpdate = HitTestObjects(point);
+
+ // Check for multi-hover...
+ if (numHovered > 1)
+ {
+ GetHovered(hover);
+
+// double t, u;
+// int numIntersecting = Geometry::Intersects((Object *)hover[0], (Object *)hover[1], &t, &u);
+ Geometry::Intersects((Object *)hover[0], (Object *)hover[1]);
+ int numIntersecting = Global::numIntersectParams;
+ double t = Global::intersectParam[0];
+ double u = Global::intersectParam[1];
+
+ if (numIntersecting > 0)
+ {
+ Vector v1 = Geometry::GetPointForParameter((Object *)hover[0], t);
+ Vector v2 = Geometry::GetPointForParameter((Object *)hover[1], u);
+ QString text = tr("Intersection t=%1 (%3, %4), u=%2 (%5, %6)");
+ informativeText = text.arg(t).arg(u).arg(v1.x).arg(v1.y).arg(v2.x).arg(v2.y);
+
+ hoveringIntersection = true;
+ intersectionPoint = v1;
+ }
+
+ numIntersecting = Global::numIntersectPoints;
+
+ if (numIntersecting > 0)
+ {
+ Vector v1 = Global::intersectPoint[0];
+ QString text = tr("Intersection <%1, %2>");
+ informativeText = text.arg(v1.x).arg(v1.y);
+
+ hoveringIntersection = true;
+ intersectionPoint = v1;
+ }
+ }
+
+ // Do tool handling, if any are active...
+ if (Global::tool)
+ {
+ if (Global::snapToGrid)
+ point = SnapPointToGrid(point);
+
+ ToolHandler(ToolMouseMove, point);
+ }
+
+ // This is used to draw the tool crosshair...
+ oldPoint = point;
+
+ if (needUpdate || Global::tool)
+ update();
+}
+
+
+void DrawingView::mouseReleaseEvent(QMouseEvent * event)
+{
+ if (event->button() == Qt::LeftButton)
+ {
+//We need to update especially if nothing collided and the state needs to change. !!! FIX !!!
+//could set it up to use the document's update function (assumes that all object updates
+//are being reported correctly:
+// if (document.NeedsUpdate())
+ // Do an update if collided with at least *one* object in the document
+// if (collided)
+ update();
+
+ if (Global::tool)
+ {
+ Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+ ToolHandler(ToolMouseUp, point);
+ return;
+ }
+
+ if (Global::selectionInProgress)
+ Global::selectionInProgress = false;
+
+ informativeText.clear();
+// Should we be doing this automagically? Hmm...
+ // Clear our vectors
+ select.clear();
+ hover.clear();
+
+ // Scoop 'em up
+ std::vector<void *>::iterator i;
+
+ for(i=document.objects.begin(); i!=document.objects.end(); i++)
+ {
+ if (((Object *)(*i))->selected)
+ select.push_back(*i);
+
+//hmm, this is no good, too late to do any good :-P
+// if ((*i)->hovered)
+// hover.push_back(*i);
+ }
+ }
+ else if (event->button() == Qt::MiddleButton)
+ {
+ scrollDrag = false;
+ setCursor(Qt::ArrowCursor);
+ }
+}
+
+
+void DrawingView::wheelEvent(QWheelEvent * event)
+{
+ double zoomFactor = 1.25;
+ QSize sizeWin = size();
+ Vector center(sizeWin.width() / 2.0, sizeWin.height() / 2.0);
+ center = Painter::QtToCartesianCoords(center);
+
+ // This is not centering for some reason. Need to figure out why. :-/
+ if (event->delta() > 0)
+ {
+ Vector newOrigin = center - ((center - Global::origin) / zoomFactor);
+ Global::origin = newOrigin;
+ Global::zoom *= zoomFactor;
+ }
+ else
+ {
+ Vector newOrigin = center + ((-center + Global::origin) * zoomFactor);
+ Global::origin = newOrigin;
+ Global::zoom /= zoomFactor;
+ }
+
+// Global::gridSpacing = gridPixels / Painter::zoom;
+// UpdateGridBackground();
+ SetGridSize(Global::gridSpacing * Global::zoom);
+ update();
+// zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Global::gridSpacing));
+}
+
+
+void DrawingView::keyPressEvent(QKeyEvent * event)
+{
+ bool oldShift = shiftDown;
+ bool oldCtrl = ctrlDown;
+
+ if (event->key() == Qt::Key_Shift)
+ shiftDown = true;
+ else if (event->key() == Qt::Key_Control)
+ ctrlDown = true;
+
+ if ((oldShift != shiftDown) || (oldCtrl != ctrlDown))
+ {
+ if (Global::tool)
+ ToolHandler(ToolKeyDown, Point(0, 0));
+
+ update();
+ }
+}
+
+
+void DrawingView::keyReleaseEvent(QKeyEvent * event)
+{
+ bool oldShift = shiftDown;
+ bool oldCtrl = ctrlDown;
+
+ if (event->key() == Qt::Key_Shift)
+ shiftDown = false;
+ else if (event->key() == Qt::Key_Control)
+ ctrlDown = false;
+
+ if ((oldShift != shiftDown) || (oldCtrl != ctrlDown))
+ {
+ if (Global::tool)
+ ToolHandler(ToolKeyUp, Point(0, 0));
+
+ update();
+ }
+}
+
+
+//
+// This looks strange, but it's really quite simple: We want a point that's
+// more than half-way to the next grid point to snap there while conversely we
+// want a point that's less than half-way to to the next grid point then snap
+// to the one before it. So we add half of the grid spacing to the point, then
+// divide by it so that we can remove the fractional part, then multiply it
+// back to get back to the correct answer.
+//
+Point DrawingView::SnapPointToGrid(Point point)
+{
+ point += Global::gridSpacing / 2.0; // *This* adds to Z!!!
+ point /= Global::gridSpacing;
+ point.x = floor(point.x);//need to fix this for negative numbers...
+ point.y = floor(point.y);
+ point.z = 0; // Make *sure* Z doesn't go anywhere!!!
+ point *= Global::gridSpacing;
+ return point;
+}
+
+
+void DrawingView::CheckObjectBounds(void)
+{
+ std::vector<void *>::iterator i;
+ numSelected = 0;
+
+ for(i=document.objects.begin(); i!=document.objects.end(); i++)
+ {
+ Object * obj = (Object *)(*i);
+ obj->selected = false;
+
+ switch (obj->type)
+ {
+ case OTLine:
+ {
+ Line * l = (Line *)obj;
+
+ if (Global::selection.contains(l->p[0].x, l->p[0].y) && Global::selection.contains(l->p[1].x, l->p[1].y))
+ l->selected = true;
+
+ break;
+ }
+ case OTCircle:
+ {
+ Circle * c = (Circle *)obj;
+
+ if (Global::selection.contains(c->p[0].x - c->radius[0], c->p[0].y - c->radius[0]) && Global::selection.contains(c->p[0].x + c->radius[0], c->p[0].y + c->radius[0]))
+ c->selected = true;
+
+ break;
+ }
+ case OTArc:
+ {
+ Arc * a = (Arc *)obj;
+
+ double start = a->angle[0];
+ double end = start + a->angle[1];
+ QPointF p1(cos(start), sin(start));
+ QPointF p2(cos(end), sin(end));
+ QRectF bounds(p1, p2);
+
+#if 1
+ // Swap X/Y coordinates if they're backwards...
+ if (bounds.left() > bounds.right())
+ {
+ double temp = bounds.left();
+ bounds.setLeft(bounds.right());
+ bounds.setRight(temp);
+ }
+
+ if (bounds.bottom() > bounds.top())
+ {
+ double temp = bounds.bottom();
+ bounds.setBottom(bounds.top());
+ bounds.setTop(temp);
+ }
+#else
+ // Doesn't work as advertised! For shame!
+ bounds = bounds.normalized();
+#endif
+
+ // If the end of the arc is before the beginning, add 360 degrees to it
+ if (end < start)
+ end += 2.0 * PI;
+
+ // Adjust the bounds depending on which axes are crossed
+ if ((start < PI_OVER_2) && (end > PI_OVER_2))
+ bounds.setTop(1.0);
+
+ if ((start < PI) && (end > PI))
+ bounds.setLeft(-1.0);
+
+ if ((start < (PI + PI_OVER_2)) && (end > (PI + PI_OVER_2)))
+ bounds.setBottom(-1.0);
+
+ if ((start < (2.0 * PI)) && (end > (2.0 * PI)))
+ bounds.setRight(1.0);
+
+ if ((start < ((2.0 * PI) + PI_OVER_2)) && (end > ((2.0 * PI) + PI_OVER_2)))
+ bounds.setTop(1.0);
+
+ if ((start < (3.0 * PI)) && (end > (3.0 * PI)))
+ bounds.setLeft(-1.0);
+
+ if ((start < ((3.0 * PI) + PI_OVER_2)) && (end > ((3.0 * PI) + PI_OVER_2)))
+ bounds.setBottom(-1.0);
+
+ bounds.setTopLeft(QPointF(bounds.left() * a->radius[0], bounds.top() * a->radius[0]));
+ bounds.setBottomRight(QPointF(bounds.right() * a->radius[0], bounds.bottom() * a->radius[0]));
+ bounds.translate(a->p[0].x, a->p[0].y);
+
+ if (Global::selection.contains(bounds))
+ a->selected = true;
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (obj->selected)
+ numSelected++;