File indexing completed on 2024-12-08 08:10:46

0001 /***************************************************************************
0002  *   Copyright (C) 2005 by David Saxton                                    *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program 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 
0011 #ifndef RESIZEOVERLAY_H
0012 #define RESIZEOVERLAY_H
0013 
0014 // This file contains class definitions for different types of resizing and rotating
0015 
0016 //#include <canvas.h> // 2018.10.16 - not needed
0017 #include "canvasitems.h"
0018 #include "item.h"
0019 #include <QList>
0020 #include <QMap>
0021 #include <QObject>
0022 #include <QPointer>
0023 
0024 class MechanicsItem;
0025 class ResizeHandle;
0026 class ResizeOverlay;
0027 class QEvent;
0028 
0029 typedef QMap<int, QPointer<ResizeHandle>> ResizeHandleMap;
0030 
0031 /**
0032 @author David Saxton
0033 */
0034 class ResizeHandle : /* public QObject, */ public KtlQCanvasRectangle
0035 {
0036     Q_OBJECT
0037 public:
0038     /**
0039      * Convenience enumeration for resize handle positioning. Note: this class
0040      * does not make use of the values in this enumeration - it is just
0041      * provided here for use by other classes.
0042      */
0043     enum ResizeHandlePosition { rhp_none, rhp_topLeft, rhp_topMiddle, rhp_topRight, rhp_middleRight, rhp_bottomRight, rhp_bottomMiddle, rhp_bottomLeft, rhp_middleLeft, rhp_center, rhp_start, rhp_end };
0044 
0045     enum DrawType {
0046         // Draws a simple rectangle
0047         dt_point_rect,
0048 
0049         // Crosshair
0050         dt_point_crosshair,
0051 
0052         // Straight arrows in various directions
0053         dt_resize_forwardsDiagonal,
0054         dt_resize_backwardsDiagonal,
0055         dt_resize_vertical,
0056         dt_resize_horizontal,
0057 
0058         // Arrows as part of an arc
0059         dt_rotate_topLeft,
0060         dt_rotate_topRight,
0061         dt_rotate_bottomRight,
0062         dt_rotate_bottomLeft
0063     };
0064 
0065     ResizeHandle(ResizeOverlay *resizeOverlay, int id, DrawType drawType, int xsnap, int ysnap);
0066     ~ResizeHandle() override;
0067 
0068     int id() const
0069     {
0070         return m_id;
0071     }
0072 
0073     void setDrawType(DrawType drawType);
0074     void moveRH(double x, double y);
0075     void setHover(bool hover);
0076 
0077     static const QPixmap &handlePixmap(DrawType drawType, bool hover);
0078 
0079     QPolygon areaPoints() const override;
0080 
0081 public slots:
0082     void slotMoveByX(double dx)
0083     {
0084         moveBy(dx, 0);
0085     }
0086     void slotMoveByY(double dy)
0087     {
0088         moveBy(0, dy);
0089     }
0090 
0091 signals:
0092     void rhMovedBy(int id, double dx, double dy);
0093     void rhMovedByX(double dx);
0094     void rhMovedByY(double dy);
0095 
0096 protected:
0097     void drawShape(QPainter &p) override;
0098 
0099     DrawType m_drawType;
0100     bool b_hover; // If true, then paint resize handle for mouse hovering over
0101     int m_id;
0102     int m_xsnap;
0103     int m_ysnap;
0104     ResizeOverlay *p_resizeOverlay;
0105 };
0106 typedef QList<ResizeHandle *> ResizeHandleList;
0107 
0108 /**
0109 @author David Saxton
0110 */
0111 class ResizeOverlay : public QObject
0112 {
0113     Q_OBJECT
0114 public:
0115     ResizeOverlay(Item *parent);
0116     ~ResizeOverlay() override;
0117 
0118     Item *parentItem() const
0119     {
0120         return p_item;
0121     }
0122 
0123     /**
0124      * Shows / hides the resize handles. They are hidden by default.
0125      */
0126     void showResizeHandles(bool show);
0127     /**
0128      * Sets the visibility. Visibility is true by default.
0129      */
0130     void setVisible(bool visible);
0131     /**
0132      * Reinherit this function to determine whether the X coordinate of the spot
0133      * that the resize handle has moved into is valid or not
0134      */
0135     virtual bool isValidXPos(ResizeHandle *rh)
0136     {
0137         Q_UNUSED(rh);
0138         return true;
0139     }
0140     /**
0141      * Reinherit this function to determine whether the Y coordinate of the spot
0142      * that the resize handle has moved into is valid or not
0143      */
0144     virtual bool isValidYPos(ResizeHandle *rh)
0145     {
0146         Q_UNUSED(rh);
0147         return true;
0148     }
0149 
0150 public slots:
0151     void slotMoveAllResizeHandles(double dx, double dy);
0152 
0153 protected slots:
0154     virtual void slotResizeHandleMoved(int id, double dx, double dy) = 0;
0155 
0156 protected:
0157     /**
0158      * Connects up the given resize handles so that they are always kept at the
0159      * same horizontal coordinate
0160      */
0161     void syncX(ResizeHandle *rh1, ResizeHandle *rh2);
0162     void syncX(ResizeHandle *rh1, ResizeHandle *rh2, ResizeHandle *rh3);
0163     /**
0164      * Connects up the given resize handles so that they are always kept at the
0165      * same vertical coordinate
0166      */
0167     void syncY(ResizeHandle *rh1, ResizeHandle *rh2);
0168     void syncY(ResizeHandle *rh1, ResizeHandle *rh2, ResizeHandle *rh3);
0169     /**
0170      * Returns a pointer to the ResizeHandle with the given id, or 0 if no such
0171      * handle exists
0172      */
0173     ResizeHandle *resizeHandle(int id);
0174     /**
0175      * Creates and attaches the resize handle with the given DrawType. If a
0176      * ResizeHandle with the given id exists, will return a pointer to that
0177      * instead
0178      */
0179     ResizeHandle *createResizeHandle(int id, ResizeHandle::DrawType drawType, int xsnap = 1, int ysnap = 1);
0180     /**
0181      * Removes the resize handle with the given id
0182      */
0183     void removeResizeHandle(int id);
0184 
0185     Item *p_item;
0186     ResizeHandleMap m_resizeHandleMap;
0187     bool b_showResizeHandles;
0188     bool b_visible;
0189 };
0190 
0191 /**
0192 @author David Saxton
0193 */
0194 class MechanicsItemOverlay : public ResizeOverlay
0195 {
0196     Q_OBJECT
0197 public:
0198     MechanicsItemOverlay(MechanicsItem *parent);
0199     ~MechanicsItemOverlay() override;
0200 
0201 public slots:
0202     void slotUpdateResizeHandles();
0203 
0204 protected slots:
0205     void slotResizeHandleMoved(int id, double dx, double dy) override;
0206 
0207 protected:
0208     ResizeHandle *m_tl;
0209     ResizeHandle *m_tm;
0210     ResizeHandle *m_tr;
0211     ResizeHandle *m_mr;
0212     ResizeHandle *m_br;
0213     ResizeHandle *m_bm;
0214     ResizeHandle *m_bl;
0215     ResizeHandle *m_ml;
0216     ResizeHandle *m_mm;
0217     MechanicsItem *p_mechanicsItem;
0218 };
0219 
0220 /**
0221 @author David Saxton
0222 */
0223 class RectangularOverlay : public ResizeOverlay
0224 {
0225     Q_OBJECT
0226 public:
0227     RectangularOverlay(Item *item, int xsnap = 1, int ysnap = 1);
0228     void removeTopMiddle();
0229     void removeBotMiddle();
0230     /**
0231      * Get the size rectangle from the position of the handles. If the size
0232      * is invalid (e.g. the parent Item does not consider it a valid size,
0233      * then *ok is set to false; otherwise to true.
0234      * @returns the sizerect, regardless of whether or not it is valid
0235      */
0236     QRect getSizeRect(bool *ok = nullptr, bool *widthOk = nullptr, bool *heightOk = nullptr) const;
0237 
0238     bool isValidXPos(ResizeHandle *rh) override;
0239     bool isValidYPos(ResizeHandle *rh) override;
0240 
0241 public slots:
0242     void slotUpdateResizeHandles();
0243 
0244 protected slots:
0245     void slotResizeHandleMoved(int id, double dx, double dy) override;
0246 
0247 protected:
0248     ResizeHandle *m_tl;
0249     ResizeHandle *m_tm;
0250     ResizeHandle *m_tr;
0251     ResizeHandle *m_mr;
0252     ResizeHandle *m_br;
0253     ResizeHandle *m_bm;
0254     ResizeHandle *m_bl;
0255     ResizeHandle *m_ml;
0256 };
0257 
0258 /**
0259 @author David Saxton
0260 */
0261 class LineOverlay : public ResizeOverlay
0262 {
0263     Q_OBJECT
0264 public:
0265     LineOverlay(Item *parent);
0266     QPoint startPoint() const;
0267     QPoint endPoint() const;
0268 
0269 public slots:
0270     void slotUpdateResizeHandles();
0271 
0272 protected slots:
0273     void slotResizeHandleMoved(int id, double dx, double dy) override;
0274 
0275 protected:
0276     ResizeHandle *m_pStart;
0277     ResizeHandle *m_pEnd;
0278 };
0279 
0280 #endif