File indexing completed on 2024-04-28 05:38:11

0001 /***************************************************************************
0002  *   Copyright (C) 2015 by Renaud Guezennec                                *
0003  *   https://rolisteam.org/contact                   *
0004  *                                                                         *
0005  *   rolisteam is free software; you can redistribute it and/or modify     *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 
0021 #include "childpointitem.h"
0022 #include "visualitem.h"
0023 
0024 #include "controller/item_controllers/visualitemcontroller.h"
0025 #include "controller/view_controller/vectorialmapcontroller.h"
0026 #include <QDebug>
0027 #include <QGraphicsScene>
0028 #include <QGraphicsSceneMouseEvent>
0029 #include <QPainter>
0030 
0031 #include <cmath>
0032 #include <math.h>
0033 #define PI 3.14159265
0034 
0035 #define SQUARE_SIZE 6
0036 
0037 bool allowResizing(ChildPointItem::Change change)
0038 {
0039     return (change == ChildPointItem::None || change == ChildPointItem::Resizing);
0040 }
0041 
0042 bool allowRotation(ChildPointItem::Change change)
0043 {
0044     return (change == ChildPointItem::None || change == ChildPointItem::Rotation);
0045 }
0046 
0047 ChildPointItem::ChildPointItem(vmap::VisualItemController* ctrl, int point, VisualItem* parent, Control control)
0048     : QGraphicsObject(parent), m_ctrl(ctrl), m_pointId(point), m_parent(parent), m_control(control)
0049 {
0050     m_editable= true;
0051     // connect(m_ctrl, &vmap::VisualItemController::rotationChanged, this, [this]() { setRotation(-m_ctrl->rotation());
0052     // });
0053     // setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
0054     // setAcceptHoverEvents(true);
0055     // setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemSendsGeometryChanges|QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsFocusable);
0056     // setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsFocusable);
0057 }
0058 
0059 ChildPointItem::~ChildPointItem() {}
0060 
0061 QVariant ChildPointItem::itemChange(GraphicsItemChange change, const QVariant& value)
0062 {
0063     /*   if(!m_editable)
0064            return QGraphicsItem::itemChange(change, value);
0065 
0066        if(change == ItemPositionChange && isSelected() && m_currentMotion != NONE
0067           && m_currentMotion != MOUSE)
0068        {
0069            QPointF newPos= value.toPointF();
0070            switch(m_currentMotion)
0071            {
0072            case X_AXIS:
0073                newPos.setY(pos().y());
0074                break;
0075            case Y_AXIS:
0076                newPos.setX(pos().x());
0077 
0078                break;
0079            case MOVE:
0080                m_parent->setPos(mapToScene(newPos));
0081                break;
0082            default:
0083                break;
0084            }
0085            if(newPos != value.toPointF())
0086            {
0087                return newPos;
0088            }
0089        }*/
0090 
0091     return QGraphicsItem::itemChange(change, value);
0092 }
0093 QRectF ChildPointItem::boundingRect() const
0094 {
0095     return QRectF(m_startPoint.x(), m_startPoint.y(), 2 * SQUARE_SIZE, 2 * SQUARE_SIZE);
0096 }
0097 void ChildPointItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
0098 {
0099     Q_UNUSED(option)
0100     Q_UNUSED(widget)
0101     painter->setPen(Qt::black);
0102     painter->fillRect(m_startPoint.x(), m_startPoint.y(), 2 * SQUARE_SIZE, 2 * SQUARE_SIZE, Qt::gray);
0103     painter->drawRect(m_startPoint.x(), m_startPoint.y(), 2 * SQUARE_SIZE, 2 * SQUARE_SIZE);
0104 }
0105 void ChildPointItem::setMotion(ChildPointItem::MOTIONS m)
0106 {
0107     m_motion= m;
0108     // if((MOUSE == m_currentMotion) || (NONE == m_currentMotion))
0109     {
0110         setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
0111     }
0112     /* else
0113      {
0114          setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges
0115                   | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
0116      }*/
0117 }
0118 void ChildPointItem::setPlacement(ChildPointItem::PLACEMENT p)
0119 {
0120     // MiddelLeft,MiddleRight,Center,ButtomLeft,ButtomRight,ButtomCenter};
0121     m_placement= p;
0122     switch(m_placement)
0123     {
0124     case TopLeft:
0125         m_startPoint.setX(0);
0126         m_startPoint.setY(0);
0127         break;
0128     case TopRight:
0129         m_startPoint.setX(-(2 * SQUARE_SIZE));
0130         m_startPoint.setY(0);
0131         break;
0132     case TopCenter:
0133         m_startPoint.setX(-(SQUARE_SIZE));
0134         m_startPoint.setY(0);
0135         break;
0136     case MiddelLeft:
0137         m_startPoint.setX(0);
0138         m_startPoint.setY(-(SQUARE_SIZE));
0139         break;
0140     case MiddleRight:
0141         m_startPoint.setX(-(2 * SQUARE_SIZE));
0142         m_startPoint.setY(-(SQUARE_SIZE));
0143         break;
0144     case Center:
0145         m_startPoint.setX(-(SQUARE_SIZE));
0146         m_startPoint.setY(-(SQUARE_SIZE));
0147         break;
0148     case ButtomLeft:
0149         m_startPoint.setX(0);
0150         m_startPoint.setY(-(2 * SQUARE_SIZE));
0151         break;
0152     case ButtomRight:
0153         m_startPoint.setX(-(2 * SQUARE_SIZE));
0154         m_startPoint.setY(-(2 * SQUARE_SIZE));
0155         break;
0156     case ButtomCenter:
0157         m_startPoint.setX(-(SQUARE_SIZE));
0158         m_startPoint.setY(-(2 * SQUARE_SIZE));
0159         break;
0160     }
0161 }
0162 
0163 ChildPointItem::PLACEMENT ChildPointItem::placement() const
0164 {
0165     return m_placement;
0166 }
0167 /*void ChildPointItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
0168 {
0169     event->accept();
0170     QPointF v = pos() + event->pos();//distance vector
0171     qreal rot = m_parent->rotation();
0172 
0173 
0174     if(m_editable)
0175     {
0176         if(m_currentMotion == MOUSE)
0177         {
0178             if(!(event->modifiers() & Qt::ControlModifier))
0179             {
0180                 VisualItem::TransformType transformType = VisualItem::NoTransform;
0181 
0182                 qreal W = 0;//qMax(fabs(v.x()), 5.0);
0183                 qreal H = 0;//qMax(fabs(v.y()), 4.0);
0184                 qreal X = 0;
0185                 qreal Y = 0;
0186                 m_parent->setRotation(0);
0187                 v = event->pos();//distance vector
0188                 switch(m_placement)
0189                 {
0190                     case TopLeft://topleft
0191                        // m_parent->setTransformOriginPoint(m_parent->boundingRect().bottomRight());
0192                         X = v.x();
0193                         Y = v.y();
0194                         W = m_parent->boundingRect().width() - X;
0195                         H = m_parent->boundingRect().height() - Y;
0196                         break;
0197                     case TopRight://topright
0198                        // m_parent->setTransformOriginPoint(m_parent->boundingRect().bottomLeft());
0199                         Y = v.y();
0200                         W = m_parent->boundingRect().width() + v.x();
0201                         H = m_parent->boundingRect().height() - Y;
0202                         break;
0203                     case ButtomRight:// bottom right
0204                        // m_parent->setTransformOriginPoint(m_parent->boundingRect().topLeft());
0205                         W = m_parent->boundingRect().width() + v.x();
0206                         H = m_parent->boundingRect().height() + v.y();
0207                         break;
0208                     case ButtomLeft://bottom left
0209                         //m_parent->setTransformOriginPoint(m_parent->boundingRect().topRight());
0210                         X = v.x();
0211                         H = m_parent->boundingRect().height() + v.y();
0212                         W = m_parent->boundingRect().width() - X;
0213                         break;
0214                 }
0215                 if((event->modifiers() & Qt::ShiftModifier))
0216                 {
0217                     transformType = VisualItem::KeepRatio;
0218                 }
0219                 else if(event->modifiers() & Qt::AltModifier)
0220                 {
0221                     transformType = VisualItem::Sticky;
0222                     int size = m_parent->getOption(VisualItem::GridSize).toInt();
0223                     W = std::round(W/size)*size;
0224                     H = std::round(H/size)*size;
0225                 }
0226 
0227                 {
0228                     if(rot == 0)
0229                     {
0230                         m_parent->moveBy(X,Y);
0231                     }
0232                     m_parent->resizeContents(QRectF(0, 0, W, H),transformType);
0233                     //m_parent->setTransformOriginPoint(m_parent->boundingRect().center());
0234                     m_parent->setRotation(rot);
0235                 }
0236             }
0237         }
0238         if(((m_currentMotion == MOUSE)||(m_allowRotation))&&(event->modifiers() & Qt::ControlModifier))
0239         {
0240                 if (v.isNull())
0241                     return;
0242 
0243                 QPointF refPos = pos();
0244 
0245                 // set item rotation (set rotation relative to current)
0246                 qreal refAngle = atan2(refPos.y(), refPos.x());
0247                 qreal newAngle = atan2(v.y(), v.x());
0248                 double dZr = 57.29577951308232 * (newAngle - refAngle); // 180 * a / M_PI
0249                 double zr = m_parent->rotation() + dZr;
0250                 m_parent->setTransformOriginPoint(m_parent->boundingRect().center());
0251                 m_parent->setRotation(zr);
0252         }
0253         else
0254         {
0255                QGraphicsItem::mouseMoveEvent(event);
0256         }
0257     }
0258     else
0259     {
0260             QGraphicsItem::mouseMoveEvent(event);
0261     }
0262 }*/
0263 
0264 void ChildPointItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
0265 {
0266     event->accept();
0267     QPointF v= pos() + event->pos();
0268     if(!m_editable)
0269     {
0270         QGraphicsItem::mouseMoveEvent(event);
0271         return;
0272     }
0273     bool hasCtrlModifier= (event->modifiers() & Qt::ControlModifier);
0274     bool hasShiftModifier= (event->modifiers() & Qt::ShiftModifier);
0275 
0276     if(!hasCtrlModifier && (m_motion & ChildPointItem::Y_AXIS || m_motion & ChildPointItem::X_AXIS)
0277        && allowResizing(m_currentChange))
0278     {
0279         m_currentChange= Resizing;
0280         auto move= event->pos() - event->lastPos();
0281         m_motion& ChildPointItem::Y_AXIS ? move.setX(0) : move.setY(0);
0282         m_ctrl->setCorner(move, m_pointId);
0283     }
0284 
0285     if(!hasCtrlModifier && (m_motion & MOVE) && allowResizing(m_currentChange))
0286     {
0287         m_currentChange= Resizing;
0288         Core::TransformType transformType= Core::TransformType::NoTransform;
0289 
0290         auto W= qMax(2 * std::fabs(v.x()), 5.0);
0291         auto H= qMax(2 * std::fabs(v.y()), 4.0);
0292         if(event->modifiers() & Qt::AltModifier)
0293         {
0294             transformType= Core::TransformType::Sticky;
0295             int size= m_ctrl->gridSize();
0296             W= std::round(W / size) * size;
0297             H= std::round(H / size) * size;
0298         }
0299         else if(hasShiftModifier)
0300         {
0301             transformType= Core::TransformType::KeepRatio;
0302         }
0303 
0304         auto move= event->pos() - event->lastPos();
0305         m_ctrl->setCorner(move, m_pointId, transformType); // mapToScene(pos()) +
0306     }
0307 
0308     if((m_motion & ROTATION) && hasCtrlModifier && allowRotation(m_currentChange))
0309     {
0310         if(v.isNull())
0311             return;
0312         m_currentChange= Rotation;
0313 
0314         QPointF refPos= pos();
0315 
0316         // set item rotation (set rotation relative to current)
0317         qreal refAngle= atan2(refPos.y(), refPos.x());
0318         qreal newAngle= atan2(v.y(), v.x());
0319         double dZr= 57.29577951308232 * (newAngle - refAngle); // 180 * a / M_PI
0320         double zr= m_ctrl->rotation() + dZr;
0321         m_ctrl->setRotation(zr);
0322     }
0323     else
0324     {
0325         QGraphicsItem::mouseMoveEvent(event);
0326     }
0327 }
0328 void ChildPointItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
0329 {
0330     m_parent->endOfGeometryChange(m_currentChange);
0331     m_currentChange= None;
0332 
0333     QGraphicsItem::mouseReleaseEvent(event);
0334 }
0335 
0336 void ChildPointItem::setEditableItem(bool b)
0337 {
0338     m_editable= b;
0339     // if((m_editable) && (((MOUSE == m_motion) || (NONE == m_motion))))
0340     {
0341         setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
0342     }
0343 }
0344 void ChildPointItem::setPointID(int a)
0345 {
0346     m_pointId= a;
0347 }
0348 int ChildPointItem::getPointID() const
0349 {
0350     return m_pointId;
0351 }
0352 
0353 ChildPointItem::Control ChildPointItem::control() const
0354 {
0355     return m_control;
0356 }