From de799569ef1142552e2704e2d5f5979811b9dee2 Mon Sep 17 00:00:00 2001 From: BojanKverh Date: Wed, 14 Sep 2016 01:15:01 +0200 Subject: [PATCH] Fixed moving and scaling grainline and ensured that it stays in bounds --HG-- branch : feature --- src/libs/vtools/tools/vgrainlineitem.cpp | 138 +++++++++++++++++------ src/libs/vtools/tools/vgrainlineitem.h | 4 +- src/libs/vtools/tools/vtooldetail.cpp | 16 ++- 3 files changed, 121 insertions(+), 37 deletions(-) diff --git a/src/libs/vtools/tools/vgrainlineitem.cpp b/src/libs/vtools/tools/vgrainlineitem.cpp index 8cc61c8d6..684944a08 100644 --- a/src/libs/vtools/tools/vgrainlineitem.cpp +++ b/src/libs/vtools/tools/vgrainlineitem.cpp @@ -31,12 +31,15 @@ #include #include #include +#include #include +#include "../vmisc/def.h" + #include "vgrainlineitem.h" -#define ARROW_ANGLE 0.5 -#define ARROW_LENGTH 0.05 +#define ARROW_ANGLE 0.35 +#define ARROW_LENGTH 15 #define RECT_WIDTH 30 #define ACTIVE_Z 10 #define INACTIVE_Z 5 @@ -47,9 +50,10 @@ * @param pParent pointer to the parent item */ VGrainlineItem::VGrainlineItem(QGraphicsItem* pParent) - :QGraphicsObject(pParent), m_eMode(mNormal), m_dRotation(0), m_dLength(0), m_rectBoundingBox(), - m_polyBound(), m_ptStartPos(), m_ptStartMove() + :QGraphicsObject(pParent), m_eMode(VGrainlineItem::mNormal), m_dRotation(0), m_dLength(0), m_rectBoundingBox(), + m_polyBound(), m_ptStartPos(), m_ptStartMove(), m_dScale(1) { + m_rectBoundingBox.setTopLeft(QPointF(0, 0)); setAcceptHoverEvents(true); Reset(); UpdateRectangle(); @@ -76,34 +80,37 @@ void VGrainlineItem::paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption pP->save(); QColor clr = Qt::black; pP->setPen(QPen(clr, 3)); - QPointF pt1 = pos(); + QPointF pt1(0, 0); QPointF pt2; pt2.setX(pt1.x() + m_dLength * cos(m_dRotation)); pt2.setY(pt1.y() + m_dLength * sin(m_dRotation)); pP->setRenderHints(QPainter::Antialiasing); + // line pP->drawLine(pt1, pt2); + // first arrow QPolygonF poly; poly << pt1; QPointF ptA; - ptA.setX(pt1.x() + m_dLength*ARROW_LENGTH*cos(m_dRotation + ARROW_ANGLE)); - ptA.setY(pt1.y() + m_dLength*ARROW_LENGTH*sin(m_dRotation + ARROW_ANGLE)); + qreal dArrLen = ARROW_LENGTH*m_dScale; + ptA.setX(pt1.x() + dArrLen*cos(m_dRotation + ARROW_ANGLE)); + ptA.setY(pt1.y() + dArrLen*sin(m_dRotation + ARROW_ANGLE)); poly << ptA; - ptA.setX(pt1.x() + m_dLength*ARROW_LENGTH*cos(m_dRotation - ARROW_ANGLE)); - ptA.setY(pt1.y() + m_dLength*ARROW_LENGTH*sin(m_dRotation - ARROW_ANGLE)); + ptA.setX(pt1.x() + dArrLen*cos(m_dRotation - ARROW_ANGLE)); + ptA.setY(pt1.y() + dArrLen*sin(m_dRotation - ARROW_ANGLE)); poly << ptA; pP->setBrush(clr); pP->drawPolygon(poly); - + // second arrow poly.clear(); poly << pt2; - ptA.setX(pt2.x() + m_dLength*ARROW_LENGTH*cos(M_PI + m_dRotation + ARROW_ANGLE)); - ptA.setY(pt2.y() + m_dLength*ARROW_LENGTH*sin(M_PI + m_dRotation + ARROW_ANGLE)); + ptA.setX(pt2.x() + dArrLen*cos(M_PI + m_dRotation + ARROW_ANGLE)); + ptA.setY(pt2.y() + dArrLen*sin(M_PI + m_dRotation + ARROW_ANGLE)); poly << ptA; - ptA.setX(pt2.x() + m_dLength*ARROW_LENGTH*cos(M_PI + m_dRotation - ARROW_ANGLE)); - ptA.setY(pt2.y() + m_dLength*ARROW_LENGTH*sin(M_PI + m_dRotation - ARROW_ANGLE)); + ptA.setX(pt2.x() + dArrLen*cos(M_PI + m_dRotation - ARROW_ANGLE)); + ptA.setY(pt2.y() + dArrLen*sin(M_PI + m_dRotation - ARROW_ANGLE)); poly << ptA; pP->drawPolygon(poly); @@ -111,6 +118,7 @@ void VGrainlineItem::paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption { pP->setPen(QPen(clr, 2, Qt::DashLine)); pP->setBrush(Qt::NoBrush); + // bounding polygon pP->drawPolygon(m_polyBound); } pP->restore(); @@ -128,7 +136,15 @@ void VGrainlineItem::UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal m_dRotation = qDegreesToRadians(dRotation); m_dLength = dLength; - setPos(ptPos); + qreal dX; + qreal dY; + QPointF pt = ptPos; + if (IsContained(pt, dX, dY) == false) + { + pt.setX(pt.x() + dX); + pt.setY(pt.y() + dY); + } + setPos(pt); UpdateRectangle(); UpdateBox(); } @@ -169,26 +185,74 @@ bool VGrainlineItem::IsIdle() const * @brief VGrainlineItem::IsContained checks, if both ends of the grainline, starting at pt, are contained in * parent widget. * @param pt starting point of the grainline. + * @param dX horizontal translation needed to put the arrow inside parent item + * @param dY vertical translation needed to put the arrow inside parent item * @return true, if both ends of the grainline, starting at pt, are contained in the parent widget and * false otherwise. */ -bool VGrainlineItem::IsContained(const QPointF& pt) const +bool VGrainlineItem::IsContained(const QPointF& pt, qreal &dX, qreal &dY) const { + dX = 0; + dY = 0; + QPointF apt[2]; + apt[0] = pt; + apt[1].setX(pt.x() + m_dLength * cos(m_dRotation)); + apt[1].setY(pt.y() + m_dLength * sin(m_dRotation)); + // single point differences + qreal dPtX; + qreal dPtY; + bool bInside = true; + QRectF rectParent = parentItem()->boundingRect(); - if (rectParent.contains(pt) == false) + for (int i = 0; i < 2; ++i) { - qDebug() << "First point out" << pt << rectParent; - return false; + dPtX = 0; + dPtY = 0; + if (rectParent.contains(apt[i]) == false) + { + if (apt[i].x() < rectParent.left()) + { + dPtX = rectParent.left() - apt[i].x(); + } + else if (apt[i].x() > rectParent.right()) + { + dPtX = rectParent.right() - apt[i].x(); + } + if (apt[i].y() < rectParent.top()) + { + dPtY = rectParent.top() - apt[i].y(); + } + else if (apt[i].y() > rectParent.bottom()) + { + dPtY = rectParent.bottom() - apt[i].y(); + } + + if (fabs(dPtX) > fabs(dX)) + { + dX = dPtX; + } + if (fabs(dPtY) > fabs(dY)) + { + dY = dPtY; + } + + bInside = false; + } } - QPointF ptA; - ptA.setX(pt.x() + m_dLength * cos(m_dRotation)); - ptA.setY(pt.y() + m_dLength * sin(m_dRotation)); - if (rectParent.contains(ptA) == false) - { - qDebug() << "Second point out" << ptA << rectParent; - } - return (rectParent.contains(ptA)); + return bInside; } + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::SetScale sets the scale for keeping the arrows of constant size + * @param dScale scale factor + */ +void VGrainlineItem::SetScale(qreal dScale) +{ + m_dScale = dScale; + UpdateBox(); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief VGrainlineItem::mousePressEvent handles left button mouse press events @@ -203,6 +267,7 @@ void VGrainlineItem::mousePressEvent(QGraphicsSceneMouseEvent* pME) m_ptStartPos = pos(); m_ptStartMove = pME->scenePos(); UpdateBox(); + SetOverrideCursor(cursorArrowCloseHand, 1, 1); } } @@ -216,13 +281,17 @@ void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME) if (m_eMode == mMove) { QPointF ptDiff = pME->scenePos() - m_ptStartMove; - QPointF pt = m_ptStartPos + ptDiff/2; - if (IsContained(pt) == true) + QPointF pt = m_ptStartPos + ptDiff; + qreal dX; + qreal dY; + if (IsContained(pt, dX, dY) == false) { - setPos(pt); - UpdateRectangle(); - UpdateBox(); + pt.setX(pt.x() + dX); + pt.setY(pt.y() + dY); } + setPos(pt); + UpdateRectangle(); + UpdateBox(); } } @@ -245,6 +314,7 @@ void VGrainlineItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME) emit SignalMoved(pos()); } } + RestoreOverrideCursor(cursorArrowCloseHand); } } @@ -265,7 +335,7 @@ void VGrainlineItem::UpdateBox() void VGrainlineItem::UpdateRectangle() { m_polyBound.clear(); - QPointF pt1 = pos(); + QPointF pt1(0, 0); QPointF pt2; pt2.setX(pt1.x() + m_dLength * cos(m_dRotation)); @@ -285,4 +355,6 @@ void VGrainlineItem::UpdateRectangle() ptA.setY(pt2.y() + RECT_WIDTH*sin(m_dRotation + M_PI/2)); m_polyBound << ptA; m_rectBoundingBox = m_polyBound.boundingRect(); + setTransformOriginPoint(m_rectBoundingBox.center()); + prepareGeometryChange(); } diff --git a/src/libs/vtools/tools/vgrainlineitem.h b/src/libs/vtools/tools/vgrainlineitem.h index 0ffa0c653..9475a46c9 100644 --- a/src/libs/vtools/tools/vgrainlineitem.h +++ b/src/libs/vtools/tools/vgrainlineitem.h @@ -57,7 +57,8 @@ public: QRectF boundingRect() const; void Reset(); bool IsIdle() const; - bool IsContained(const QPointF &pt) const; + bool IsContained(const QPointF &pt, qreal &dX, qreal &dY) const; + void SetScale(qreal dScale); protected: void mousePressEvent(QGraphicsSceneMouseEvent* pME); @@ -77,6 +78,7 @@ private: QPolygonF m_polyBound; QPointF m_ptStartPos; QPointF m_ptStartMove; + qreal m_dScale; }; #endif // VGRAINLINEITEM_H diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp index 8aae46e99..58332c6e3 100644 --- a/src/libs/vtools/tools/vtooldetail.cpp +++ b/src/libs/vtools/tools/vtooldetail.cpp @@ -408,11 +408,20 @@ void VToolDetail::FullUpdateFromGuiOk(int result) //--------------------------------------------------------------------------------------------------------------------- /** - * @brief VToolDetail::paint draws a bounding box around detail, if one of its text items is not idle. + * @brief VToolDetail::paint draws a bounding box around detail, if one of its text or grainline items is not idle. */ void VToolDetail::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - if (dataLabel->IsIdle() == false || patternInfo->IsIdle() == false) + if (scene()->views().count() > 0) + { + QPoint pt0 = scene()->views().at(0)->mapFromScene(0, 0); + QPoint pt = scene()->views().at(0)->mapFromScene(0, 100); + qreal dScale = qSqrt(QPoint::dotProduct(pt - pt0, pt - pt0)); + grainLine->SetScale(100/dScale); + qDebug() << "SCALE" << dScale << 10/dScale; + } + + if (dataLabel->IsIdle() == false || patternInfo->IsIdle() == false || grainLine->IsIdle() == false) { painter->save(); painter->setPen(QPen(Qt::black, 3, Qt::DashLine)); @@ -915,7 +924,8 @@ void VToolDetail::UpdateGrainline() grainLine->hide(); return; } - grainLine->UpdateGeometry(geom.GetPos(), dRotation, dLength); + + grainLine->UpdateGeometry(geom.GetPos(), dRotation, ToPixel(dLength, *VDataTool::data.GetPatternUnit())); grainLine->show(); } else