Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: rotate snap indicator and snap rotated items #1168

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions src/board/UBBoardView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,14 @@ void UBBoardView::handleItemsSelection(QGraphicsItem *item)
{
scene()->deselectAllItemsExcept(item);
scene()->updateSelectionFrame();

// calculate initial corner points
mCornerPoints.clear();
const auto bounds = UBGraphicsScene::itemRect(item);
mCornerPoints << item->mapToScene(bounds.topLeft());
mCornerPoints << item->mapToScene(bounds.topRight());
mCornerPoints << item->mapToScene(bounds.bottomLeft());
mCornerPoints << item->mapToScene(bounds.bottomRight());
}
}
}
Expand Down Expand Up @@ -774,6 +782,7 @@ QGraphicsItem* UBBoardView::determineItemToMove(QGraphicsItem *item)
void UBBoardView::handleItemMousePress(QMouseEvent *event)
{
mLastPressedMousePos = mapToScene(event->pos());
mFirstPressedMousePos = mLastPressedMousePos;

// Determining item who will take mouse press event
//all other items will be deselected and if all item will be deselected, then
Expand Down Expand Up @@ -852,13 +861,29 @@ void UBBoardView::handleItemMouseMove(QMouseEvent *event)
// snap to grid
if (scene()->isSnapping())
{
QRectF rect = UBGraphicsScene::itemRect(movingItem);
Qt::Corner corner;
auto offset = scene()->snap(rect, &corner);
newPos += offset;
QPointF moved = scenePos - mFirstPressedMousePos;
std::vector<QPointF> corners;

for (const auto& cornerPoint : mCornerPoints)
{
corners.push_back(cornerPoint + moved);
}

int snapIndex;
QPointF snapVector = scene()->snap(corners, &snapIndex);
Qt::Corner corner = Qt::Corner(snapIndex);

if (!snapVector.isNull())
{
auto* view = UBApplication::boardController->controlView();
const auto angle = QLineF{corners.at(0), corners.at(1)}.angle();
view->updateSnapIndicator(corner, corners.at(snapIndex) + snapVector, angle);
}

newPos += snapVector;
movingItem->setPos(newPos);

mLastPressedMousePos = scenePos + offset;
mLastPressedMousePos = scenePos + snapVector;
}
else
{
Expand Down Expand Up @@ -944,15 +969,15 @@ void UBBoardView::setMultiselection(bool enable)
mMultipleSelectionIsEnabled = enable;
}

void UBBoardView::updateSnapIndicator(Qt::Corner corner, QPointF snapPoint)
void UBBoardView::updateSnapIndicator(Qt::Corner corner, QPointF snapPoint, double angle)
{
if (!mSnapIndicator)
{
mSnapIndicator = new UBSnapIndicator(this);
mSnapIndicator->resize(120, 120);
}

mSnapIndicator->appear(corner, snapPoint);
mSnapIndicator->appear(corner, snapPoint, angle);
}

void UBBoardView::setBoxing(const QMargins& margins)
Expand Down
5 changes: 3 additions & 2 deletions src/board/UBBoardView.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class UBBoardView : public QGraphicsView
bool isMultipleSelectionEnabled() { return mMultipleSelectionIsEnabled; }

void setBoxing(const QMargins& margins);
void updateSnapIndicator(Qt::Corner corner, QPointF snapPoint);
void updateSnapIndicator(Qt::Corner corner, QPointF snapPoint, double angle = 0);

// work around for handling tablet events on MAC OS with Qt 4.8.0 and above
#if defined(Q_OS_OSX)
Expand Down Expand Up @@ -165,8 +165,9 @@ class UBBoardView : public QGraphicsView
bool mOkOnWidget;

bool mWidgetMoved;
QPointF mFirstPressedMousePos;
QPointF mLastPressedMousePos;

QList<QPointF> mCornerPoints;

/* when an item is moved around, the tracking must stop if the object is deleted */
QGraphicsItem *_movingItem;
Expand Down
86 changes: 63 additions & 23 deletions src/domain/UBGraphicsDelegateFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,6 @@ void UBGraphicsDelegateFrame::mousePressEvent(QGraphicsSceneMouseEvent *event)
mDelegate->startUndoStep();

mStartingPoint = event->scenePos();
mStartingBounds = UBGraphicsScene::itemRect(delegated());

initializeTransform();

Expand All @@ -293,6 +292,27 @@ void UBGraphicsDelegateFrame::mousePressEvent(QGraphicsSceneMouseEvent *event)
mRotatedAngle = mAngle;

mInitialTransform = buildTransform();

// calculate initial corner points and respect mirroring
mCornerPoints.clear();
const auto bounds = UBGraphicsScene::itemRect(delegated());
mCornerPoints << delegated()->mapToScene(bounds.topLeft());
mCornerPoints << delegated()->mapToScene(bounds.topRight());
mCornerPoints << delegated()->mapToScene(bounds.bottomLeft());
mCornerPoints << delegated()->mapToScene(bounds.bottomRight());

if (mMirrorX)
{
std::swap(mCornerPoints[0], mCornerPoints[1]);
std::swap(mCornerPoints[2], mCornerPoints[3]);
}

if (mMirrorY)
{
std::swap(mCornerPoints[0], mCornerPoints[2]);
std::swap(mCornerPoints[1], mCornerPoints[3]);
}

mOriginalSize = delegated()->boundingRect().size();

mCurrentTool = toolFromPos(event->pos());
Expand Down Expand Up @@ -420,8 +440,9 @@ void UBGraphicsDelegateFrame::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
return;

QLineF move = QLineF(mStartingPoint, event->scenePos());
qreal moveX = (event->pos() - mStartingPoint).x();
qreal moveY = (event->pos() - mStartingPoint).y();
QPointF itemStartingPoint = mapFromScene(mStartingPoint);
qreal moveX = (event->pos() - itemStartingPoint).x();
qreal moveY = (event->pos() - itemStartingPoint).y();
qreal width = delegated()->boundingRect().width() * mTotalScaleX;
qreal height = delegated()->boundingRect().height() * mTotalScaleY;

Expand All @@ -430,13 +451,20 @@ void UBGraphicsDelegateFrame::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
if(!rotating())
{
const auto* ubscene = dynamic_cast<UBGraphicsScene*>(scene());
constexpr double epsilon = 0.0001;

if (ubscene && ubscene->isSnapping())
if (ubscene && ubscene->isSnapping() && !resizingBottomRight() && std::fmod(mAngle + epsilon, 90.) <= 2. * epsilon)
{
QPointF snap = snapVector(event->scenePos());
move.setP2(move.p2() + snap);

// rotate the snap according to item angle
QLineF snapLine{{}, snap};
snapLine.setAngle(snapLine.angle() - mAngle);
snap = snapLine.p2();

moveX += snap.x();
moveY += snap.y();
move.setP2(move.p2() + snap);
}

mTranslateX = moveX;
Expand Down Expand Up @@ -574,10 +602,23 @@ void UBGraphicsDelegateFrame::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
// snap to grid
QPointF moved = event->scenePos() - mStartingPoint;
QRectF movedBounds = mStartingBounds.translated(moved);
std::vector<QPointF> corners;

for (const auto& cornerPoint : mCornerPoints)
{
corners.push_back(cornerPoint + moved);
}

int snapIndex;
QPointF snapVector = ubscene->snap(corners, &snapIndex);
Qt::Corner corner = Qt::Corner(snapIndex);

if (!snapVector.isNull())
{
auto* view = UBApplication::boardController->controlView();
view->updateSnapIndicator(corner, corners.at(snapIndex) + snapVector, mAngle);
}

Qt::Corner corner;
QPointF snapVector = ubscene->snap(movedBounds, &corner);
moveX += snapVector.x();
moveY += snapVector.y();
move.setP2(move.p2() + snapVector);
Expand Down Expand Up @@ -1091,33 +1132,32 @@ void UBGraphicsDelegateFrame::refreshGeometry()

QPointF UBGraphicsDelegateFrame::snapVector(QPointF scenePos) const
{
QPointF moved = scenePos - mStartingPoint;
QRectF movedBounds = mStartingBounds.translated(moved);
const auto moved = scenePos - mStartingPoint;
std::vector<QPointF> corners;

if (resizingLeft())
if (resizingLeft() && !mMirrorX || resizingRight() && mMirrorX)
{
corners.push_back(movedBounds.topLeft());
corners.push_back(movedBounds.bottomLeft());
corners.push_back(mCornerPoints[0] + moved);
corners.push_back(mCornerPoints[2] + moved);
}
else if (resizingRight())
else if (resizingRight() && !mMirrorX || resizingLeft() && mMirrorX)
{
corners.push_back(movedBounds.topRight());
corners.push_back(movedBounds.bottomRight());
corners.push_back(mCornerPoints[1] + moved);
corners.push_back(mCornerPoints[3] + moved);
}
else if (resizingTop())
else if (resizingTop() && !mMirrorY || resizingBottom() && mMirrorY)
{
corners.push_back(movedBounds.topLeft());
corners.push_back(movedBounds.topRight());
corners.push_back(mCornerPoints[0] + moved);
corners.push_back(mCornerPoints[1] + moved);
}
else if (resizingBottom())
else if (resizingBottom() && !mMirrorY || resizingTop() && mMirrorY)
{
corners.push_back(movedBounds.bottomLeft());
corners.push_back(movedBounds.bottomRight());
corners.push_back(mCornerPoints[2] + moved);
corners.push_back(mCornerPoints[3] + moved);
}
else if (resizingBottomRight())
{
corners.push_back(movedBounds.bottomRight());
corners.push_back(mCornerPoints[3] + moved);
}

UBGraphicsScene* ubscene = dynamic_cast<UBGraphicsScene*>(scene());
Expand Down
2 changes: 1 addition & 1 deletion src/domain/UBGraphicsDelegateFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ class UBGraphicsDelegateFrame: public QGraphicsRectItem, public QObject
QRect mAngleRect;

QPointF mStartingPoint;
QRectF mStartingBounds;
QTransform mInitialTransform;
QList<QPointF> mCornerPoints;
QSizeF mOriginalSize;
QPointF mFixedPoint;

Expand Down
6 changes: 2 additions & 4 deletions src/domain/UBGraphicsScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2626,7 +2626,7 @@ QPointF UBGraphicsScene::snap(const QRectF& rect, Qt::Corner* corner) const

QRectF UBGraphicsScene::itemRect(const QGraphicsItem* item)
{
// compute an item's rectangle in scene coordinates
// compute an item's rectangle in item coordinates
// taking into account the shape of the item and
// the nature of nominal lines
QRectF bounds = item->boundingRect();
Expand Down Expand Up @@ -2655,9 +2655,7 @@ QRectF UBGraphicsScene::itemRect(const QGraphicsItem* item)
}
}

QRectF rect = item->mapRectToScene(bounds);

return rect;
return bounds;
}

void UBGraphicsScene::addMask(const QPointF &center)
Expand Down
80 changes: 36 additions & 44 deletions src/gui/UBSnapIndicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
#include <QPropertyAnimation>

#include "board/UBBoardController.h"
#include "board/UBBoardPaletteManager.h"
#include "board/UBBoardView.h"
#include "core/UBApplication.h"

UBSnapIndicator::UBSnapIndicator(QWidget* parent)
: QLabel(parent)
Expand All @@ -42,23 +40,42 @@ UBSnapIndicator::UBSnapIndicator(QWidget* parent)
connect(mAnimation, &QPropertyAnimation::finished, this, &QWidget::hide);
}

void UBSnapIndicator::appear(Qt::Corner corner, QPointF snapPoint)
void UBSnapIndicator::appear(Qt::Corner corner, QPointF snapPoint, double angle)
{
if (corner != mCorner)
mAnimation->stop();
mAngle = -angle; // painter rotate is clockwise

switch (corner)
{
mAnimation->stop();
mCorner = corner;
show();
case Qt::TopLeftCorner:
mAngle += 270;
break;

case Qt::TopRightCorner:
break;

case Qt::BottomLeftCorner:
mAngle += 180;
break;

UBBoardView* view = dynamic_cast<UBBoardView*>(parentWidget());
case Qt::BottomRightCorner:
mAngle += 90;
break;

if (view)
{
QPoint indicationPoint{view->mapFromScene(snapPoint) - QPoint(width() / 2, height() / 2)};
default:
break;
}

show();

UBBoardView* view = dynamic_cast<UBBoardView*>(parentWidget());

if (view)
{
QPoint indicationPoint{view->mapFromScene(snapPoint) - QPoint(width() / 2, height() / 2)};

move(indicationPoint);
mAnimation->start();
}
move(indicationPoint);
mAnimation->start();
}
}

Expand All @@ -81,7 +98,9 @@ void UBSnapIndicator::setColor(const QColor& color)
void UBSnapIndicator::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
QRect area = rect();

painter.translate(width() / 2, height() / 2);
painter.rotate(mAngle);

QPen pen;
QColor penColor{mColor};
Expand All @@ -91,35 +110,8 @@ void UBSnapIndicator::paintEvent(QPaintEvent* event)
painter.setPen(pen);

QPoint p1;
QPoint p2(area.center());
QPoint p3;
int dist = area.width() / 3;

switch (mCorner)
{
case Qt::TopLeftCorner:
p1 = p2 + QPoint{0, dist};
p3 = p2 + QPoint(dist, 0);
break;

case Qt::TopRightCorner:
p1 = p2 + QPoint{0, dist};
p3 = p2 + QPoint(-dist, 0);
break;

case Qt::BottomLeftCorner:
p1 = p2 + QPoint{0, -dist};
p3 = p2 + QPoint(dist, 0);
break;

case Qt::BottomRightCorner:
p1 = p2 + QPoint{0, -dist};
p3 = p2 + QPoint(-dist, 0);
break;

default:
break;
}
QPoint p2{-width() / 2, 0};
QPoint p3{0, height() / 2};

QPolygon polygon;
polygon << p1 << p2 << p3 << p1;
Expand Down
Loading