From 53cb607f343679331504c3b8edbfe217aeaae782 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Sat, 27 Feb 2016 10:29:32 +0200 Subject: [PATCH] Block moving a control point if a formula was used. --HG-- branch : feature --- .../tools/drawTools/toolcurve/vtoolspline.cpp | 77 ++++++++-- .../drawTools/toolcurve/vtoolsplinepath.cpp | 4 +- src/libs/vwidgets/vcontrolpointspline.cpp | 135 ++++++++++++------ src/libs/vwidgets/vcontrolpointspline.h | 8 +- 4 files changed, 167 insertions(+), 57 deletions(-) diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp index 30a8482da..cce351134 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp @@ -69,16 +69,24 @@ VToolSpline::VToolSpline(VAbstractPattern *doc, VContainer *data, quint32 id, co const auto spl = VAbstractTool::data.GeometricObject(id); + const bool freeAngle1 = qmu::QmuTokenParser::IsSingle(spl->GetStartAngleFormula()); + const bool freeLength1 = qmu::QmuTokenParser::IsSingle(spl->GetC1LengthFormula()); + auto *controlPoint1 = new VControlPointSpline(1, SplinePointPosition::FirstPoint, spl->GetP2(), - spl->GetP1().toQPointF(), *data->GetPatternUnit(), this); + spl->GetP1().toQPointF(), *data->GetPatternUnit(), freeAngle1, + freeLength1, this); connect(controlPoint1, &VControlPointSpline::ControlPointChangePosition, this, &VToolSpline::ControlPointChangePosition); connect(this, &VToolSpline::setEnabledPoint, controlPoint1, &VControlPointSpline::setEnabledPoint); connect(controlPoint1, &VControlPointSpline::ShowContextMenu, this, &VToolSpline::contextMenuEvent); controlPoints.append(controlPoint1); + const bool freeAngle2 = qmu::QmuTokenParser::IsSingle(spl->GetEndAngleFormula()); + const bool freeLength2 = qmu::QmuTokenParser::IsSingle(spl->GetC2LengthFormula()); + auto *controlPoint2 = new VControlPointSpline(1, SplinePointPosition::LastPoint, spl->GetP3(), - spl->GetP4().toQPointF(), *data->GetPatternUnit(), this); + spl->GetP4().toQPointF(), *data->GetPatternUnit(), freeAngle2, + freeLength2, this); connect(controlPoint2, &VControlPointSpline::ControlPointChangePosition, this, &VToolSpline::ControlPointChangePosition); connect(this, &VToolSpline::setEnabledPoint, controlPoint2, &VControlPointSpline::setEnabledPoint); @@ -247,11 +255,54 @@ void VToolSpline::ControlPointChangePosition(const qint32 &indexSpline, const Sp VSpline spl; if (position == SplinePointPosition::FirstPoint) { - spl = VSpline(spline->GetP1(), pos, spline->GetP3(), spline->GetP4(), spline->GetKcurve()); + QLineF line(spline->GetP1().toQPointF(), pos); + + qreal newAngle1 = line.angle(); + QString newAngle1F = QString().setNum(newAngle1); + + qreal newLength1 = line.length(); + QString newLength1F = QString().setNum(qApp->fromPixel(newLength1)); + + if (not qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula())) + { + newAngle1 = spline->GetStartAngle(); + newAngle1F = spline->GetStartAngleFormula(); + } + + if (not qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula())) + { + newLength1 = spline->GetC1Length(); + newLength1F = spline->GetC1LengthFormula(); + } + + spl = VSpline(spline->GetP1(), spline->GetP4(), newAngle1, newAngle1F, spline->GetEndAngle(), + spline->GetEndAngleFormula(), newLength1, newLength1F, spline->GetC2Length(), + spline->GetC2LengthFormula(), spline->GetKcurve()); } else { - spl = VSpline(spline->GetP1(), spline->GetP2(), pos, spline->GetP4(), spline->GetKcurve()); + QLineF line(spline->GetP4().toQPointF(), pos); + + qreal newAngle2 = line.angle(); + QString newAngle2F = QString().setNum(newAngle2); + + qreal newLength2 = line.length(); + QString newLength2F = QString().setNum(qApp->fromPixel(newLength2)); + + if (not qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula())) + { + newAngle2 = spline->GetEndAngle(); + newAngle2F = spline->GetEndAngleFormula(); + } + + if (not qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula())) + { + newLength2 = spline->GetC2Length(); + newLength2F = spline->GetC2LengthFormula(); + } + spl = VSpline(spline->GetP1(), spline->GetP4(), spline->GetStartAngle(), spline->GetStartAngleFormula(), + newAngle2, newAngle2F, spline->GetC1Length(), spline->GetC1LengthFormula(), + newLength2, newLength2F, spline->GetKcurve()); } MoveSpline *moveSpl = new MoveSpline(doc, spline.data(), spl, id, this->scene()); @@ -544,13 +595,21 @@ void VToolSpline::RefreshGeometry() const auto spl = VAbstractTool::data.GeometricObject(id); { + const bool freeAngle1 = qmu::QmuTokenParser::IsSingle(spl->GetStartAngleFormula()); + const bool freeLength1 = qmu::QmuTokenParser::IsSingle(spl->GetC1LengthFormula()); + const QPointF splinePoint = VAbstractTool::data.GeometricObject(spl->GetP1().id())->toQPointF(); - controlPoints[0]->RefreshCtrlPoint(1, SplinePointPosition::FirstPoint, spl->GetP2(), splinePoint); + controlPoints[0]->RefreshCtrlPoint(1, SplinePointPosition::FirstPoint, spl->GetP2(), splinePoint, freeAngle1, + freeLength1); } { + const bool freeAngle2 = qmu::QmuTokenParser::IsSingle(spl->GetEndAngleFormula()); + const bool freeLength2 = qmu::QmuTokenParser::IsSingle(spl->GetC2LengthFormula()); + const QPointF splinePoint = VAbstractTool::data.GeometricObject(spl->GetP4().id())->toQPointF(); - controlPoints[1]->RefreshCtrlPoint(1, SplinePointPosition::LastPoint, spl->GetP3(), splinePoint); + controlPoints[1]->RefreshCtrlPoint(1, SplinePointPosition::LastPoint, spl->GetP3(), splinePoint, freeAngle2, + freeLength2); } controlPoints[0]->blockSignals(false); @@ -569,11 +628,7 @@ void VToolSpline::SetSplineAttributes(QDomElement &domElement, const VSpline &sp { SCASSERT(doc != nullptr); - if (domElement.attribute(AttrType) == OldToolType) - { - doc->SetAttribute(domElement, AttrType, ToolType); - } - + doc->SetAttribute(domElement, AttrType, ToolType); doc->SetAttribute(domElement, AttrPoint1, spl.GetP1().id()); doc->SetAttribute(domElement, AttrPoint4, spl.GetP4().id()); doc->SetAttribute(domElement, AttrAngle1, spl.GetStartAngleFormula()); diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp index 5027f90f5..22a55b72c 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp @@ -68,7 +68,7 @@ VToolSplinePath::VToolSplinePath(VAbstractPattern *doc, VContainer *data, quint3 { VSpline spl = splPath->GetSpline(i); auto *controlPoint = new VControlPointSpline(i, SplinePointPosition::FirstPoint, spl.GetP2(), - spl.GetP1().toQPointF(), *data->GetPatternUnit(), this); + spl.GetP1().toQPointF(), *data->GetPatternUnit(), true, true, this); connect(controlPoint, &VControlPointSpline::ControlPointChangePosition, this, &VToolSplinePath::ControlPointChangePosition); connect(this, &VToolSplinePath::setEnabledPoint, controlPoint, &VControlPointSpline::setEnabledPoint); @@ -76,7 +76,7 @@ VToolSplinePath::VToolSplinePath(VAbstractPattern *doc, VContainer *data, quint3 controlPoints.append(controlPoint); controlPoint = new VControlPointSpline(i, SplinePointPosition::LastPoint, spl.GetP3(), spl.GetP4().toQPointF(), - *data->GetPatternUnit(), this); + *data->GetPatternUnit(), true, true, this); connect(controlPoint, &VControlPointSpline::ControlPointChangePosition, this, &VToolSplinePath::ControlPointChangePosition); connect(this, &VToolSplinePath::setEnabledPoint, controlPoint, &VControlPointSpline::setEnabledPoint); diff --git a/src/libs/vwidgets/vcontrolpointspline.cpp b/src/libs/vwidgets/vcontrolpointspline.cpp index 2ed632242..373a05a26 100644 --- a/src/libs/vwidgets/vcontrolpointspline.cpp +++ b/src/libs/vwidgets/vcontrolpointspline.cpp @@ -44,7 +44,9 @@ VControlPointSpline::VControlPointSpline(const qint32 &indexSpline, SplinePointP controlLine(nullptr), indexSpline(indexSpline), position(position), - patternUnit(patternUnit) + patternUnit(patternUnit), + freeAngle(true), + freeLength(true) { Init(); } @@ -60,13 +62,15 @@ VControlPointSpline::VControlPointSpline(const qint32 &indexSpline, SplinePointP */ VControlPointSpline::VControlPointSpline(const qint32 &indexSpline, SplinePointPosition position, const QPointF &controlPoint, const QPointF &splinePoint, Unit patternUnit, - QGraphicsItem *parent) + bool freeAngle, bool freeLength, QGraphicsItem *parent) :QGraphicsEllipseItem(parent), radius(CircleRadius()), controlLine(nullptr), indexSpline(indexSpline), position(position), - patternUnit(patternUnit) + patternUnit(patternUnit), + freeAngle(freeAngle), + freeLength(freeLength) { Init(); @@ -107,7 +111,10 @@ void VControlPointSpline::paint(QPainter *painter, const QStyleOptionGraphicsIte void VControlPointSpline::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { this->setPen(QPen(Qt::black, ToPixel(WidthMainLine(patternUnit), patternUnit))); - SetOverrideCursor(cursorArrowOpenHand, 1, 1); + if (freeAngle || freeLength) + { + SetOverrideCursor(cursorArrowOpenHand, 1, 1); + } QGraphicsEllipseItem::hoverEnterEvent(event); } @@ -115,8 +122,11 @@ void VControlPointSpline::hoverEnterEvent(QGraphicsSceneHoverEvent *event) void VControlPointSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { this->setPen(QPen(Qt::black, ToPixel(WidthHairLine(patternUnit), patternUnit))); - //Disable cursor-arrow-openhand - RestoreOverrideCursor(cursorArrowOpenHand); + if (freeAngle || freeLength) + { + //Disable cursor-arrow-openhand + RestoreOverrideCursor(cursorArrowOpenHand); + } QGraphicsEllipseItem::hoverLeaveEvent(event); } @@ -129,49 +139,81 @@ void VControlPointSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) */ QVariant VControlPointSpline::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { - if (change == ItemPositionChange && scene()) + switch (change) { - // Each time we move something we call recalculation scene rect. In some cases this can cause moving - // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move. - static bool changeFinished = true; - if (changeFinished) + case ItemPositionChange: { - changeFinished = false; - // value - new position. - QPointF newPos = value.toPointF(); - emit ControlPointChangePosition(indexSpline, position, newPos); - if (scene()) + if (not freeAngle || not freeLength) { - const QList viewList = scene()->views(); - if (not viewList.isEmpty()) + const QPointF splPoint = controlLine->line().p1() + pos(); + + QLineF newLine(splPoint, value.toPointF());// value - new position. + QLineF oldLine(splPoint, pos());// pos() - old position. + + if (not freeAngle) { - if (QGraphicsView *view = viewList.at(0)) + newLine.setAngle(oldLine.angle()); + } + + if (not freeLength) + { + qreal length = controlLine->line().length(); + qreal l2 = oldLine.length(); + newLine.setLength(oldLine.length()); + } + + return newLine.p2(); + } + + break; + } + case ItemPositionHasChanged: + { + // Each time we move something we call recalculation scene rect. In some cases this can cause moving + // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last + // move. + static bool changeFinished = true; + if (changeFinished) + { + changeFinished = false; + // value - new position. + emit ControlPointChangePosition(indexSpline, position, value.toPointF()); + if (scene()) + { + const QList viewList = scene()->views(); + if (not viewList.isEmpty()) { - const int xmargin = 50; - const int ymargin = 50; - - const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view); - const QRectF itemRect = mapToScene(boundingRect()).boundingRect(); - - // If item's rect is bigger than view's rect ensureVisible works very unstable. - if (itemRect.height() + 2*ymargin < viewRect.height() && - itemRect.width() + 2*xmargin < viewRect.width()) + if (QGraphicsView *view = viewList.at(0)) { - view->ensureVisible(itemRect, xmargin, ymargin); - } - else - { - // Ensure visible only small rect around a cursor - VMainGraphicsScene *currentScene = qobject_cast(scene()); - SCASSERT(currentScene); - const QPointF cursorPosition = currentScene->getScenePos(); - view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10)); + const int xmargin = 50; + const int ymargin = 50; + + const QRectF viewRect = VMainGraphicsView::SceneVisibleArea(view); + const QRectF itemRect = mapToScene(boundingRect()).boundingRect(); + + // If item's rect is bigger than view's rect ensureVisible works very unstable. + if (itemRect.height() + 2*ymargin < viewRect.height() && + itemRect.width() + 2*xmargin < viewRect.width()) + { + view->ensureVisible(itemRect, xmargin, ymargin); + } + else + { + // Ensure visible only small rect around a cursor + VMainGraphicsScene *currentScene = qobject_cast(scene()); + SCASSERT(currentScene); + const QPointF cursorPosition = currentScene->getScenePos(); + view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10)); + } } } } + changeFinished = true; } - changeFinished = true; + break; } + default: + break; } return QGraphicsItem::itemChange(change, value); } @@ -181,7 +223,10 @@ void VControlPointSpline::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) { - SetOverrideCursor(cursorArrowCloseHand, 1, 1); + if (freeAngle || freeLength) + { + SetOverrideCursor(cursorArrowCloseHand, 1, 1); + } } QGraphicsEllipseItem::mousePressEvent(event); } @@ -191,8 +236,11 @@ void VControlPointSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) { - //Disable cursor-arrow-closehand - RestoreOverrideCursor(cursorArrowCloseHand); + if (freeAngle || freeLength) + { + //Disable cursor-arrow-closehand + RestoreOverrideCursor(cursorArrowCloseHand); + } } QGraphicsEllipseItem::mouseReleaseEvent(event); } @@ -235,10 +283,13 @@ void VControlPointSpline::SetCtrlLine(const QPointF &controlPoint, const QPointF * @param splinePoint spline point. */ void VControlPointSpline::RefreshCtrlPoint(const qint32 &indexSpline, SplinePointPosition pos, - const QPointF &controlPoint, const QPointF &splinePoint) + const QPointF &controlPoint, const QPointF &splinePoint, bool freeAngle, + bool freeLength) { if (this->indexSpline == indexSpline && this->position == pos) { + this->freeAngle = freeAngle; + this->freeLength = freeLength; this->setPos(controlPoint); SetCtrlLine(controlPoint, splinePoint); } diff --git a/src/libs/vwidgets/vcontrolpointspline.h b/src/libs/vwidgets/vcontrolpointspline.h index a15e33756..cd1cfd87d 100644 --- a/src/libs/vwidgets/vcontrolpointspline.h +++ b/src/libs/vwidgets/vcontrolpointspline.h @@ -44,7 +44,8 @@ public: VControlPointSpline(const qint32 &indexSpline, SplinePointPosition position, Unit patternUnit, QGraphicsItem * parent = nullptr); VControlPointSpline(const qint32 &indexSpline, SplinePointPosition position, const QPointF &controlPoint, - const QPointF &splinePoint, Unit patternUnit, QGraphicsItem * parent = nullptr); + const QPointF &splinePoint, Unit patternUnit, bool freeAngle, bool freeLength, + QGraphicsItem * parent = nullptr); virtual ~VControlPointSpline() Q_DECL_OVERRIDE; virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) Q_DECL_OVERRIDE; @@ -66,7 +67,7 @@ signals: void ShowContextMenu(QGraphicsSceneContextMenuEvent *event); public slots: void RefreshCtrlPoint(const qint32 &indexSpline, SplinePointPosition pos, const QPointF &controlPoint, - const QPointF &splinePoint); + const QPointF &splinePoint, bool freeAngle = true, bool freeLength = true); void setEnabledPoint(bool enable); protected: /** @brief radius radius circle. */ @@ -91,6 +92,9 @@ private: Unit patternUnit; + bool freeAngle; + bool freeLength; + inline qreal CircleRadius() const; void Init(); void SetCtrlLine(const QPointF &controlPoint, const QPointF &splinePoint);