KQuickImageEditor

resizerectangle.cpp
1 /*
2  * SPDX-FileCopyrightText: (C) 2020 Carl Schwan <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  */
6 
7 #include "resizerectangle.h"
8 
9 #include <QDebug>
10 #include <QSGFlatColorMaterial>
11 #include <QSGGeometry>
12 #include <QSGGeometryNode>
13 
14 ResizeRectangle::ResizeRectangle(QQuickItem *parent)
15  : QQuickItem(parent)
16 {
17  setAcceptedMouseButtons(Qt::LeftButton);
18  setFlag(ItemHasContents);
19 }
20 
21 void ResizeRectangle::componentComplete()
22 {
24  QQmlEngine *engine = qmlEngine(this);
25  m_handleComponent = new QQmlComponent(engine, QUrl(QStringLiteral("qrc:/BasicResizeHandle.qml")));
26 
27  auto handleItem = qobject_cast<QQuickItem *>(m_handleComponent->create());
28  qDebug() << handleItem;
29  m_handleBottomLeft = qobject_cast<ResizeHandle *>(handleItem);
30  m_handleBottomLeft->setParent(this);
31  m_handleBottomLeft->setParentItem(this);
32  m_handleBottomLeft->setResizeCorner(ResizeHandle::BottomLeft);
33  m_handleBottomLeft->setX(m_insideX - 5);
34  m_handleBottomLeft->setY(m_insideY + m_insideHeight - 5);
35  m_handleBottomLeft->setRectangle(this);
36 
37  handleItem = qobject_cast<QQuickItem *>(m_handleComponent->create());
38  m_handleBottomRight = qobject_cast<ResizeHandle *>(handleItem);
39  m_handleBottomRight->setParent(this);
40  m_handleBottomRight->setParentItem(this);
41  m_handleBottomRight->setResizeCorner(ResizeHandle::BottomRight);
42  m_handleBottomRight->setX(m_insideX + m_insideWidth - 5);
43  m_handleBottomRight->setY(m_insideY + m_insideHeight - 5);
44  m_handleBottomRight->setRectangle(this);
45 
46  handleItem = qobject_cast<QQuickItem *>(m_handleComponent->create());
47  m_handleTopLeft = qobject_cast<ResizeHandle *>(handleItem);
48  m_handleTopLeft->setParent(this);
49  m_handleTopLeft->setParentItem(this);
50  m_handleTopLeft->setResizeCorner(ResizeHandle::TopLeft);
51  m_handleTopLeft->setX(m_insideX - 5);
52  m_handleTopLeft->setY(m_insideY - 5);
53  m_handleTopLeft->setRectangle(this);
54 
55  handleItem = qobject_cast<QQuickItem *>(m_handleComponent->create());
56  m_handleTopRight = qobject_cast<ResizeHandle *>(handleItem);
57  m_handleTopRight->setParent(this);
58  m_handleTopRight->setParentItem(this);
59  m_handleTopRight->setResizeCorner(ResizeHandle::TopRight);
60  m_handleTopRight->setX(m_insideX + m_insideWidth - 5);
61  m_handleTopRight->setY(m_insideY - 5);
62  m_handleTopRight->setRectangle(this);
63 }
64 
65 void ResizeRectangle::updateHandles()
66 {
67  if (isComponentComplete()) {
68  m_handleTopRight->setX(m_insideX + m_insideWidth - 5);
69  m_handleTopRight->setY(m_insideY - 5);
70  m_handleTopLeft->setX(m_insideX - 5);
71  m_handleTopLeft->setY(m_insideY - 5);
72  m_handleBottomRight->setX(m_insideX + m_insideWidth - 5);
73  m_handleBottomRight->setY(m_insideY + m_insideHeight - 5);
74  m_handleBottomLeft->setX(m_insideX - 5);
75  m_handleBottomLeft->setY(m_insideY + m_insideHeight - 5);
76  }
77 }
78 
79 qreal ResizeRectangle::insideX() const
80 {
81  return m_insideX;
82 }
83 
84 void ResizeRectangle::setInsideX(qreal x)
85 {
86  x = qBound(0.0, x, this->width() - m_insideWidth);
87  if (m_insideX == x) {
88  return;
89  }
90  m_insideX = x;
91  updateHandles();
92  Q_EMIT insideXChanged();
93  update();
94 }
95 
96 qreal ResizeRectangle::insideY() const
97 {
98  return m_insideY;
99 }
100 
101 void ResizeRectangle::setInsideY(qreal y)
102 {
103  y = qBound(0.0, y, this->height() - m_insideHeight);
104  if (m_insideY == y) {
105  return;
106  }
107  m_insideY = y;
108  updateHandles();
109  Q_EMIT insideYChanged();
110  update();
111 }
112 
113 qreal ResizeRectangle::insideWidth() const
114 {
115  return m_insideWidth;
116 }
117 
118 void ResizeRectangle::setInsideWidth(qreal width)
119 {
120  width = qMin(width, this->width());
121  if (m_insideWidth == width) {
122  return;
123  }
124  m_insideWidth = width;
125  updateHandles();
126  Q_EMIT insideWidthChanged();
127  update();
128 }
129 
130 qreal ResizeRectangle::insideHeight() const
131 {
132  return m_insideHeight;
133 }
134 
135 void ResizeRectangle::setInsideHeight(qreal height)
136 {
137  height = qMin(height, this->height());
138  if (m_insideHeight == height) {
139  return;
140  }
141  m_insideHeight = height;
142  updateHandles();
143  Q_EMIT insideHeightChanged();
144  update();
145 }
146 
147 QSGNode *ResizeRectangle::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
148 {
149  QSGGeometryNode *node = nullptr;
150  QSGGeometry *geometry = nullptr;
151 
152  const int vertexCount = 12;
153  const int indexCount = 8 * 3;
154  if (!oldNode) {
155  node = new QSGGeometryNode;
156  geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), vertexCount, indexCount);
158  geometry->setDrawingMode(GL_TRIANGLES);
159  node->setGeometry(geometry);
161 
163  material->setColor(QColor(0, 0, 0, 70));
164  node->setMaterial(material);
166  } else {
167  node = static_cast<QSGGeometryNode *>(oldNode);
168  geometry = node->geometry();
169  geometry->allocate(vertexCount, indexCount);
170  }
171 
172  QSGGeometry::Point2D *points = geometry->vertexDataAsPoint2D();
173  points[0].set(0, 0);
174  points[1].set(0, height());
175  points[2].set(m_insideX, 0);
176  points[3].set(m_insideX, height());
177 
178  points[4].set(m_insideX + m_insideWidth, 0);
179  points[5].set(m_insideX + m_insideWidth, height());
180  points[6].set(width(), 0);
181  points[7].set(width(), height());
182 
183  points[8].set(m_insideX, m_insideY);
184  points[9].set(m_insideX + m_insideWidth, m_insideY);
185  points[10].set(m_insideX + m_insideWidth, m_insideY + m_insideHeight);
186  points[11].set(m_insideX, m_insideY + m_insideHeight);
187 
188  quint16 *indices = geometry->indexDataAsUShort();
189  // left
190  indices[0 + 0] = 0;
191  indices[0 + 1] = 1;
192  indices[0 + 2] = 2;
193 
194  indices[3 + 0] = 3;
195  indices[3 + 1] = 1;
196  indices[3 + 2] = 2;
197 
198  // right
199  indices[6 + 0] = 4;
200  indices[6 + 1] = 5;
201  indices[6 + 2] = 6;
202 
203  indices[9 + 0] = 7;
204  indices[9 + 1] = 5;
205  indices[9 + 2] = 6;
206 
207  // top
208  indices[12 + 0] = 2;
209  indices[12 + 1] = 8;
210  indices[12 + 2] = 4;
211 
212  indices[15 + 0] = 9;
213  indices[15 + 1] = 8;
214  indices[15 + 2] = 4;
215 
216  // bottom
217  indices[18 + 0] = 3;
218  indices[18 + 1] = 11;
219  indices[18 + 2] = 10;
220 
221  indices[21 + 0] = 3;
222  indices[21 + 1] = 5;
223  indices[21 + 2] = 10;
224 
225  geometry->markIndexDataDirty();
226  geometry->markVertexDataDirty();
228  return node;
229 }
230 
231 void ResizeRectangle::mouseReleaseEvent(QMouseEvent *event)
232 {
233  m_mouseClickedOnRectangle = false;
234  event->accept();
235 }
236 
237 void ResizeRectangle::mousePressEvent(QMouseEvent *event)
238 {
239  m_mouseDownPosition = event->pos();
240  m_mouseDownGeometry = QPointF(m_insideX, m_insideY);
241  if (m_mouseDownPosition.x() >= m_insideX && m_mouseDownPosition.x() <= m_insideX + m_insideWidth && m_mouseDownPosition.y() >= m_insideY
242  && m_mouseDownPosition.y() <= m_insideY + m_insideHeight) {
243  m_mouseClickedOnRectangle = true;
244  }
245  event->accept();
246 }
247 
248 void ResizeRectangle::mouseMoveEvent(QMouseEvent *event)
249 {
250  if (m_mouseClickedOnRectangle) {
251  const QPointF difference = m_mouseDownPosition - event->pos();
252  const qreal x = m_mouseDownGeometry.x() - difference.x();
253  const qreal y = m_mouseDownGeometry.y() - difference.y();
254  setInsideX(x);
255  setInsideY(y);
256  }
257 }
258 
259 void ResizeRectangle::mouseDoubleClickEvent(QMouseEvent *event)
260 {
261  Q_EMIT acceptSize();
262  event->accept();
263 }
264 
265 #include "moc_resizerectangle.cpp"
void setDrawingMode(unsigned int mode)
void setMaterial(QSGMaterial *material)
void set(float x, float y)
void markDirty(QSGNode::DirtyState bits)
const QSGGeometry * geometry() const const
const QSGGeometry::AttributeSet & defaultAttributes_Point2D()
void setGeometry(QSGGeometry *geometry)
QSGGeometry::Point2D * vertexDataAsPoint2D()
LeftButton
void setIndexDataPattern(QSGGeometry::DataPattern p)
void markIndexDataDirty()
qreal x() const const
qreal y() const const
void setFlag(QSGNode::Flag f, bool enabled)
virtual void componentComplete() override
quint16 * indexDataAsUShort()
void setParent(QObject *parent)
void setColor(const QColor &color)
void update(Part *part, const QByteArray &data, qint64 dataSize)
void allocate(int vertexCount, int indexCount)
void markVertexDataDirty()
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 18 2021 23:08:19 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.