File indexing completed on 2024-12-22 04:09:14

0001 /* This file is part of the KDE project
0002 
0003    SPDX-FileCopyrightText: 2006 Thorsten Zachmann <zachmann@kde.org>
0004    SPDX-FileCopyrightText: 2006 Thomas Zander <zander@kde.org>
0005 
0006    SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "KoShapeRubberSelectStrategy.h"
0010 #include "KoShapeRubberSelectStrategy_p.h"
0011 #include "KoViewConverter.h"
0012 
0013 #include <QPainter>
0014 
0015 #include "KoShapeManager.h"
0016 #include "KoSelection.h"
0017 #include "KoCanvasBase.h"
0018 
0019 KoShapeRubberSelectStrategy::KoShapeRubberSelectStrategy(KoToolBase *tool, const QPointF &clicked, bool useSnapToGrid)
0020     : KoInteractionStrategy(*(new KoShapeRubberSelectStrategyPrivate(tool)))
0021 {
0022     Q_D(KoShapeRubberSelectStrategy);
0023     d->snapGuide->enableSnapStrategies(KoSnapGuide::GridSnapping);
0024     d->snapGuide->enableSnapping(useSnapToGrid);
0025 
0026     d->selectRect = QRectF(d->snapGuide->snap(clicked, QFlags<Qt::KeyboardModifier>()), QSizeF(0, 0));
0027 }
0028 
0029 void KoShapeRubberSelectStrategy::paint(QPainter &painter, const KoViewConverter &converter)
0030 {
0031     Q_D(KoShapeRubberSelectStrategy);
0032     painter.setRenderHint(QPainter::Antialiasing, false);
0033 
0034     const QColor crossingColor(80,130,8);
0035     const QColor coveringColor(8,60,167);
0036 
0037     QColor selectColor(
0038         currentMode() == CrossingSelection ?
0039         crossingColor : coveringColor);
0040 
0041     selectColor.setAlphaF(0.8);
0042     QPen select(selectColor, decorationThickness());
0043     select.setCosmetic(true);
0044     painter.setPen(select);
0045 
0046     selectColor.setAlphaF(0.4);
0047     const QBrush fillBrush(selectColor);
0048     painter.setBrush(fillBrush);
0049 
0050     QRectF paintRect = converter.documentToView(d->selectedRect());
0051     paintRect = paintRect.normalized();
0052 
0053     painter.drawRect(paintRect);
0054 }
0055 
0056 void KoShapeRubberSelectStrategy::handleMouseMove(const QPointF &p, Qt::KeyboardModifiers modifiers)
0057 {
0058     Q_D(KoShapeRubberSelectStrategy);
0059     QPointF point = d->snapGuide->snap(p, modifiers);
0060     if (modifiers & Qt::ControlModifier) {
0061         const QRectF oldDirtyRect = d->selectedRect();
0062         d->selectRect.moveTopLeft(d->selectRect.topLeft() - (d->lastPos - point));
0063         d->lastPos = point;
0064         d->tool->canvas()->updateCanvas(oldDirtyRect | d->selectedRect());
0065         return;
0066     }
0067     d->lastPos = point;
0068     QPointF old = d->selectRect.bottomRight();
0069     d->selectRect.setBottomRight(point);
0070     /*
0071         +---------------|--+
0072         |               |  |    We need to figure out rects A and B based on the two points. BUT
0073         |          old  | A|    we need to do that even if the points are switched places
0074         |             \ |  |    (i.e. the rect got smaller) and even if the rect is mirrored
0075         +---------------+  |    in either the horizontal or vertical axis.
0076         |       B          |
0077         +------------------+
0078                             `- point
0079     */
0080     QPointF x1 = old;
0081     x1.setY(d->selectRect.topLeft().y());
0082     qreal h1 = point.y() - x1.y();
0083     qreal h2 = old.y() - x1.y();
0084     QRectF A(x1, QSizeF(point.x() - x1.x(), point.y() < d->selectRect.top() ? qMin(h1, h2) : qMax(h1, h2)));
0085     A = A.normalized();
0086     d->tool->canvas()->updateCanvas(A);
0087 
0088     QPointF x2 = old;
0089     x2.setX(d->selectRect.topLeft().x());
0090     qreal w1 = point.x() - x2.x();
0091     qreal w2 = old.x() - x2.x();
0092     QRectF B(x2, QSizeF(point.x() < d->selectRect.left() ? qMin(w1, w2) : qMax(w1, w2), point.y() - x2.y()));
0093     B = B.normalized();
0094     d->tool->canvas()->updateCanvas(B);
0095 }
0096 
0097 KoShapeRubberSelectStrategy::SelectionMode KoShapeRubberSelectStrategy::currentMode() const
0098 {
0099     Q_D(const KoShapeRubberSelectStrategy);
0100     return d->selectRect.left() < d->selectRect.right() ? CoveringSelection : CrossingSelection;
0101 }
0102 
0103 KUndo2Command *KoShapeRubberSelectStrategy::createCommand()
0104 {
0105     return 0;
0106 }
0107 
0108 QRectF KoShapeRubberSelectStrategy::selectedRectangle() const {
0109     Q_D(const KoShapeRubberSelectStrategy);
0110     return d->selectedRect();
0111 }