DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
// The value in the settings file will override this.
useAntialiasing(true), /*numSelected(0),*/ numHovered(0), shiftDown(false),
- ctrlDown(false),
+ ctrlDown(false), altDown(false),
gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
scale(1.0), offsetX(-10), offsetY(-10), document(true),
- gridPixels(0), collided(false), hoveringIntersection(false)
+ gridPixels(0), collided(false), hoveringIntersection(false),
+ dragged(NULL), draggingObject(false), angleSnap(false)
{
//wtf? doesn't work except in c++11??? document = { 0 };
setBackgroundRole(QPalette::Base);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
Global::gridSpacing = 12.0; // In base units (inch is default)
-
#if 0
Line * line = new Line(Vector(5, 5), Vector(50, 40), &document);
document.Add(line);
}
+void DrawingView::HandlePenWidth(float width)
+{
+ std::vector<void *>::iterator i = select.begin();
+
+ for(; i!=select.end(); i++)
+ {
+ Object * obj = (Object *)(*i);
+ obj->thickness = width;
+ }
+}
+
+
+void DrawingView::HandlePenStyle(int style)
+{
+ std::vector<void *>::iterator i = select.begin();
+
+ for(; i!=select.end(); i++)
+ {
+ Object * obj = (Object *)(*i);
+ obj->style = style;
+ }
+}
+
+
+void DrawingView::HandlePenColor(uint32_t color)
+{
+ std::vector<void *>::iterator i = select.begin();
+
+ for(; i!=select.end(); i++)
+ {
+ Object * obj = (Object *)(*i);
+ obj->color = color;
+ }
+}
+
+
QPoint DrawingView::GetAdjustedMousePosition(QMouseEvent * event)
{
// This is undoing the transform, e.g. going from client coords to local
Vector v(d->p[0], d->p[1]);
double angle = v.Angle();
Vector unit = v.Unit();
- Vector linePt1 = d->p[0], linePt2 = d->p[1];
+ d->lp[0] = d->p[0], d->lp[1] = d->p[1];
Vector ortho;
double x1, y1, length;
angle = QTR_TAU;
}
- linePt1.x = linePt2.x = x1;
+ d->lp[0].x = d->lp[1].x = x1;
length = fabs(d->p[0].y - d->p[1].y);
}
else if (d->subtype == DTLinearHorz)
angle = HALF_TAU;
}
- linePt1.y = linePt2.y = y1;
+ d->lp[0].y = d->lp[1].y = y1;
length = fabs(d->p[0].x - d->p[1].x);
}
else if (d->subtype == DTLinear)
{
- angle = Vector(linePt1, linePt2).Angle();
- ortho = Vector::Normal(linePt1, linePt2);
+ angle = Vector(d->lp[0], d->lp[1]).Angle();
+ ortho = Vector::Normal(d->lp[0], d->lp[1]);
length = v.Magnitude();
}
- unit = Vector(linePt1, linePt2).Unit();
+ unit = Vector(d->lp[0], d->lp[1]).Unit();
- Point p1 = linePt1 + (ortho * 10.0 * scaledThickness);
- Point p2 = linePt2 + (ortho * 10.0 * scaledThickness);
- Point p3 = linePt1 + (ortho * 16.0 * scaledThickness);
- Point p4 = linePt2 + (ortho * 16.0 * scaledThickness);
+ Point p1 = d->lp[0] + (ortho * 10.0 * scaledThickness);
+ Point p2 = d->lp[1] + (ortho * 10.0 * scaledThickness);
+ Point p3 = d->lp[0] + (ortho * 16.0 * scaledThickness);
+ Point p4 = d->lp[1] + (ortho * 16.0 * scaledThickness);
Point p5 = d->p[0] + (ortho * 4.0 * scaledThickness);
Point p6 = d->p[1] + (ortho * 4.0 * scaledThickness);
// Calculate whether or not the arrowheads are too crowded to put
// inside the extension lines. 9.0 is the length of the arrowhead.
- double t = Geometry::ParameterOfLineAndPoint(linePt1, linePt2, linePt2 - (unit * 9.0 * scaledThickness));
+ double t = Geometry::ParameterOfLineAndPoint(d->lp[0], d->lp[1], d->lp[1] - (unit * 9.0 * scaledThickness));
// On the screen, it's acting like this is actually 58%...
// This is correct, we want it to happen at > 50%
painter->DrawAngledText(ctr, angle, dimText, scaledThickness);
+ if (d->hitObject)
+ {
+ Point hp1 = (p1 + p2) / 2.0;
+ Point hp2 = (p1 + hp1) / 2.0;
+ Point hp3 = (hp1 + p2) / 2.0;
+
+ if (d->hitPoint[2])
+ {
+ painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+ painter->SetBrush(QBrush(QColor(Qt::magenta)));
+ painter->DrawArrowHandle(hp1, ortho.Angle() + HALF_TAU);
+ painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+ }
+
+ painter->DrawHandle(hp1);
+ painter->SetPen(QPen(Qt::blue, 1.0 * Global::zoom * scaledThickness, Qt::SolidLine));
+
+ if (d->hitPoint[3])
+ {
+ painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+ painter->SetBrush(QBrush(QColor(Qt::magenta)));
+ painter->DrawArrowToLineHandle(hp2, (d->subtype == DTLinearVert ? v.Angle() - QTR_TAU : (v.Angle() < HALF_TAU ? HALF_TAU : 0)));
+ painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+ }
+
+ painter->DrawHandle(hp2);
+ painter->SetPen(QPen(Qt::blue, 1.0 * Global::zoom * scaledThickness, Qt::SolidLine));
+
+ if (d->hitPoint[4])
+ {
+ painter->SetPen(QPen(Qt::magenta, 1.0, Qt::SolidLine));
+ painter->SetBrush(QBrush(QColor(Qt::magenta)));
+ painter->DrawArrowToLineHandle(hp3, (d->subtype == DTLinearHorz ? v.Angle() - QTR_TAU : (v.Angle() > HALF_TAU && v.Angle() < THREE_QTR_TAU ? THREE_QTR_TAU : QTR_TAU)));
+ painter->SetPen(QPen(Qt::magenta, 2.0, Qt::DotLine));
+ }
+
+ painter->DrawHandle(hp3);
+ }
+
+ if (obj->hitPoint[0])
+ painter->DrawHandle(obj->p[0]);
+
+ if (obj->hitPoint[1])
+ painter->DrawHandle(obj->p[1]);
+
break;
}
case OTText:
{
Text * t = (Text *)obj;
- painter->DrawTextObject(t->p[0], t->s.c_str(), scaledThickness);
+
+ if (t->measured == false)
+ {
+ t->extents = painter->MeasureTextObject(t->s.c_str(), scaledThickness);
+ t->measured = true;
+ }
+
+ painter->DrawTextObject(t->p[0], t->s.c_str(), scaledThickness, t->angle[0]);
break;
}
case OTSpline:
void DrawingView::ToolHandler(int mode, Point p)
{
+ // Drop angle snap until it's needed
+ angleSnap = false;
+
if (Global::tool == TTLine)
LineHandler(mode, p);
else if (Global::tool == TTCircle)
RotateHandler(mode, p);
else if (Global::tool == TTMirror)
MirrorHandler(mode, p);
+ else if (Global::tool == TTDimension)
+ DimensionHandler(mode, p);
}
{
if (toolPoint[0] == toolPoint[1])
return;
-
+
Point mirrorPoint = toolPoint[0] + Vector(toolPoint[1], toolPoint[0]);
painter->DrawLine(mirrorPoint, toolPoint[1]);
informativeText += " (Copy)";
}
}
+ if (Global::tool == TTDimension)
+ {
+ if (Global::toolState == TSNone)
+ {
+ painter->DrawHandle(toolPoint[0]);
+ }
+ else if ((Global::toolState == TSPoint2) && shiftDown)
+ {
+ painter->DrawHandle(toolPoint[1]);
+ }
+ else
+ {
+ painter->DrawLine(toolPoint[0], toolPoint[1]);
+ painter->DrawHandle(toolPoint[1]);
+
+ Vector v(toolPoint[0], toolPoint[1]);
+ double absAngle = v.Angle() * RADIANS_TO_DEGREES;
+ double absLength = v.Magnitude();
+ QString text = tr("Length: %1 in.\n") + QChar(0x2221) + tr(": %2");
+ informativeText = text.arg(absLength).arg(absAngle);
+ }
+ }
}
}
else
{
- Line * l = new Line(toolPoint[0], toolPoint[1]);
+ Line * l = new Line(toolPoint[0], toolPoint[1], Global::penWidth, Global::penColor, Global::penStyle);
l->layer = Global::activeLayer;
document.objects.push_back(l);
toolPoint[0] = toolPoint[1];
else
{
double length = Vector::Magnitude(toolPoint[0], toolPoint[1]);
- Circle * c = new Circle(toolPoint[0], length);
+ Circle * c = new Circle(toolPoint[0], length, Global::penWidth, Global::penColor, Global::penStyle);
c->layer = Global::activeLayer;
document.objects.push_back(c);
toolPoint[0] = toolPoint[1];
else if (Global::toolState == TSPoint2)
toolPoint[1] = p;
else if (Global::toolState == TSPoint3)
+ {
toolPoint[2] = p;
+ angleSnap = true;
+ }
else
+ {
toolPoint[3] = p;
+ angleSnap = true;
+ }
break;
case ToolMouseUp:
{
if (shiftDown)
{
- // Key override is telling us to start circle at new center, not
+ // Key override is telling us to start arc at new center, not
// continue the current one.
toolPoint[0] = toolPoint[1];
return;
if (span < 0)
span += TAU;
- Arc * arc = new Arc(toolPoint[0], toolPoint[1].x, toolPoint[2].x, span);
+ Arc * arc = new Arc(toolPoint[0], toolPoint[1].x, toolPoint[2].x, span, Global::penWidth, Global::penColor, Global::penStyle);
arc->layer = Global::activeLayer;
document.objects.push_back(arc);
Global::toolState = TSNone;
if (shiftDown)
return;
+ angleSnap = true;
double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
std::vector<void *>::iterator j = select.begin();
std::vector<Object>::iterator i = toolScratch.begin();
if (shiftDown)
return;
+ angleSnap = true;
double angle = Vector(toolPoint[0], toolPoint[1]).Angle();
std::vector<void *>::iterator j = select.begin();
std::vector<Object>::iterator i = toolScratch.begin();
}
+void DrawingView::DimensionHandler(int mode, Point p)
+{
+ switch (mode)
+ {
+ case ToolMouseDown:
+ if (Global::toolState == TSNone)
+ toolPoint[0] = p;
+ else
+ toolPoint[1] = p;
+
+ break;
+ case ToolMouseMove:
+ if (Global::toolState == TSNone)
+ toolPoint[0] = p;
+ else
+ toolPoint[1] = p;
+
+ break;
+ case ToolMouseUp:
+ if (Global::toolState == TSNone)
+ {
+ Global::toolState = TSPoint2;
+ // Prevent spurious line from drawing...
+ toolPoint[1] = toolPoint[0];
+ }
+ else if ((Global::toolState == TSPoint2) && shiftDown)
+ {
+ // Key override is telling us to make a new line, not continue the
+ // previous one.
+ toolPoint[0] = toolPoint[1];
+ }
+ else
+ {
+ Dimension * d = new Dimension(toolPoint[0], toolPoint[1], DTLinear);
+ d->layer = Global::activeLayer;
+ document.objects.push_back(d);
+ Global::toolState = TSNone;
+ }
+ }
+}
+
+
void DrawingView::mousePressEvent(QMouseEvent * event)
{
if (event->button() == Qt::LeftButton)
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.
+ //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;
}
AddHoveredToSelection();
update(); // needed??
GetHovered(hover); // prolly needed
+ dragged = (Object *)hover[0];
+ draggingObject = true;
+
+ // Alert the pen widget
+ emit(ObjectSelected(dragged));
+
+ // See if anything is using just a straight click on a handle
+ if (HandleObjectClicked())
+ {
+ draggingObject = false;
+ update();
+ return;
+ }
// Needed for grab & moving objects
// We do it *after*... why? (doesn't seem to confer any advantage...)
// Only needs to be done here, as mouse down is always preceded by movement
Global::snapPointIsValid = false;
hoveringIntersection = false;
+ oldScrollPoint = Vector(event->x(), event->y());
// Scrolling...
- if (event->buttons() & Qt::MiddleButton)
+ if ((event->buttons() & Qt::MiddleButton) || scrollDrag)
{
point = Vector(event->x(), event->y());
// Since we're using Qt coords for scrolling, we have to adjust them
return;
}
- // Handle object movement (left button down & over an object)
- if ((event->buttons() & Qt::LeftButton) && numHovered && !Global::tool)
- {
- if (hoveringIntersection)
- point = intersectionPoint;
- else if (Global::snapToGrid)
- point = SnapPointToGrid(point);
-
- HandleObjectMovement(point);
- update();
- oldPoint = point;
- return;
- }
-
// Do object hit testing...
bool needUpdate = HitTestObjects(point);
+ GetHovered(hover);
// Check for multi-hover...
if (numHovered > 1)
{
- GetHovered(hover);
- Geometry::Intersects((Object *)hover[0], (Object *)hover[1]);
+//need to check for case where hover is over 2 circles and a 3rd's center...
+ Object * obj1 = (Object *)hover[0], * obj2 = (Object *)hover[1];
+
+ Geometry::Intersects(obj1, obj2);
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);
+ Vector v1 = Geometry::GetPointForParameter(obj1, t);
+ Vector v2 = Geometry::GetPointForParameter(obj2, 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);
}
}
-//this doesn't work down here for some reason... :-P
-//could be because the object being moved is part of the intersection, and this is screwing things up. In which case, we need to exclude the moving object somehow from the hit test function...
-#if 0
// Handle object movement (left button down & over an object)
- if ((event->buttons() & Qt::LeftButton) && numHovered && !Global::tool)
+ if ((event->buttons() & Qt::LeftButton) && draggingObject && !Global::tool)
{
if (hoveringIntersection)
point = intersectionPoint;
+ else if (hoverPointValid)
+ point = hoverPoint;
else if (Global::snapToGrid)
point = SnapPointToGrid(point);
oldPoint = point;
return;
}
-#endif
// Do tool handling, if any are active...
if (Global::tool)
{
if (hoveringIntersection)
point = intersectionPoint;
+ else if (hoverPointValid)
+ point = hoverPoint;
else if (Global::snapToGrid)
- point = SnapPointToGrid(point);
+ {
+ if (angleSnap)
+ point = SnapPointToAngle(point);
+ else
+ point = SnapPointToGrid(point);
+ }
ToolHandler(ToolMouseMove, point);
}
{
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);
}
+
+ draggingObject = false;
}
else if (event->button() == Qt::MiddleButton)
{
{
bool oldShift = shiftDown;
bool oldCtrl = ctrlDown;
+ bool oldAlt = altDown;
if (event->key() == Qt::Key_Shift)
shiftDown = true;
else if (event->key() == Qt::Key_Control)
ctrlDown = true;
+ else if (event->key() == Qt::Key_Alt)
+ altDown = true;
if ((oldShift != shiftDown) || (oldCtrl != ctrlDown))
{
update();
}
+
+ if (oldAlt != altDown)
+ {
+ scrollDrag = true;
+ setCursor(Qt::SizeAllCursor);
+// oldPoint = Vector();
+ oldPoint = oldScrollPoint;
+ }
+
+ if (select.size() > 0)
+ {
+ if (event->key() == Qt::Key_Up)
+ {
+ TranslateObjects(select, Point(0, +1.0));
+ update();
+ }
+ else if (event->key() == Qt::Key_Down)
+ {
+ TranslateObjects(select, Point(0, -1.0));
+ update();
+ }
+ else if (event->key() == Qt::Key_Right)
+ {
+ TranslateObjects(select, Point(+1.0, 0));
+ update();
+ }
+ else if (event->key() == Qt::Key_Left)
+ {
+ TranslateObjects(select, Point(-1.0, 0));
+ update();
+ }
+ }
}
{
bool oldShift = shiftDown;
bool oldCtrl = ctrlDown;
+ bool oldAlt = altDown;
if (event->key() == Qt::Key_Shift)
shiftDown = false;
else if (event->key() == Qt::Key_Control)
ctrlDown = false;
+ else if (event->key() == Qt::Key_Alt)
+ altDown = false;
if ((oldShift != shiftDown) || (oldCtrl != ctrlDown))
{
update();
}
+
+ if (oldAlt != altDown)
+ {
+ scrollDrag = false;
+ setCursor(Qt::ArrowCursor);
+ }
}
}
+Point DrawingView::SnapPointToAngle(Point point)
+{
+ // Snap to a single digit angle (using toolpoint #1 as the center)
+ double angle = Vector::Angle(toolPoint[0], point);
+ double length = Vector::Magnitude(toolPoint[0], point);
+
+ // Convert from radians to degrees
+ double degAngle = angle * RADIANS_TO_DEGREES;
+ double snapAngle = (double)((int)(degAngle + 0.5));
+
+ Vector v;
+ v.SetAngleAndLength(snapAngle * DEGREES_TO_RADIANS, length);
+ point = toolPoint[0] + v;
+
+ return point;
+}
+
+
Rect DrawingView::GetObjectExtents(Object * obj)
{
// Default to empty rect, if object checks below fail for some reason
switch (obj->type)
{
case OTLine:
+ case OTDimension:
{
rect = Rect(obj->p[0], obj->p[1]);
break;
}
+
case OTCircle:
{
rect = Rect(obj->p[0], obj->p[0]);
rect.Expand(obj->radius[0]);
break;
}
+
case OTArc:
{
Arc * a = (Arc *)obj;
rect *= a->radius[0];
rect.Translate(a->p[0]);
+ break;
+ }
+ case OTText:
+ {
+ Text * t = (Text *)obj;
+ rect = Rect(t->p[0], Point(t->p[0].x + t->extents.Width(), t->p[0].y - t->extents.Height()));
break;
}
+
case OTContainer:
{
Container * c = (Container *)obj;
for(; i!=c->objects.end(); i++)
rect |= GetObjectExtents((Object *)*i);
}
+
default:
break;
}
switch (obj->type)
{
case OTLine:
+ case OTDimension:
{
Line * l = (Line *)obj;
break;
}
+
case OTCircle:
{
Circle * c = (Circle *)obj;
break;
}
+
case OTArc:
{
Arc * a = (Arc *)obj;
break;
}
+
+ case OTText:
+ {
+ Text * t = (Text *)obj;
+ Rect r(obj->p[0], Point(t->p[0].x + t->extents.Width(), t->p[0].y - t->extents.Height()));
+
+ if (Global::selection.contains(r.l, r.t) && Global::selection.contains(r.r, r.b))
+ t->selected = true;
+
+ break;
+ }
+
default:
break;
}
std::vector<void *>::iterator i;
numHovered = 0;
bool needUpdate = false;
+ hoverPointValid = false;
for(i=document.objects.begin(); i!=document.objects.end(); i++)
{
Object * obj = (Object *)(*i);
+ // If we're seeing the object we're dragging, skip it
+ if (draggingObject && (obj == dragged))
+ continue;
+
if (HitTest(obj, point))
needUpdate = true;
-#if 0
- switch (obj->type)
- {
- case OTLine:
- {
- bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHO = obj->hitObject;
- obj->hitPoint[0] = obj->hitPoint[1] = obj->hitObject = false;
- Vector lineSegment = obj->p[1] - obj->p[0];
- Vector v1 = point - obj->p[0];
- Vector v2 = point - obj->p[1];
- double t = Geometry::ParameterOfLineAndPoint(obj->p[0], obj->p[1], point);
- double distance;
-
- if (t < 0.0)
- distance = v1.Magnitude();
- else if (t > 1.0)
- distance = v2.Magnitude();
- else
- // distance = ?Det?(ls, v1) / |ls|
- distance = fabs((lineSegment.x * v1.y - v1.x * lineSegment.y)
- / lineSegment.Magnitude());
-
- if ((v1.Magnitude() * Global::zoom) < 8.0)
- obj->hitPoint[0] = true;
- else if ((v2.Magnitude() * Global::zoom) < 8.0)
- obj->hitPoint[1] = true;
- else if ((distance * Global::zoom) < 5.0)
- obj->hitObject = true;
-
- obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitObject ? true : false);
-
- if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHO != obj->hitObject))
- needUpdate = true;
-
- break;
- }
- case OTCircle:
- {
- bool oldHP = obj->hitPoint[0], oldHO = obj->hitObject;
- obj->hitPoint[0] = obj->hitObject = false;
- double length = Vector::Magnitude(obj->p[0], point);
-
- if ((length * Global::zoom) < 8.0)
- obj->hitPoint[0] = true;
- else if ((fabs(length - obj->radius[0]) * Global::zoom) < 2.0)
- obj->hitObject = true;
-
- obj->hovered = (obj->hitPoint[0] || obj->hitObject ? true : false);
-
- if ((oldHP != obj->hitPoint[0]) || (oldHO != obj->hitObject))
- needUpdate = true;
-
- break;
- }
- case OTArc:
- {
- bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHP2 = obj->hitPoint[2], oldHO = obj->hitObject;
- obj->hitPoint[0] = obj->hitPoint[1] = obj->hitPoint[2] = obj->hitObject = false;
- double length = Vector::Magnitude(obj->p[0], point);
- double angle = Vector::Angle(obj->p[0], point);
-
- // Make sure we get the angle in the correct spot
- if (angle < obj->angle[0])
- angle += TAU;
-
- // Get the span that we're pointing at...
- double span = angle - obj->angle[0];
-
- // N.B.: Still need to hit test the arc start & arc span handles...
- double spanAngle = obj->angle[0] + obj->angle[1];
- Point handle1 = obj->p[0] + (Vector(cos(obj->angle[0]), sin(obj->angle[0])) * obj->radius[0]);
- Point handle2 = obj->p[0] + (Vector(cos(spanAngle), sin(spanAngle)) * obj->radius[0]);
- double length2 = Vector::Magnitude(point, handle1);
- double length3 = Vector::Magnitude(point, handle2);
-
- if ((length * Global::zoom) < 8.0)
- obj->hitPoint[0] = true;
- else if ((length2 * Global::zoom) < 8.0)
- obj->hitPoint[1] = true;
- else if ((length3 * Global::zoom) < 8.0)
- obj->hitPoint[2] = true;
- else if (((fabs(length - obj->radius[0]) * Global::zoom) < 2.0) && (span < obj->angle[1]))
- obj->hitObject = true;
-
- obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitObject ? true : false);
-
- if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHO != obj->hitObject))
- needUpdate = true;
-
- break;
- }
- case OTContainer:
- {
- // Containers must be recursively tested...
- Container * c = (Container *)obj;
- std::vector<void *>::iterator i;
-
- for(i=c->objects.begin(); i!=c->objects.end(); i++)
- {
-
- }
- }
- default:
- break;
- }
-#endif
if (obj->hovered)
{
/ lineSegment.Magnitude());
if ((v1.Magnitude() * Global::zoom) < 8.0)
+ {
obj->hitPoint[0] = true;
+ hoverPoint = obj->p[0];
+ hoverPointValid = true;
+ }
else if ((v2.Magnitude() * Global::zoom) < 8.0)
+ {
obj->hitPoint[1] = true;
+ hoverPoint = obj->p[1];
+ hoverPointValid = true;
+ }
else if ((distance * Global::zoom) < 5.0)
obj->hitObject = true;
break;
}
+
case OTCircle:
{
bool oldHP = obj->hitPoint[0], oldHO = obj->hitObject;
double length = Vector::Magnitude(obj->p[0], point);
if ((length * Global::zoom) < 8.0)
+ {
obj->hitPoint[0] = true;
+ hoverPoint = obj->p[0];
+ hoverPointValid = true;
+ }
else if ((fabs(length - obj->radius[0]) * Global::zoom) < 2.0)
obj->hitObject = true;
break;
}
+
case OTArc:
{
bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHP2 = obj->hitPoint[2], oldHO = obj->hitObject;
double length3 = Vector::Magnitude(point, handle2);
if ((length * Global::zoom) < 8.0)
+ {
obj->hitPoint[0] = true;
+ hoverPoint = obj->p[0];
+ hoverPointValid = true;
+ }
else if ((length2 * Global::zoom) < 8.0)
+ {
obj->hitPoint[1] = true;
+ hoverPoint = handle1;
+ hoverPointValid = true;
+ }
else if ((length3 * Global::zoom) < 8.0)
+ {
obj->hitPoint[2] = true;
+ hoverPoint = handle2;
+ hoverPointValid = true;
+ }
else if (((fabs(length - obj->radius[0]) * Global::zoom) < 2.0) && (span < obj->angle[1]))
obj->hitObject = true;
break;
}
+
+ case OTDimension:
+ {
+ bool oldHP0 = obj->hitPoint[0], oldHP1 = obj->hitPoint[1], oldHP2 = obj->hitPoint[2], oldHP3 = obj->hitPoint[3], oldHP4 = obj->hitPoint[4], oldHO = obj->hitObject;
+ obj->hitPoint[0] = obj->hitPoint[1] = obj->hitPoint[2] = obj->hitPoint[3] = obj->hitPoint[4] = obj->hitObject = false;
+
+ Dimension * d = (Dimension *)obj;
+
+ Vector orthogonal = Vector::Normal(d->lp[0], d->lp[1]);
+ // Get our line parallel to our points
+ float scaledThickness = Global::scale * obj->thickness;
+ Point p1 = d->lp[0] + (orthogonal * 10.0 * scaledThickness);
+ Point p2 = d->lp[1] + (orthogonal * 10.0 * scaledThickness);
+ Point p3(p1, point);
+
+ Vector v1(d->p[0], point);
+ Vector v2(d->p[1], point);
+ Vector lineSegment(p1, p2);
+ double t = Geometry::ParameterOfLineAndPoint(p1, p2, point);
+ double distance;
+ Point midpoint = (p1 + p2) / 2.0;
+ Point hFSPoint = Point(midpoint, point);
+ Point hCS1Point = Point((p1 + midpoint) / 2.0, point);
+ Point hCS2Point = Point((midpoint + p2) / 2.0, point);
+
+ if (t < 0.0)
+ distance = v1.Magnitude();
+ else if (t > 1.0)
+ distance = v2.Magnitude();
+ else
+ // distance = ?Det?(ls, v1) / |ls|
+ distance = fabs((lineSegment.x * p3.y - p3.x * lineSegment.y)
+ / lineSegment.Magnitude());
+
+ if ((v1.Magnitude() * Global::zoom) < 8.0)
+ obj->hitPoint[0] = true;
+ else if ((v2.Magnitude() * Global::zoom) < 8.0)
+ obj->hitPoint[1] = true;
+ else if ((distance * Global::zoom) < 5.0)
+ obj->hitObject = true;
+
+ if ((hFSPoint.Magnitude() * Global::zoom) < 8.0)
+ obj->hitPoint[2] = true;
+ else if ((hCS1Point.Magnitude() * Global::zoom) < 8.0)
+ obj->hitPoint[3] = true;
+ else if ((hCS2Point.Magnitude() * Global::zoom) < 8.0)
+ obj->hitPoint[4] = true;
+
+// return (hitPoint1 || hitPoint2 || hitLine || hitFlipSwitch || hitChangeSwitch1 || hitChangeSwitch2 ? true : false);
+ obj->hovered = (obj->hitPoint[0] || obj->hitPoint[1] || obj->hitPoint[2] || obj->hitPoint[3] || obj->hitPoint[4] || obj->hitObject ? true : false);
+
+ if ((oldHP0 != obj->hitPoint[0]) || (oldHP1 != obj->hitPoint[1]) || (oldHP2 != obj->hitPoint[2]) || (oldHP3 != obj->hitPoint[3]) || (oldHP4 != obj->hitPoint[4]) || (oldHO != obj->hitObject))
+ needUpdate = true;
+
+ break;
+ }
+
+ case OTText:
+ {
+ Text * t = (Text *)obj;
+ bool oldHO = obj->hitObject;
+ obj->hitObject = false;
+
+ Rect r(obj->p[0], Point(obj->p[0].x + t->extents.Width(), obj->p[0].y - t->extents.Height()));
+//printf("Text: p=<%lf, %lf>, w/h=%lf, %lf [lrtb=%lf, %lf, %lf, %lf]\n", obj->p[0].x, obj->p[0].y, t->extents.Width(), t->extents.Height(), t->extents.l, t->extents.r, t->extents.t, t->extents.b);
+
+ if (r.Contains(point))
+ obj->hitObject = true;
+
+ obj->hovered = (obj->hitObject ? true : false);
+
+ if (oldHO != obj->hitObject)
+ needUpdate = true;
+
+ break;
+ }
+
case OTContainer:
{
// Containers must be recursively tested...
break;
}
+
default:
break;
}
}
+bool DrawingView::HandleObjectClicked(void)
+{
+ if (dragged->type == OTDimension)
+ {
+ Dimension * d = (Dimension *)dragged;
+
+ if (d->hitPoint[2])
+ {
+ // Hit the "flip sides" switch, so flip 'em
+ Point temp = d->p[0];
+ d->p[0] = d->p[1];
+ d->p[1] = temp;
+ return true;
+ }
+ else if (d->hitPoint[3])
+ {
+ // There are three cases here: aligned, horizontal, & vertical.
+ // Aligned and horizontal do the same thing, vertical goes back to
+ // linear.
+ if (d->subtype == DTLinearVert)
+ d->subtype = DTLinear;
+ else
+ d->subtype = DTLinearVert;
+
+ return true;
+ }
+ else if (d->hitPoint[4])
+ {
+ // There are three cases here: aligned, horizontal, & vertical.
+ // Aligned and vertical do the same thing, horizontal goes back to
+ // linear.
+ if (d->subtype == DTLinearHorz)
+ d->subtype = DTLinear;
+ else
+ d->subtype = DTLinearHorz;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
void DrawingView::HandleObjectMovement(Point point)
{
Point delta = point - oldPoint;
//printf("HOM: old = (%f,%f), new = (%f, %f), delta = (%f, %f)\n", oldPoint.x, oldPoint.y, point.x, point.y, delta.x, delta.y);
- Object * obj = (Object *)hover[0];
+// Object * obj = (Object *)hover[0];
+ Object * obj = dragged;
//printf("Object type = %i (size=%i), ", obj->type, hover.size());
//printf("Object (%X) move: hp1=%s, hp2=%s, hl=%s\n", obj, (obj->hitPoint[0] ? "true" : "false"), (obj->hitPoint[1] ? "true" : "false"), (obj->hitObject ? "true" : "false"));
}
break;
+
case OTCircle:
if (obj->hitPoint[0])
obj->p[0] = point;
}
break;
+
case OTArc:
if (obj->hitPoint[0])
obj->p[0] = point;
}
break;
+
+ case OTDimension:
+ if (obj->hitPoint[0])
+ obj->p[0] = point;
+ else if (obj->hitPoint[1])
+ obj->p[1] = point;
+ else if (obj->hitObject)
+ {
+ obj->p[0] += delta;
+ obj->p[1] += delta;
+ }
+
+ break;
+
+ case OTText:
+ if (obj->hitObject)
+ obj->p[0] += delta;
+
+ break;
+
case OTContainer:
// This is shitty, but works for now until I can code up something
// nicer :-)