Krita Source Code Documentation
Loading...
Searching...
No Matches
KoShapeDistributeCommand.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2006 Thomas Zander <zander@kde.org>
3 * SPDX-FileCopyrightText: 2006 Jan Hambrecht <jaham@gmx.net>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7
9
11#include "KoShape.h"
12#include <QMap>
13
14#include <klocalizedstring.h>
15
17{
18public:
19 Private() : command(0) {}
21 delete command;
22 }
23
24 qreal getAvailableSpace(KoShape *first, KoShape *last, qreal extent, const QRectF &boundingRect);
25
28};
29
30KoShapeDistributeCommand::KoShapeDistributeCommand(const QList<KoShape*> &shapes, Distribute distribute, const QRectF &boundingRect, KUndo2Command *parent)
31 : KUndo2Command(parent),
32 d(new Private())
33{
34 d->distribute = distribute;
35 QMap<qreal, KoShape*> sortedPos;
36 QRectF bRect;
37 qreal extent = 0.0;
38 // sort by position and calculate sum of objects width/height
39 Q_FOREACH (KoShape *shape, shapes) {
40 bRect = shape->absoluteOutlineRect();
41 switch (d->distribute) {
43 sortedPos[bRect.center().x()] = shape;
44 break;
47 sortedPos[bRect.left()] = shape;
48 extent += bRect.width();
49 break;
51 sortedPos[bRect.right()] = shape;
52 break;
54 sortedPos[bRect.center().y()] = shape;
55 break;
58 sortedPos[bRect.bottom()] = shape;
59 extent += bRect.height();
60 break;
62 sortedPos[bRect.top()] = shape;
63 break;
64 }
65 }
66 KoShape* first = sortedPos.begin().value();
67 KoShape* last = (--sortedPos.end()).value();
68
69 // determine the available space to distribute
70 qreal space = d->getAvailableSpace(first, last, extent, boundingRect);
71 qreal pos = 0.0, step = space / qreal(shapes.count() - 1);
72
73 QList<QPointF> previousPositions;
74 QList<QPointF> newPositions;
75 QPointF position;
76 QPointF delta;
77 QMapIterator<qreal, KoShape*> it(sortedPos);
78 while (it.hasNext()) {
79 it.next();
80 position = it.value()->absolutePosition();
81 previousPositions << position;
82
83 bRect = it.value()->absoluteOutlineRect();
84 switch (d->distribute) {
86 delta = QPointF(boundingRect.x() + first->absoluteOutlineRect().width() / 2 + pos - bRect.width() / 2, bRect.y()) - bRect.topLeft();
87 break;
89 delta = QPointF(boundingRect.left() + pos, bRect.y()) - bRect.topLeft();
90 pos += bRect.width();
91 break;
93 delta = QPointF(boundingRect.left() + pos, bRect.y()) - bRect.topLeft();
94 break;
96 delta = QPointF(boundingRect.left() + first->absoluteOutlineRect().width() + pos - bRect.width(), bRect.y()) - bRect.topLeft();
97 break;
99 delta = QPointF(bRect.x(), boundingRect.y() + first->absoluteOutlineRect().height() / 2 + pos - bRect.height() / 2) - bRect.topLeft();
100 break;
102 delta = QPointF(bRect.x(), boundingRect.top() + pos) - bRect.topLeft();
103 pos += bRect.height();
104 break;
106 delta = QPointF(bRect.x(), boundingRect.top() + first->absoluteOutlineRect().height() + pos - bRect.height()) - bRect.topLeft();
107 break;
109 delta = QPointF(bRect.x(), boundingRect.top() + pos) - bRect.topLeft();
110 break;
111 };
112 newPositions << position + delta;
113 pos += step;
114 }
115 d->command = new KoShapeMoveCommand(sortedPos.values(), previousPositions, newPositions);
116
117 setText(kundo2_i18n("Distribute shapes"));
118}
119
124
126{
128 d->command->redo();
129}
130
132{
134 d->command->undo();
135}
136
137qreal KoShapeDistributeCommand::Private::getAvailableSpace(KoShape *first, KoShape *last, qreal extent, const QRectF &boundingRect)
138{
139 switch (distribute) {
140 case HorizontalCenterDistribution:
141 return boundingRect.width() - last->absoluteOutlineRect().width() / 2 - first->absoluteOutlineRect().width() / 2;
142 break;
143 case HorizontalGapsDistribution:
144 return boundingRect.width() - extent;
145 break;
146 case HorizontalLeftDistribution:
147 return boundingRect.width() - last->absoluteOutlineRect().width();
148 break;
149 case HorizontalRightDistribution:
150 return boundingRect.width() - first->absoluteOutlineRect().width();
151 break;
152 case VerticalCenterDistribution:
153 return boundingRect.height() - last->absoluteOutlineRect().height() / 2 - first->absoluteOutlineRect().height() / 2;
154 break;
155 case VerticalGapsDistribution:
156 return boundingRect.height() - extent;
157 break;
158 case VerticalBottomDistribution:
159 return boundingRect.height() - first->absoluteOutlineRect().height();
160 break;
161 case VerticalTopDistribution:
162 return boundingRect.height() - last->absoluteOutlineRect().height();
163 break;
164 }
165 return 0.0;
166}
float value(const T *src, size_t ch)
virtual void undo()
void setText(const KUndo2MagicString &text)
virtual void redo()
The undo / redo command for distributing shapes.
void redo() override
redo the command
Distribute
The different options to distribute with this command.
@ HorizontalRightDistribution
Horizontal Right.
@ VerticalCenterDistribution
Vertical centered.
@ HorizontalGapsDistribution
Horizontal Gaps.
@ VerticalBottomDistribution
Vertical bottom.
@ HorizontalCenterDistribution
Horizontal centered.
@ HorizontalLeftDistribution
Horizontal Left.
qreal getAvailableSpace(KoShape *first, KoShape *last, qreal extent, const QRectF &boundingRect)
void undo() override
revert the actions done in redo
KoShapeDistributeCommand(const QList< KoShape * > &shapes, Distribute distribute, const QRectF &boundingRect, KUndo2Command *parent=0)
The undo / redo command for shape moving.
QRectF absoluteOutlineRect() const
Definition KoShape.cpp:368
KUndo2MagicString kundo2_i18n(const char *text)