Sticky edges.
This commit is contained in:
parent
3d9a4f6f65
commit
b877009d90
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include "../vmisc/def.h"
|
#include "../vmisc/def.h"
|
||||||
#include "vpsheet.h"
|
#include "vpsheet.h"
|
||||||
|
#include "vplayout.h"
|
||||||
#include "../vlayout/vtextmanager.h"
|
#include "../vlayout/vtextmanager.h"
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
@ -39,6 +40,86 @@
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(pPiece, "p.piece")
|
Q_LOGGING_CATEGORY(pPiece, "p.piece")
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr qreal minStickyDistance = ToPixel(3, Unit::Mm);
|
||||||
|
constexpr qreal maxStickyDistance = ToPixel(10, Unit::Mm);
|
||||||
|
constexpr qreal stickyShift = ToPixel(1, Unit::Mm);
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
auto CutEdge(const QLineF &edge) -> QVector<QPointF>
|
||||||
|
{
|
||||||
|
QVector<QPointF> points;
|
||||||
|
if (qFuzzyIsNull(stickyShift))
|
||||||
|
{
|
||||||
|
points.append(edge.p1());
|
||||||
|
points.append(edge.p2());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int n = qFloor(edge.length()/stickyShift);
|
||||||
|
|
||||||
|
if (n <= 0)
|
||||||
|
{
|
||||||
|
points.append(edge.p1());
|
||||||
|
points.append(edge.p2());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
points.reserve(n);
|
||||||
|
const qreal nShift = edge.length()/n;
|
||||||
|
for (int i = 1; i <= n+1; ++i)
|
||||||
|
{
|
||||||
|
QLineF l1 = edge;
|
||||||
|
l1.setLength(nShift*(i-1));
|
||||||
|
points.append(l1.p2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
auto PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF>
|
||||||
|
{
|
||||||
|
if (path.size() < 2)
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QPointF> stickyPath;
|
||||||
|
|
||||||
|
for (int i=0; i<path.size(); ++i)
|
||||||
|
{
|
||||||
|
stickyPath += CutEdge(QLineF(path.at(i), path.at(i < path.size()-1 ? i+1 : 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return stickyPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
auto ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF
|
||||||
|
{
|
||||||
|
qreal distance = INT_MAX;
|
||||||
|
QLineF closestDistance;
|
||||||
|
|
||||||
|
for (auto p1 : path1)
|
||||||
|
{
|
||||||
|
for (auto p2 : path2)
|
||||||
|
{
|
||||||
|
QLineF d(p1, p2);
|
||||||
|
if (d.length() <= distance)
|
||||||
|
{
|
||||||
|
distance = d.length();
|
||||||
|
closestDistance = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closestDistance;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VPPiece::VPPiece(const VLayoutPiece &layoutPiece)
|
VPPiece::VPPiece(const VLayoutPiece &layoutPiece)
|
||||||
: VLayoutPiece(layoutPiece)
|
: VLayoutPiece(layoutPiece)
|
||||||
|
@ -239,3 +320,111 @@ void VPPiece::Flip()
|
||||||
SetMatrix(pieceMatrix);
|
SetMatrix(pieceMatrix);
|
||||||
SetMirror(!IsMirror());
|
SetMirror(!IsMirror());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
auto VPPiece::StickyPosition(qreal &dx, qreal &dy) const -> bool
|
||||||
|
{
|
||||||
|
VPLayoutPtr layout = Layout();
|
||||||
|
if (layout.isNull() || not layout->LayoutSettings().GetStickyEdges())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qreal pieceGap = layout->LayoutSettings().GetPiecesGap();
|
||||||
|
if (pieceGap <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VPSheetPtr sheet = Sheet();
|
||||||
|
if (sheet.isNull())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<VPPiecePtr> allPieces = sheet->GetPieces();
|
||||||
|
|
||||||
|
if (allPieces.count() < 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QPointF> path = GetMappedExternalContourPoints();
|
||||||
|
QRectF boundingRect = VLayoutPiece::BoundingRect(path);
|
||||||
|
const qreal stickyDistance = pieceGap+minStickyDistance;
|
||||||
|
QRectF stickyZone = QRectF(boundingRect.topLeft().x()-stickyDistance, boundingRect.topLeft().y()-stickyDistance,
|
||||||
|
boundingRect.width()+stickyDistance*2, boundingRect.height()+stickyDistance*2);
|
||||||
|
|
||||||
|
QVector<QPointF> stickyPath = PrepareStickyPath(path);
|
||||||
|
QLineF closestDistance;
|
||||||
|
|
||||||
|
for (const auto& piece : allPieces)
|
||||||
|
{
|
||||||
|
if (piece.isNull() || piece->GetUniqueID() == GetUniqueID())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QPointF> piecePath = piece->GetMappedExternalContourPoints();
|
||||||
|
QRectF pieceBoundingRect = VLayoutPiece::BoundingRect(piecePath);
|
||||||
|
|
||||||
|
if (stickyZone.intersects(pieceBoundingRect) || pieceBoundingRect.contains(stickyZone) ||
|
||||||
|
stickyZone.contains(pieceBoundingRect))
|
||||||
|
{
|
||||||
|
if (not VPPiece::PathsSuperposition(path, piecePath))
|
||||||
|
{
|
||||||
|
QVector<QPointF> pieceStickyPath = PrepareStickyPath(piecePath);
|
||||||
|
closestDistance = ClosestDistance(stickyPath, pieceStickyPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closestDistance.isNull())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qreal extraZone = qBound(minStickyDistance, pieceGap * 50 / 100, maxStickyDistance);
|
||||||
|
const qreal length = closestDistance.length();
|
||||||
|
|
||||||
|
if (length > pieceGap && length <= pieceGap + extraZone)
|
||||||
|
{
|
||||||
|
closestDistance.setLength(length - pieceGap);
|
||||||
|
QPointF diff = closestDistance.p2() - closestDistance.p1();
|
||||||
|
dx = diff.x();
|
||||||
|
dy = diff.y();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < pieceGap && length >= pieceGap - extraZone)
|
||||||
|
{
|
||||||
|
closestDistance.setAngle(closestDistance.angle() + 180);
|
||||||
|
closestDistance.setLength(pieceGap - length);
|
||||||
|
QPointF diff = closestDistance.p2() - closestDistance.p1();
|
||||||
|
dx = diff.x();
|
||||||
|
dy = diff.y();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
auto VPPiece::PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> bool
|
||||||
|
{
|
||||||
|
const QRectF path1Rect = VLayoutPiece::BoundingRect(path1);
|
||||||
|
const QPainterPath path1Path = VAbstractPiece::PainterPath(path1);
|
||||||
|
|
||||||
|
const QRectF path2Rect = VLayoutPiece::BoundingRect(path2);
|
||||||
|
const QPainterPath path2Path = VAbstractPiece::PainterPath(path2);
|
||||||
|
|
||||||
|
if (path1Rect.intersects(path2Rect) || path2Rect.contains(path1Rect) || path1Rect.contains(path2Rect))
|
||||||
|
{
|
||||||
|
if (path1Path.contains(path2Path) || path2Path.contains(path1Path) || path1Path.intersects(path2Path))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -112,6 +112,10 @@ public:
|
||||||
auto HasSuperpositionWithPieces() const -> bool;
|
auto HasSuperpositionWithPieces() const -> bool;
|
||||||
void SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces);
|
void SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces);
|
||||||
|
|
||||||
|
auto StickyPosition(qreal &dx, qreal &dy) const -> bool;
|
||||||
|
|
||||||
|
static auto PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> bool;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(VPPiece)
|
Q_DISABLE_COPY(VPPiece)
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ void VPSheet::ValidateSuperpositionOfPieces() const
|
||||||
|
|
||||||
QVector<QPointF> path2 = p->GetMappedExternalContourPoints();
|
QVector<QPointF> path2 = p->GetMappedExternalContourPoints();
|
||||||
|
|
||||||
bool superposition = PathsSuperposition(path1, path2);
|
bool superposition = VPPiece::PathsSuperposition(path1, path2);
|
||||||
if (superposition)
|
if (superposition)
|
||||||
{
|
{
|
||||||
hasSuperposition = superposition;
|
hasSuperposition = superposition;
|
||||||
|
@ -313,23 +313,3 @@ void VPSheet::CheckPiecePositionValidity(const VPPiecePtr &piece) const
|
||||||
ValidateSuperpositionOfPieces();
|
ValidateSuperpositionOfPieces();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
auto VPSheet::PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) const -> bool
|
|
||||||
{
|
|
||||||
const QRectF path1Rect = VLayoutPiece::BoundingRect(path1);
|
|
||||||
const QPainterPath path1Path = VAbstractPiece::PainterPath(path1);
|
|
||||||
|
|
||||||
const QRectF path2Rect = VLayoutPiece::BoundingRect(path2);
|
|
||||||
const QPainterPath path2Path = VAbstractPiece::PainterPath(path2);
|
|
||||||
|
|
||||||
if (path1Rect.intersects(path2Rect) || path2Rect.contains(path1Rect) || path1Rect.contains(path2Rect))
|
|
||||||
{
|
|
||||||
if (path1Path.contains(path2Path) || path2Path.contains(path1Path) || path1Path.intersects(path2Path))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ private:
|
||||||
|
|
||||||
VPTransformationOrigon m_transformationOrigin{};
|
VPTransformationOrigon m_transformationOrigin{};
|
||||||
|
|
||||||
auto PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) const -> bool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(VPSheetPtr)
|
Q_DECLARE_METATYPE(VPSheetPtr)
|
||||||
|
|
|
@ -94,6 +94,7 @@ auto VPGraphicsPiece::boundingRect() const -> QRectF
|
||||||
shape.addPath(m_internalPaths);
|
shape.addPath(m_internalPaths);
|
||||||
shape.addPath(m_passmarks);
|
shape.addPath(m_passmarks);
|
||||||
shape.addPath(m_placeLabels);
|
shape.addPath(m_placeLabels);
|
||||||
|
shape.addPath(m_stickyPath);
|
||||||
|
|
||||||
constexpr qreal halfPenWidth = penWidth/2.;
|
constexpr qreal halfPenWidth = penWidth/2.;
|
||||||
|
|
||||||
|
@ -136,6 +137,7 @@ void VPGraphicsPiece::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
|
||||||
m_moveStartPoint = event->pos();
|
m_moveStartPoint = event->pos();
|
||||||
emit HideTransformationHandles(true);
|
emit HideTransformationHandles(true);
|
||||||
|
m_hasStickyPosition = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +163,26 @@ void VPGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
setCursor(Qt::OpenHandCursor);
|
setCursor(Qt::OpenHandCursor);
|
||||||
emit HideTransformationHandles(false);
|
emit HideTransformationHandles(false);
|
||||||
|
|
||||||
|
VPPiecePtr piece = m_piece.toStrongRef();
|
||||||
|
if (not piece.isNull())
|
||||||
|
{
|
||||||
|
VPLayoutPtr layout = piece->Layout();
|
||||||
|
if (not layout.isNull())
|
||||||
|
{
|
||||||
|
if (layout->LayoutSettings().GetStickyEdges() && m_hasStickyPosition)
|
||||||
|
{
|
||||||
|
auto *command = new VPUndoPieceMove(piece, m_stickyTranslateX, m_stickyTranslateY,
|
||||||
|
allowChangeMerge);
|
||||||
|
layout->UndoStack()->push(command);
|
||||||
|
|
||||||
|
SetStickyPoints(QVector<QPointF>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allowChangeMerge = false;
|
allowChangeMerge = false;
|
||||||
|
m_hasStickyPosition = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +239,15 @@ void VPGraphicsPiece::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VPGraphicsPiece::SetStickyPoints(const QVector<QPointF> &newStickyPoint)
|
||||||
|
{
|
||||||
|
m_stickyPoints = newStickyPoint;
|
||||||
|
|
||||||
|
prepareGeometryChange();
|
||||||
|
PaintPiece(); // refresh shapes
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VPGraphicsPiece::PaintPieceLabel(const QVector<QPointF> &labelShape, const VTextManager &tm, QPainter *painter)
|
void VPGraphicsPiece::PaintPieceLabel(const QVector<QPointF> &labelShape, const VTextManager &tm, QPainter *painter)
|
||||||
{
|
{
|
||||||
|
@ -329,6 +359,7 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
|
||||||
m_internalPaths = QPainterPath();
|
m_internalPaths = QPainterPath();
|
||||||
m_passmarks = QPainterPath();
|
m_passmarks = QPainterPath();
|
||||||
m_placeLabels = QPainterPath();
|
m_placeLabels = QPainterPath();
|
||||||
|
m_stickyPath = QPainterPath();
|
||||||
|
|
||||||
VPPiecePtr piece = m_piece.toStrongRef();
|
VPPiecePtr piece = m_piece.toStrongRef();
|
||||||
if (piece.isNull())
|
if (piece.isNull())
|
||||||
|
@ -457,6 +488,29 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter)
|
||||||
|
|
||||||
PaintPieceLabel(piece->GetPieceLabelRect(), piece->GetPieceLabelData(), painter);
|
PaintPieceLabel(piece->GetPieceLabelRect(), piece->GetPieceLabelData(), painter);
|
||||||
PaintPieceLabel(piece->GetPatternLabelRect(), piece->GetPatternLabelData(), painter);
|
PaintPieceLabel(piece->GetPatternLabelRect(), piece->GetPatternLabelData(), painter);
|
||||||
|
|
||||||
|
if (not m_stickyPoints.isEmpty())
|
||||||
|
{
|
||||||
|
m_stickyPath.moveTo(m_stickyPoints.first());
|
||||||
|
for (int i = 1; i < m_stickyPoints.size(); i++)
|
||||||
|
{
|
||||||
|
m_stickyPath.lineTo(m_stickyPoints.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (painter != nullptr)
|
||||||
|
{
|
||||||
|
painter->save();
|
||||||
|
painter->setBrush(QBrush(Qt::BDiagPattern));
|
||||||
|
|
||||||
|
QPen pen = painter->pen();
|
||||||
|
pen.setStyle(Qt::DashLine);
|
||||||
|
pen.setColor(mainColor);
|
||||||
|
painter->setPen(pen);
|
||||||
|
|
||||||
|
painter->drawPath(m_stickyPath);
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -497,8 +551,28 @@ void VPGraphicsPiece::GroupMove(const QPointF &pos)
|
||||||
|
|
||||||
if (pieces.size() == 1)
|
if (pieces.size() == 1)
|
||||||
{
|
{
|
||||||
auto *command = new VPUndoPieceMove(pieces.first(), newPos.x(), newPos.y(), allowChangeMerge);
|
VPPiecePtr p = pieces.first();
|
||||||
|
auto *command = new VPUndoPieceMove(piece, newPos.x(), newPos.y(), allowChangeMerge);
|
||||||
layout->UndoStack()->push(command);
|
layout->UndoStack()->push(command);
|
||||||
|
|
||||||
|
if (layout->LayoutSettings().GetStickyEdges())
|
||||||
|
{
|
||||||
|
QVector<QPointF> path;
|
||||||
|
if (not p.isNull() && p->StickyPosition(m_stickyTranslateX, m_stickyTranslateY))
|
||||||
|
{
|
||||||
|
path = p->GetMappedExternalContourPoints();
|
||||||
|
QTransform m;
|
||||||
|
m.translate(m_stickyTranslateX, m_stickyTranslateY);
|
||||||
|
path = m.map(path);
|
||||||
|
m_hasStickyPosition = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_hasStickyPosition = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetStickyPoints(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (pieces.size() > 1)
|
else if (pieces.size() > 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,6 +53,8 @@ public:
|
||||||
virtual int type() const override {return Type;}
|
virtual int type() const override {return Type;}
|
||||||
enum { Type = UserType + static_cast<int>(PGraphicsItem::Piece)};
|
enum { Type = UserType + static_cast<int>(PGraphicsItem::Piece)};
|
||||||
|
|
||||||
|
void SetStickyPoints(const QVector<QPointF> &newStickyPoint);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HideTransformationHandles(bool hide);
|
void HideTransformationHandles(bool hide);
|
||||||
void PieceTransformationChanged();
|
void PieceTransformationChanged();
|
||||||
|
@ -91,6 +93,13 @@ private:
|
||||||
|
|
||||||
bool allowChangeMerge{false};
|
bool allowChangeMerge{false};
|
||||||
|
|
||||||
|
QVector<QPointF> m_stickyPoints{};
|
||||||
|
QPainterPath m_stickyPath{};
|
||||||
|
|
||||||
|
bool m_hasStickyPosition{false};
|
||||||
|
qreal m_stickyTranslateX{0};
|
||||||
|
qreal m_stickyTranslateY{0};
|
||||||
|
|
||||||
void PaintPieceLabel(const QVector<QPointF> &labelShape, const VTextManager &tm, QPainter *painter=nullptr);
|
void PaintPieceLabel(const QVector<QPointF> &labelShape, const VTextManager &tm, QPainter *painter=nullptr);
|
||||||
void PaintPiece(QPainter *painter=nullptr);
|
void PaintPiece(QPainter *painter=nullptr);
|
||||||
|
|
||||||
|
|
|
@ -302,7 +302,7 @@ void VPMainGraphicsView::keyPressEvent(QKeyEvent *event)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TranslatePiecesOn(0, 1);
|
TranslatePiecesOn(0, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event->key() == Qt::Key_Down)
|
else if (event->key() == Qt::Key_Down)
|
||||||
|
@ -360,7 +360,48 @@ void VPMainGraphicsView::keyReleaseEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
if (not event->isAutoRepeat())
|
if (not event->isAutoRepeat())
|
||||||
{
|
{
|
||||||
|
if (m_hasStickyPosition && not m_graphicsPieces.isEmpty())
|
||||||
|
{
|
||||||
|
VPPiecePtr piece = m_graphicsPieces.first()->GetPiece();
|
||||||
|
if (not piece.isNull())
|
||||||
|
{
|
||||||
|
VPLayoutPtr layout = piece->Layout();
|
||||||
|
if (not layout.isNull() && layout->LayoutSettings().GetStickyEdges())
|
||||||
|
{
|
||||||
|
auto PreparePieces = [layout]()
|
||||||
|
{
|
||||||
|
QList<VPPiecePtr> pieces;
|
||||||
|
VPSheetPtr sheet = layout->GetFocusedSheet();
|
||||||
|
if (not sheet.isNull())
|
||||||
|
{
|
||||||
|
pieces = sheet->GetSelectedPieces();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pieces;
|
||||||
|
};
|
||||||
|
|
||||||
|
QList<VPPiecePtr> pieces = PreparePieces();
|
||||||
|
if (pieces.size() == 1)
|
||||||
|
{
|
||||||
|
VPPiecePtr p = pieces.first();
|
||||||
|
|
||||||
|
auto *command = new VPUndoPieceMove(p, m_stickyTranslateX, m_stickyTranslateY,
|
||||||
|
m_allowChangeMerge);
|
||||||
|
layout->UndoStack()->push(command);
|
||||||
|
|
||||||
|
VPGraphicsPiece * gPiece = ScenePiece(p);
|
||||||
|
if (gPiece != nullptr)
|
||||||
|
{
|
||||||
|
gPiece->SetStickyPoints(QVector<QPointF>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_allowChangeMerge = false;
|
m_allowChangeMerge = false;
|
||||||
|
m_hasStickyPosition = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,8 +673,32 @@ void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy)
|
||||||
QList<VPPiecePtr> pieces = PreparePieces();
|
QList<VPPiecePtr> pieces = PreparePieces();
|
||||||
if (pieces.size() == 1)
|
if (pieces.size() == 1)
|
||||||
{
|
{
|
||||||
auto *command = new VPUndoPieceMove(pieces.first(), dx, dy, m_allowChangeMerge);
|
VPPiecePtr p = pieces.first();
|
||||||
|
auto *command = new VPUndoPieceMove(p, dx, dy, m_allowChangeMerge);
|
||||||
layout->UndoStack()->push(command);
|
layout->UndoStack()->push(command);
|
||||||
|
|
||||||
|
if (layout->LayoutSettings().GetStickyEdges())
|
||||||
|
{
|
||||||
|
QVector<QPointF> path;
|
||||||
|
if (not p.isNull() && p->StickyPosition(m_stickyTranslateX, m_stickyTranslateY))
|
||||||
|
{
|
||||||
|
path = p->GetMappedExternalContourPoints();
|
||||||
|
QTransform m;
|
||||||
|
m.translate(m_stickyTranslateX, m_stickyTranslateY);
|
||||||
|
path = m.map(path);
|
||||||
|
m_hasStickyPosition = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_hasStickyPosition = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VPGraphicsPiece *gPiece = ScenePiece(p);
|
||||||
|
if (gPiece != nullptr)
|
||||||
|
{
|
||||||
|
gPiece->SetStickyPoints(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (pieces.size() > 1)
|
else if (pieces.size() > 1)
|
||||||
{
|
{
|
||||||
|
@ -645,7 +710,7 @@ void VPMainGraphicsView::TranslatePiecesOn(qreal dx, qreal dy)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VPMainGraphicsView::on_PieceSheetChanged(const VPPiecePtr &piece)
|
auto VPMainGraphicsView::ScenePiece(const VPPiecePtr &piece) const -> VPGraphicsPiece *
|
||||||
{
|
{
|
||||||
VPGraphicsPiece *_graphicsPiece = nullptr;
|
VPGraphicsPiece *_graphicsPiece = nullptr;
|
||||||
for(auto *graphicPiece : m_graphicsPieces)
|
for(auto *graphicPiece : m_graphicsPieces)
|
||||||
|
@ -656,6 +721,14 @@ void VPMainGraphicsView::on_PieceSheetChanged(const VPPiecePtr &piece)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return _graphicsPiece;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VPMainGraphicsView::on_PieceSheetChanged(const VPPiecePtr &piece)
|
||||||
|
{
|
||||||
|
VPGraphicsPiece *graphicsPiece = ScenePiece(piece);
|
||||||
|
|
||||||
VPLayoutPtr layout = piece->Layout();
|
VPLayoutPtr layout = piece->Layout();
|
||||||
if (layout.isNull())
|
if (layout.isNull())
|
||||||
{
|
{
|
||||||
|
@ -665,22 +738,22 @@ void VPMainGraphicsView::on_PieceSheetChanged(const VPPiecePtr &piece)
|
||||||
if (piece->Sheet().isNull() || piece->Sheet() == layout->GetTrashSheet() ||
|
if (piece->Sheet().isNull() || piece->Sheet() == layout->GetTrashSheet() ||
|
||||||
piece->Sheet() != layout->GetFocusedSheet()) // remove
|
piece->Sheet() != layout->GetFocusedSheet()) // remove
|
||||||
{
|
{
|
||||||
if (_graphicsPiece != nullptr)
|
if (graphicsPiece != nullptr)
|
||||||
{
|
{
|
||||||
scene()->removeItem(_graphicsPiece);
|
scene()->removeItem(graphicsPiece);
|
||||||
m_graphicsPieces.removeAll(_graphicsPiece);
|
m_graphicsPieces.removeAll(graphicsPiece);
|
||||||
delete _graphicsPiece;
|
delete graphicsPiece;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // add
|
else // add
|
||||||
{
|
{
|
||||||
if(_graphicsPiece == nullptr)
|
if(graphicsPiece == nullptr)
|
||||||
{
|
{
|
||||||
_graphicsPiece = new VPGraphicsPiece(piece);
|
graphicsPiece = new VPGraphicsPiece(piece);
|
||||||
m_graphicsPieces.append(_graphicsPiece);
|
m_graphicsPieces.append(graphicsPiece);
|
||||||
ConnectPiece(_graphicsPiece);
|
ConnectPiece(graphicsPiece);
|
||||||
}
|
}
|
||||||
scene()->addItem(_graphicsPiece);
|
scene()->addItem(graphicsPiece);
|
||||||
}
|
}
|
||||||
|
|
||||||
VMainGraphicsView::NewSceneRect(scene(), this);
|
VMainGraphicsView::NewSceneRect(scene(), this);
|
||||||
|
|
|
@ -126,11 +126,16 @@ private:
|
||||||
|
|
||||||
qreal m_rotationSum{0};
|
qreal m_rotationSum{0};
|
||||||
|
|
||||||
|
bool m_hasStickyPosition{false};
|
||||||
|
qreal m_stickyTranslateX{0};
|
||||||
|
qreal m_stickyTranslateY{0};
|
||||||
|
|
||||||
void ConnectPiece(VPGraphicsPiece *piece);
|
void ConnectPiece(VPGraphicsPiece *piece);
|
||||||
|
|
||||||
void RotatePiecesByAngle(qreal angle);
|
void RotatePiecesByAngle(qreal angle);
|
||||||
void TranslatePiecesOn(qreal dx, qreal dy);
|
void TranslatePiecesOn(qreal dx, qreal dy);
|
||||||
|
|
||||||
|
auto ScenePiece(const VPPiecePtr &piece) const -> VPGraphicsPiece *;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VPMAINGRAPHICSVIEW_H
|
#endif // VPMAINGRAPHICSVIEW_H
|
||||||
|
|
|
@ -909,7 +909,6 @@ void VPMainWindow::InitPropertyTabLayout()
|
||||||
{
|
{
|
||||||
m_layout->LayoutSettings().SetPiecesGapConverted(d);
|
m_layout->LayoutSettings().SetPiecesGapConverted(d);
|
||||||
LayoutWasSaved(false);
|
LayoutWasSaved(false);
|
||||||
// TODO update the QGraphicView
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2539,6 +2538,19 @@ void VPMainWindow::on_ApplyPieceTransformation()
|
||||||
|
|
||||||
auto *command = new VPUndoPieceMove(piece, pieceDx, pieceDy);
|
auto *command = new VPUndoPieceMove(piece, pieceDx, pieceDy);
|
||||||
m_layout->UndoStack()->push(command);
|
m_layout->UndoStack()->push(command);
|
||||||
|
|
||||||
|
if (m_layout->LayoutSettings().GetStickyEdges())
|
||||||
|
{
|
||||||
|
qreal stickyTranslateX = 0;
|
||||||
|
qreal stickyTranslateY = 0;
|
||||||
|
if (piece->StickyPosition(stickyTranslateX, stickyTranslateY))
|
||||||
|
{
|
||||||
|
bool allowMerge = selectedPieces.size() == 1;
|
||||||
|
auto *stickyCommand = new VPUndoPieceMove(piece, stickyTranslateX, stickyTranslateY,
|
||||||
|
allowMerge);
|
||||||
|
m_layout->UndoStack()->push(stickyCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -297,7 +297,7 @@ void VPLayoutFileReader::ReadControl(const VPLayoutPtr &layout)
|
||||||
ReadAttributeBool(attribs, ML::AttrWarningSuperposition, trueStr));
|
ReadAttributeBool(attribs, ML::AttrWarningSuperposition, trueStr));
|
||||||
layout->LayoutSettings().SetWarningPiecesOutOfBound(ReadAttributeBool(attribs, ML::AttrWarningOutOfBound, trueStr));
|
layout->LayoutSettings().SetWarningPiecesOutOfBound(ReadAttributeBool(attribs, ML::AttrWarningOutOfBound, trueStr));
|
||||||
layout->LayoutSettings().SetStickyEdges(ReadAttributeBool(attribs, ML::AttrStickyEdges, trueStr));
|
layout->LayoutSettings().SetStickyEdges(ReadAttributeBool(attribs, ML::AttrStickyEdges, trueStr));
|
||||||
layout->LayoutSettings().SetPiecesGap(ReadAttributeDouble(attribs, ML::AttrPiecesGap, QChar('0')));
|
layout->LayoutSettings().SetPiecesGap(qMax(ReadAttributeDouble(attribs, ML::AttrPiecesGap, QChar('0')), 0.0));
|
||||||
layout->LayoutSettings().SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr));
|
layout->LayoutSettings().SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr));
|
||||||
|
|
||||||
readElementText();
|
readElementText();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user