17 #include "selectionmanager.h"
20 #include "layerbitmap.h"
21 #include "vectorimage.h"
22 #include "bitmapimage.h"
24 #include "layervector.h"
25 #include "mathutils.h"
36 SelectionManager::~SelectionManager()
40 bool SelectionManager::init()
47 resetSelectionProperties();
56 void SelectionManager::workingLayerChanged(
Layer *)
64 mSelectionTransform.
reset();
67 void SelectionManager::updatePolygons()
69 mCurrentSelectionPolygonF = mTempTransformedSelection;
70 mLastSelectionPolygonF = mTransformedSelection;
73 void SelectionManager::resetSelectionTransform()
75 mSelectionTransform.
reset();
78 bool SelectionManager::isOutsideSelectionArea(
QPointF point)
80 return (!mTransformedSelection.
contains(point)
81 && validateMoveMode(point) == MoveMode::NONE);
84 bool SelectionManager::transformHasBeenModified()
86 return (mSelection != mTempTransformedSelection) || rotationHasBeenModified();
89 bool SelectionManager::rotationHasBeenModified()
91 return !qFuzzyCompare(mRotatedAngle,0);
94 void SelectionManager::deleteSelection()
96 emit needDeleteSelection();
99 void SelectionManager::clearCurves()
101 mClosestCurves.
clear();
104 void SelectionManager::clearVertices()
106 mClosestVertices.
clear();
109 qreal SelectionManager::selectionTolerance()
const
111 return qAbs(mSelectionTolerance * editor()->viewScaleInversed());
114 MoveMode SelectionManager::validateMoveMode(
QPointF pos)
116 return moveModeForAnchorInRange(pos);
119 MoveMode SelectionManager::moveModeForAnchorInRange(
QPointF lastPos)
121 QRectF transformRect = mTempTransformedSelection;
124 const double calculatedSelectionTol = selectionTolerance();
127 if (
QLineF(lastPoint, transformRect.
topLeft()).length() < calculatedSelectionTol)
129 mode = MoveMode::TOPLEFT;
131 else if (
QLineF(lastPoint, transformRect.
topRight()).length() < calculatedSelectionTol)
133 mode = MoveMode::TOPRIGHT;
135 else if (
QLineF(lastPoint, transformRect.
bottomLeft()).length() < calculatedSelectionTol)
137 mode = MoveMode::BOTTOMLEFT;
140 else if (
QLineF(lastPoint, transformRect.
bottomRight()).length() < calculatedSelectionTol)
142 mode = MoveMode::BOTTOMRIGHT;
144 else if (mTransformedSelection.
contains(lastPoint))
146 mode = MoveMode::MIDDLE;
149 mode = MoveMode::NONE;
155 MoveMode SelectionManager::getMoveModeForSelectionAnchor(
QPointF pos)
157 const double calculatedSelectionTol = selectionTolerance();
159 if (mCurrentSelectionPolygonF.
count() < 4) {
return MoveMode::NONE; }
161 QPointF topLeftCorner = mCurrentSelectionPolygonF[0];
163 QPointF topRightCorner = mCurrentSelectionPolygonF[1];
165 QPointF bottomRightCorner = mCurrentSelectionPolygonF[2];
167 QPointF bottomLeftCorner = mCurrentSelectionPolygonF[3];
171 if (
QLineF(currentPos, topLeftCorner).
length() < calculatedSelectionTol)
173 return MoveMode::TOPLEFT;
175 else if (
QLineF(currentPos, topRightCorner).
length() < calculatedSelectionTol)
177 return MoveMode::TOPRIGHT;
179 else if (
QLineF(currentPos, bottomLeftCorner).
length() < calculatedSelectionTol)
181 return MoveMode::BOTTOMLEFT;
184 else if (
QLineF(currentPos, bottomRightCorner).
length() < calculatedSelectionTol)
186 return MoveMode::BOTTOMRIGHT;
188 else if (mTempTransformedSelection.
contains(currentPos))
190 return MoveMode::MIDDLE;
193 return MoveMode::NONE;
199 MoveMode mode = getMoveModeForSelectionAnchor(currentPoint);
200 if (mode == MoveMode::TOPLEFT)
204 else if (mode == MoveMode::TOPRIGHT)
208 else if (mode == MoveMode::BOTTOMLEFT)
210 anchorPoint = mSelection.
topRight();
212 else if (mode == MoveMode::BOTTOMRIGHT)
214 anchorPoint = mSelection.
topLeft();
219 void SelectionManager::adjustSelection(
const QPointF& currentPoint, qreal offsetX, qreal offsetY, qreal rotationOffset,
int rotationIncrement)
221 offsetX = qRound(offsetX);
222 offsetY = qRound(offsetY);
223 QRectF& transformedSelection = mTransformedSelection;
227 case MoveMode::MIDDLE:
229 mTempTransformedSelection = transformedSelection.
translated(
QPointF(offsetX, offsetY));
232 case MoveMode::TOPRIGHT:
234 mTempTransformedSelection = transformedSelection.
adjusted(0, offsetY, offsetX, 0);
237 case MoveMode::TOPLEFT:
239 mTempTransformedSelection = transformedSelection.
adjusted(offsetX, offsetY, 0, 0);
242 case MoveMode::BOTTOMLEFT:
244 mTempTransformedSelection = transformedSelection.
adjusted(offsetX, 0, 0, offsetY);
247 case MoveMode::BOTTOMRIGHT:
249 mTempTransformedSelection = transformedSelection.
adjusted(0, 0, offsetX, offsetY);
253 case MoveMode::ROTATION:
255 mTempTransformedSelection = transformedSelection;
257 qreal rotatedAngle = qRadiansToDegrees(MathUtils::getDifferenceAngle(anchorPoint, currentPoint)) - rotationOffset;
258 if (rotationIncrement > 0) {
259 mRotatedAngle = constrainRotationToAngle(rotatedAngle, rotationIncrement);
261 mRotatedAngle = rotatedAngle;
270 int SelectionManager::constrainRotationToAngle(
const qreal& rotatedAngle,
const int& rotationIncrement)
const
272 return qRound(rotatedAngle / rotationIncrement) * rotationIncrement;
275 void SelectionManager::setSelection(
QRectF rect,
bool roundPixels)
283 mTransformedSelection = rect;
284 mTempTransformedSelection = rect;
285 mSomethingSelected = (mSelection.
isNull() ?
false :
true);
287 emit selectionChanged();
290 void SelectionManager::calculateSelectionTransformation()
294 mSelectionTransform.
reset();
296 mSelectionTransform.
translate(centerPoints[0].x(), centerPoints[0].y());
297 mSelectionTransform.
rotate(mRotatedAngle);
299 if (mSelection.
width() > 0 && mSelection.
height() > 0)
301 qreal scaleX = mTempTransformedSelection.
width() / mSelection.
width();
302 qreal scaleY = mTempTransformedSelection.
height() / mSelection.
height();
303 mSelectionTransform.
scale(scaleX, scaleY);
305 mSelectionTransform.
translate(-centerPoints[1].x(), -centerPoints[1].y());
311 qreal selectionCenterX,
313 tempSelectionCenterX,
314 tempSelectionCenterY;
316 tempSelectionCenterX = mTempTransformedSelection.
center().
x();
317 tempSelectionCenterY = mTempTransformedSelection.
center().
y();
318 selectionCenterX = mSelection.
center().
x();
319 selectionCenterY = mSelection.
center().
y();
320 centerPoints.
append(
QPointF(tempSelectionCenterX, tempSelectionCenterY));
321 centerPoints.
append(
QPointF(selectionCenterX, selectionCenterY));
326 QPointF SelectionManager::offsetFromAspectRatio(qreal offsetX, qreal offsetY)
328 qreal factor = mTransformedSelection.
width() / mTransformedSelection.
height();
330 if (mMoveMode == MoveMode::TOPLEFT || mMoveMode == MoveMode::BOTTOMRIGHT)
332 offsetY = offsetX / factor;
334 else if (mMoveMode == MoveMode::TOPRIGHT || mMoveMode == MoveMode::BOTTOMLEFT)
336 offsetY = -(offsetX / factor);
338 else if (mMoveMode == MoveMode::MIDDLE)
340 qreal absX = offsetX;
341 if (absX < 0) { absX = -absX; }
343 qreal absY = offsetY;
344 if (absY < 0) { absY = -absY; }
346 if (absX > absY) { offsetY = 0; }
347 if (absY > absX) { offsetX = 0; }
349 return QPointF(offsetX, offsetY);
360 editor()->backup(
tr(
"Flip selection vertically"));
364 editor()->backup(
tr(
"Flip selection horizontally"));
367 qreal scaleX = mTempTransformedSelection.
width() / mSelection.
width();
368 qreal scaleY = mTempTransformedSelection.
height() / mSelection.
height();
381 mSelectionTransform.
reset();
382 mSelectionTransform *= _translate * scale * translate;
384 emit needPaintAndApply();
387 void SelectionManager::translate(
QPointF point)
389 mTempTransformedSelection.
translate(point);
390 mTransformedSelection = mTempTransformedSelection;
391 calculateSelectionTransformation();
394 void SelectionManager::resetSelectionProperties()
398 mTransformedSelection =
QRectF();
399 mTempTransformedSelection =
QRectF();
403 mSomethingSelected =
false;
404 vectorSelection.clear();
406 emit selectionChanged();
void append(const T &value)
bool contains(const QRectF &rectangle) const const
void resetSelectionTransformProperties()
SelectionManager::resetSelectionTransformProperties should be used whenever translate, rotate, transform, scale has been applied to a selection, but don't want to reset size nor position.
QString tr(const char *sourceText, const char *disambiguation, int n)
qreal length() const const
void translate(qreal dx, qreal dy)
QPointF topLeft() const const
QPointF center() const const
QPointF topRight() const const
bool isNull() const const
qreal width() const const
QPoint toPoint() const const
QRectF translated(qreal dx, qreal dy) const const
QPointF bottomLeft() const const
int count(const T &value) const const
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const const
qreal height() const const
void flipSelection(bool flipVertical)
ScribbleArea::flipSelection flip selection along the X or Y axis.
QPointF bottomRight() const const