File indexing completed on 2023-09-24 04:49:59
0001 /* 0002 * SPDX-FileCopyrightText: (C) 2019 Marco Martin <mart@kde.org> 0003 * SPDX-FileCopyrightText: (C) 2020 Carl Schwan <carl@carlschwan.eu> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 0008 #include "resizehandle.h" 0009 #include "resizerectangle.h" 0010 0011 #include <QCursor> 0012 #include <cmath> 0013 0014 ResizeHandle::ResizeHandle(QQuickItem *parent) 0015 : QQuickItem(parent) 0016 { 0017 setAcceptedMouseButtons(Qt::LeftButton); 0018 0019 auto syncCursor = [this]() { 0020 switch (m_resizeCorner) { 0021 case Left: 0022 case Right: 0023 setCursor(QCursor(Qt::SizeHorCursor)); 0024 break; 0025 case Top: 0026 case Bottom: 0027 setCursor(QCursor(Qt::SizeVerCursor)); 0028 break; 0029 case TopLeft: 0030 case BottomRight: 0031 setCursor(QCursor(Qt::SizeFDiagCursor)); 0032 break; 0033 case TopRight: 0034 case BottomLeft: 0035 default: 0036 setCursor(Qt::SizeBDiagCursor); 0037 } 0038 }; 0039 0040 syncCursor(); 0041 connect(this, &ResizeHandle::resizeCornerChanged, this, syncCursor); 0042 } 0043 0044 QQuickItem *ResizeHandle::rectangle() const 0045 { 0046 return m_rectangle; 0047 } 0048 0049 void ResizeHandle::setResizeCorner(ResizeHandle::Corner corner) 0050 { 0051 if (m_resizeCorner == corner) { 0052 return; 0053 } 0054 m_resizeCorner = corner; 0055 Q_EMIT resizeCornerChanged(); 0056 } 0057 0058 void ResizeHandle::setRectangle(QQuickItem *rectangle) 0059 { 0060 if (m_rectangle == rectangle) { 0061 return; 0062 } 0063 m_rectangle = qobject_cast<ResizeRectangle *>(rectangle); 0064 Q_EMIT rectangleChanged(); 0065 } 0066 0067 bool ResizeHandle::resizeBlocked() const 0068 { 0069 return false; // m_resizeWidthBlocked || m_resizeHeightBlocked; 0070 } 0071 0072 bool ResizeHandle::resizeLeft() const 0073 { 0074 return m_resizeCorner == Left || m_resizeCorner == TopLeft || m_resizeCorner == BottomLeft; 0075 } 0076 0077 bool ResizeHandle::resizeTop() const 0078 { 0079 return m_resizeCorner == Top || m_resizeCorner == TopLeft || m_resizeCorner == TopRight; 0080 } 0081 0082 bool ResizeHandle::resizeRight() const 0083 { 0084 return m_resizeCorner == Right || m_resizeCorner == TopRight || m_resizeCorner == BottomRight; 0085 } 0086 0087 bool ResizeHandle::resizeBottom() const 0088 { 0089 return m_resizeCorner == Bottom || m_resizeCorner == BottomLeft || m_resizeCorner == BottomRight; 0090 } 0091 0092 void ResizeHandle::setResizeBlocked(bool width, bool height) 0093 { 0094 if (m_resizeWidthBlocked == width && m_resizeHeightBlocked == height) { 0095 return; 0096 } 0097 0098 m_resizeWidthBlocked = width; 0099 m_resizeHeightBlocked = height; 0100 0101 Q_EMIT resizeBlockedChanged(); 0102 } 0103 0104 void ResizeHandle::mousePressEvent(QMouseEvent *event) 0105 { 0106 m_mouseDownPosition = event->windowPos(); 0107 m_mouseDownGeometry = QRectF(m_rectangle->insideX(), m_rectangle->insideY(), m_rectangle->insideWidth(), m_rectangle->insideHeight()); 0108 setResizeBlocked(false, false); 0109 event->accept(); 0110 } 0111 0112 void ResizeHandle::mouseMoveEvent(QMouseEvent *event) 0113 { 0114 const QPointF difference = m_mouseDownPosition - event->windowPos(); 0115 0116 const QSizeF minimumSize = QSize(20, 20); 0117 0118 // Horizontal resize 0119 if (resizeLeft()) { 0120 const qreal width = qMax(minimumSize.width(), m_mouseDownGeometry.width() + difference.x()); 0121 const qreal x = m_mouseDownGeometry.x() + (m_mouseDownGeometry.width() - width); 0122 0123 m_rectangle->setInsideX(x); 0124 m_rectangle->setInsideWidth(width); 0125 setResizeBlocked(m_mouseDownGeometry.width() + difference.x() < minimumSize.width(), m_resizeHeightBlocked); 0126 } else if (resizeRight()) { 0127 const qreal width = qMax(minimumSize.width(), m_mouseDownGeometry.width() - difference.x()); 0128 0129 m_rectangle->setInsideWidth(width); 0130 setResizeBlocked(m_mouseDownGeometry.width() - difference.x() < minimumSize.width(), m_resizeHeightBlocked); 0131 } 0132 0133 // Vertical Resize 0134 if (resizeTop()) { 0135 const qreal height = qMax(minimumSize.height(), m_mouseDownGeometry.height() + difference.y()); 0136 const qreal y = m_mouseDownGeometry.y() + (m_mouseDownGeometry.height() - height); 0137 0138 m_rectangle->setInsideY(y); 0139 m_rectangle->setInsideHeight(height); 0140 setResizeBlocked(m_resizeWidthBlocked, m_mouseDownGeometry.height() + difference.y() < minimumSize.height()); 0141 } else if (resizeBottom()) { 0142 const qreal height = qMax(minimumSize.height(), m_mouseDownGeometry.height() - difference.y()); 0143 0144 m_rectangle->setInsideHeight(qMax(height, minimumSize.height())); 0145 setResizeBlocked(m_resizeWidthBlocked, m_mouseDownGeometry.height() - difference.y() < minimumSize.height()); 0146 } 0147 0148 event->accept(); 0149 } 0150 0151 void ResizeHandle::mouseReleaseEvent(QMouseEvent *event) 0152 { 0153 event->accept(); 0154 0155 setResizeBlocked(false, false); 0156 Q_EMIT resizeBlockedChanged(); 0157 }