Block moving a spline by dragging if a formula was used.
--HG-- branch : feature
This commit is contained in:
parent
773383ec70
commit
679f90d627
|
@ -32,6 +32,7 @@
|
||||||
#include "../../../undocommands/movespline.h"
|
#include "../../../undocommands/movespline.h"
|
||||||
#include "../../../visualization/vistoolspline.h"
|
#include "../../../visualization/vistoolspline.h"
|
||||||
#include "../vwidgets/vcontrolpointspline.h"
|
#include "../vwidgets/vcontrolpointspline.h"
|
||||||
|
#include "../qmuparser/qmutokenparser.h"
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
|
||||||
# include "../vmisc/vmath.h"
|
# include "../vmisc/vmath.h"
|
||||||
|
@ -335,9 +336,17 @@ void VToolSpline::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
|
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
|
||||||
{
|
{
|
||||||
SetOverrideCursor(cursorArrowCloseHand, 1, 1);
|
const auto spline = VAbstractTool::data.GeometricObject<VSpline>(id);
|
||||||
oldPosition = event->scenePos();
|
|
||||||
event->accept();
|
if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula()))
|
||||||
|
{
|
||||||
|
SetOverrideCursor(cursorArrowCloseHand, 1, 1);
|
||||||
|
oldPosition = event->scenePos();
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VAbstractSpline::mousePressEvent(event);
|
VAbstractSpline::mousePressEvent(event);
|
||||||
|
@ -350,8 +359,16 @@ void VToolSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
|
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
|
||||||
{
|
{
|
||||||
//Disable cursor-arrow-closehand
|
const auto spline = VAbstractTool::data.GeometricObject<VSpline>(id);
|
||||||
RestoreOverrideCursor(cursorArrowCloseHand);
|
|
||||||
|
if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula()))
|
||||||
|
{
|
||||||
|
//Disable cursor-arrow-closehand
|
||||||
|
RestoreOverrideCursor(cursorArrowCloseHand);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VAbstractSpline::mouseReleaseEvent(event);
|
VAbstractSpline::mouseReleaseEvent(event);
|
||||||
|
@ -360,74 +377,81 @@ void VToolSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VToolSpline::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
void VToolSpline::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
// Don't need check if left mouse button was pressed. According to the Qt documentation "If you do receive this
|
const auto spline = VAbstractTool::data.GeometricObject<VSpline>(id);
|
||||||
// event, you can be certain that this item also received a mouse press event, and that this item is the current
|
|
||||||
// mouse grabber.".
|
|
||||||
|
|
||||||
// Magic Bezier Drag Equations follow!
|
if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) &&
|
||||||
// "weight" describes how the influence of the drag should be distributed
|
qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) &&
|
||||||
// among the handles; 0 = front handle only, 1 = back handle only.
|
qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula()))
|
||||||
const QSharedPointer<VSpline> spline = VAbstractTool::data.GeometricObject<VSpline>(id);
|
|
||||||
const qreal t = spline->ParamT(oldPosition);
|
|
||||||
|
|
||||||
if (qFloor(t) == -1)
|
|
||||||
{
|
{
|
||||||
return;
|
// Don't need check if left mouse button was pressed. According to the Qt documentation "If you do receive this
|
||||||
}
|
// event, you can be certain that this item also received a mouse press event, and that this item is the current
|
||||||
|
// mouse grabber.".
|
||||||
|
|
||||||
double weight;
|
// Magic Bezier Drag Equations follow!
|
||||||
if (t <= 1.0 / 6.0)
|
// "weight" describes how the influence of the drag should be distributed
|
||||||
{
|
// among the handles; 0 = front handle only, 1 = back handle only.
|
||||||
weight = 0;
|
|
||||||
}
|
|
||||||
else if (t <= 0.5)
|
|
||||||
{
|
|
||||||
weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
|
|
||||||
}
|
|
||||||
else if (t <= 5.0 / 6.0)
|
|
||||||
{
|
|
||||||
weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
weight = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QPointF delta = event->scenePos() - oldPosition;
|
const qreal t = spline->ParamT(oldPosition);
|
||||||
const QPointF offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
|
|
||||||
const QPointF offset1 = (weight/(3*t*t*(1-t))) * delta;
|
|
||||||
|
|
||||||
const QPointF p2 = spline->GetP2() + offset0;
|
if (qFloor(t) == -1)
|
||||||
const QPointF p3 = spline->GetP3() + offset1;
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
oldPosition = event->scenePos(); // Now mouse here
|
double weight;
|
||||||
|
if (t <= 1.0 / 6.0)
|
||||||
|
{
|
||||||
|
weight = 0;
|
||||||
|
}
|
||||||
|
else if (t <= 0.5)
|
||||||
|
{
|
||||||
|
weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
|
||||||
|
}
|
||||||
|
else if (t <= 5.0 / 6.0)
|
||||||
|
{
|
||||||
|
weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weight = 1;
|
||||||
|
}
|
||||||
|
|
||||||
VSpline spl = VSpline(spline->GetP1(), p2, p3, spline->GetP4(), spline->GetKcurve());
|
const QPointF delta = event->scenePos() - oldPosition;
|
||||||
|
const QPointF offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
|
||||||
|
const QPointF offset1 = (weight/(3*t*t*(1-t))) * delta;
|
||||||
|
|
||||||
MoveSpline *moveSpl = new MoveSpline(doc, spline.data(), spl, id, this->scene());
|
const QPointF p2 = spline->GetP2() + offset0;
|
||||||
connect(moveSpl, &MoveSpline::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
|
const QPointF p3 = spline->GetP3() + offset1;
|
||||||
qApp->getUndoStack()->push(moveSpl);
|
|
||||||
|
|
||||||
// Each time we move something we call recalculation scene rect. In some cases this can cause moving
|
oldPosition = event->scenePos(); // Now mouse here
|
||||||
// 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;
|
|
||||||
|
|
||||||
const QList<QGraphicsView *> viewList = scene()->views();
|
VSpline spl = VSpline(spline->GetP1(), p2, p3, spline->GetP4(), spline->GetKcurve());
|
||||||
if (not viewList.isEmpty())
|
|
||||||
{
|
MoveSpline *moveSpl = new MoveSpline(doc, spline.data(), spl, id, this->scene());
|
||||||
if (QGraphicsView *view = viewList.at(0))
|
connect(moveSpl, &MoveSpline::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
|
||||||
|
qApp->getUndoStack()->push(moveSpl);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
const QList<QGraphicsView *> viewList = scene()->views();
|
||||||
|
if (not viewList.isEmpty())
|
||||||
{
|
{
|
||||||
VMainGraphicsScene *currentScene = qobject_cast<VMainGraphicsScene *>(scene());
|
if (QGraphicsView *view = viewList.at(0))
|
||||||
SCASSERT(currentScene);
|
{
|
||||||
const QPointF cursorPosition = currentScene->getScenePos();
|
VMainGraphicsScene *currentScene = qobject_cast<VMainGraphicsScene *>(scene());
|
||||||
view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10));
|
SCASSERT(currentScene);
|
||||||
|
const QPointF cursorPosition = currentScene->getScenePos();
|
||||||
|
view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
changeFinished = true;
|
||||||
changeFinished = true;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +460,15 @@ void VToolSpline::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
||||||
{
|
{
|
||||||
if (flags() & QGraphicsItem::ItemIsMovable)
|
if (flags() & QGraphicsItem::ItemIsMovable)
|
||||||
{
|
{
|
||||||
SetOverrideCursor(cursorArrowOpenHand, 1, 1);
|
const auto spline = VAbstractTool::data.GeometricObject<VSpline>(id);
|
||||||
|
|
||||||
|
if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula()))
|
||||||
|
{
|
||||||
|
SetOverrideCursor(cursorArrowOpenHand, 1, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VAbstractSpline::hoverEnterEvent(event);
|
VAbstractSpline::hoverEnterEvent(event);
|
||||||
|
@ -447,8 +479,16 @@ void VToolSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||||
{
|
{
|
||||||
if (flags() & QGraphicsItem::ItemIsMovable)
|
if (flags() & QGraphicsItem::ItemIsMovable)
|
||||||
{
|
{
|
||||||
//Disable cursor-arrow-openhand
|
const auto spline = VAbstractTool::data.GeometricObject<VSpline>(id);
|
||||||
RestoreOverrideCursor(cursorArrowOpenHand);
|
|
||||||
|
if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) &&
|
||||||
|
qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula()))
|
||||||
|
{
|
||||||
|
//Disable cursor-arrow-openhand
|
||||||
|
RestoreOverrideCursor(cursorArrowOpenHand);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VAbstractSpline::hoverLeaveEvent(event);
|
VAbstractSpline::hoverLeaveEvent(event);
|
||||||
|
@ -527,6 +567,8 @@ void VToolSpline::RefreshGeometry()
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VToolSpline::SetSplineAttributes(QDomElement &domElement, const VSpline &spl)
|
void VToolSpline::SetSplineAttributes(QDomElement &domElement, const VSpline &spl)
|
||||||
{
|
{
|
||||||
|
SCASSERT(doc != nullptr);
|
||||||
|
|
||||||
if (domElement.attribute(AttrType) == OldToolType)
|
if (domElement.attribute(AttrType) == OldToolType)
|
||||||
{
|
{
|
||||||
doc->SetAttribute(domElement, AttrType, ToolType);
|
doc->SetAttribute(domElement, AttrType, ToolType);
|
||||||
|
|
|
@ -52,6 +52,12 @@ void TST_QmuTokenParser::IsSingle_data()
|
||||||
QTest::newRow("Empty string") << "" << false;
|
QTest::newRow("Empty string") << "" << false;
|
||||||
QTest::newRow("Several spaces") << " " << false;
|
QTest::newRow("Several spaces") << " " << false;
|
||||||
QTest::newRow("Invalid formula") << "2*)))" << false;
|
QTest::newRow("Invalid formula") << "2*)))" << false;
|
||||||
|
QTest::newRow("Incorrect thousand separator 15 500") << "15 500" << false;
|
||||||
|
QTest::newRow("Correct C locale 15500") << "15500" << true;
|
||||||
|
QTest::newRow("Correct C locale 15,500") << "15,500" << true;
|
||||||
|
QTest::newRow("Correct C locale 15,500.1") << "15,500.1" << true;
|
||||||
|
QTest::newRow("Not C locale 15,5") << "15,5" << false;
|
||||||
|
QTest::newRow("Not C locale 15.500,1") << "15.500,1" << false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user