File indexing completed on 2024-05-12 04:06:22

0001 /*
0002     SPDX-FileCopyrightText: 2010 Stefan Majewsky <majewsky@gmx.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "constraintinteractor.h"
0008 #include "scene.h"
0009 
0010 #include <KLocalizedString>
0011 
0012 Palapeli::ConstraintInteractor::ConstraintInteractor(QGraphicsView* view)
0013     : Palapeli::Interactor(10, Palapeli::MouseInteractor, view) //priority: less than interaction with pieces, but more than interaction with viewport
0014 {
0015     setMetadata(TableInteraction, i18n("Change size of puzzle table area by dragging its edges"), QIcon());
0016 }
0017 
0018 QList<Palapeli::ConstraintInteractor::Side> Palapeli::ConstraintInteractor::touchingSides(const QPointF& scenePos) const
0019 {
0020     QList<Side> result;
0021     // The scene must be Palapeli::Scene type, to get handleWidth().
0022     Palapeli::Scene* scene = qobject_cast<Palapeli::Scene*>(this->scene());
0023     if (!scene)
0024         return result;      // No scene, so no sides touching.
0025     const QRectF sceneRect = scene->sceneRect();
0026     const qreal w = scene->handleWidth();
0027     const QSizeF handleSize = QSizeF(w, w);
0028     if ((scenePos.x() > sceneRect.left()) && (scenePos.x() < sceneRect.left() + handleSize.width()))
0029         result << LeftSide;
0030     else if ((scenePos.x() < sceneRect.right()) && (scenePos.x() > sceneRect.right() - handleSize.width()))
0031         result << RightSide;
0032     if ((scenePos.y() > sceneRect.top()) && (scenePos.y() < sceneRect.top() + handleSize.height()))
0033         result << TopSide;
0034     else if ((scenePos.y() < sceneRect.bottom()) && (scenePos.y() > sceneRect.bottom() - handleSize.height()))
0035         result << BottomSide;
0036     return result;
0037 }
0038 
0039 bool Palapeli::ConstraintInteractor::startInteraction(const Palapeli::MouseEvent& event)
0040 {
0041     if (!scene())
0042         return false;
0043     //determine touching sides
0044     m_draggingSides = touchingSides(event.scenePos);
0045     if (m_draggingSides.isEmpty())
0046         return false;
0047     //record the position where we grabbed the handles (more precisely: its distance to the sides of the scene rect)
0048     m_baseSceneRectOffset = QPointF();
0049     const QRectF sceneRect = scene()->sceneRect();
0050     if (m_draggingSides.contains(LeftSide))
0051         m_baseSceneRectOffset.rx() = event.scenePos.x() - sceneRect.left();
0052     else if (m_draggingSides.contains(RightSide))
0053         m_baseSceneRectOffset.rx() = event.scenePos.x() - sceneRect.right();
0054     if (m_draggingSides.contains(TopSide))
0055         m_baseSceneRectOffset.ry() = event.scenePos.y() - sceneRect.top();
0056     else if (m_draggingSides.contains(BottomSide))
0057         m_baseSceneRectOffset.ry() = event.scenePos.y() - sceneRect.bottom();
0058     return true;
0059 }
0060 
0061 void Palapeli::ConstraintInteractor::continueInteraction(const Palapeli::MouseEvent& event)
0062 {
0063     // In this method, we need the scene() to be Palapeli::Scene type.
0064     Palapeli::Scene* scene = qobject_cast<Palapeli::Scene*>(this->scene());
0065     if (!scene)
0066         return;
0067     QRectF sceneRect = scene->sceneRect();
0068     //change scene rect
0069     const QPointF newBounds = event.scenePos - m_baseSceneRectOffset;
0070     if (m_draggingSides.contains(LeftSide))
0071         sceneRect.setLeft(newBounds.x());
0072     else if (m_draggingSides.contains(RightSide))
0073         sceneRect.setRight(newBounds.x());
0074     if (m_draggingSides.contains(TopSide))
0075         sceneRect.setTop(newBounds.y());
0076     else if (m_draggingSides.contains(BottomSide))
0077         sceneRect.setBottom(newBounds.y());
0078     scene->setSceneRect(sceneRect | scene->extPiecesBoundingRect());
0079 }
0080 
0081 void Palapeli::ConstraintInteractor::stopInteraction(const Palapeli::MouseEvent& event)
0082 {
0083     Q_UNUSED(event)
0084     m_draggingSides.clear();
0085 }