1 /***************************************************************************
2  *   Copyright (C) 2005 by David Saxton                                    *
3  *   david@bluehaze.org                                                    *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  ***************************************************************************/
10 
11 #ifndef RESIZEOVERLAY_H
12 #define RESIZEOVERLAY_H
13 
14 // This file contains class definitions for different types of resizing and rotating
15 
16 //#include <canvas.h> // 2018.10.16 - not needed
17 #include "canvasitems.h"
18 #include <QPointer>
19 #include <QMap>
20 #include <QObject>
21 #include <QList>
22 
23 class MechanicsItem;
24 class ResizeHandle;
25 class ResizeOverlay;
26 class QEvent;
27 
28 typedef QMap< int, QPointer<ResizeHandle> > ResizeHandleMap;
29 
30 /**
31 @author David Saxton
32 */
33 class ResizeHandle : /* public QObject, */ public KtlQCanvasRectangle
34 {
35 	Q_OBJECT
36 public:
37 	/**
38 	 * Convenience enumeration for resize handle positioning. Note: this class
39 	 * does not make use of the values in this enumeration - it is just
40 	 * provided here for use by other classes.
41 	 */
42 	enum ResizeHandlePosition
43 	{
44 		rhp_none,
45 		rhp_topLeft,
46 		rhp_topMiddle,
47 		rhp_topRight,
48 		rhp_middleRight,
49 		rhp_bottomRight,
50 		rhp_bottomMiddle,
51 		rhp_bottomLeft,
52 		rhp_middleLeft,
53 		rhp_center,
54 		rhp_start,
55 		rhp_end
56 	};
57 
58 	enum DrawType
59 	{
60 		// Draws a simple rectangle
61 		dt_point_rect,
62 
63 		// Crosshair
64 		dt_point_crosshair,
65 
66 		// Straight arrows in various directions
67 		dt_resize_forwardsDiagonal,
68 		dt_resize_backwardsDiagonal,
69 		dt_resize_vertical,
70 		dt_resize_horizontal,
71 
72 		// Arrows as part of an arc
73 		dt_rotate_topLeft,
74 		dt_rotate_topRight,
75 		dt_rotate_bottomRight,
76 		dt_rotate_bottomLeft
77 	};
78 
79 	ResizeHandle( ResizeOverlay *resizeOverlay, int id, DrawType drawType, int xsnap, int ysnap );
80 	~ResizeHandle() override;
81 
id()82 	int id() const { return m_id; }
83 
84 	void setDrawType( DrawType drawType );
85 	void moveRH( double x, double y );
86 	void setHover( bool hover );
87 
88 	static const QPixmap& handlePixmap( DrawType drawType, bool hover );
89 
90 	QPolygon areaPoints () const override;
91 
92 public slots:
slotMoveByX(double dx)93 	void slotMoveByX( double dx ) { moveBy( dx, 0 ); }
slotMoveByY(double dy)94 	void slotMoveByY( double dy ) { moveBy( 0, dy ); }
95 
96 signals:
97 	void rhMovedBy( int id, double dx, double dy );
98 	void rhMovedByX( double dx );
99 	void rhMovedByY( double dy );
100 
101 protected:
102 	void drawShape( QPainter &p ) override;
103 
104 	DrawType m_drawType;
105 	bool b_hover; // If true, then paint resize handle for mouse hovering over
106 	int m_id;
107 	int m_xsnap;
108 	int m_ysnap;
109 	ResizeOverlay *p_resizeOverlay;
110 
111 };
112 typedef QList<ResizeHandle*> ResizeHandleList;
113 
114 /**
115 @author David Saxton
116 */
117 class ResizeOverlay : public QObject
118 {
119 	Q_OBJECT
120 public:
121 	ResizeOverlay( Item *parent );
122 	~ResizeOverlay() override;
123 
124 
parentItem()125 	Item *parentItem() const { return p_item; }
126 
127 	/**
128 	 * Shows / hides the resize handles. They are hidden by default.
129 	 */
130 	void showResizeHandles( bool show );
131 	/**
132 	 * Sets the visibility. Visibility is true by default.
133 	 */
134 	void setVisible( bool visible );
135 	/**
136 	 * Reinherit this function to determine whether the X coordinate of the spot
137 	 * that the resize handle has moved into is valid or not
138 	 */
isValidXPos(ResizeHandle * rh)139 	virtual bool isValidXPos( ResizeHandle *rh ) { Q_UNUSED(rh); return true; }
140 	/**
141 	 * Reinherit this function to determine whether the Y coordinate of the spot
142 	 * that the resize handle has moved into is valid or not
143 	 */
isValidYPos(ResizeHandle * rh)144 	virtual bool isValidYPos( ResizeHandle *rh ) { Q_UNUSED(rh); return true; }
145 
146 public slots:
147 	void slotMoveAllResizeHandles( double dx, double dy );
148 
149 protected slots:
150 	virtual void slotResizeHandleMoved( int id, double dx, double dy ) = 0;
151 
152 protected:
153 	/**
154 	 * Connects up the given resize handles so that they are always kept at the
155 	 * same horizontal coordinate
156 	 */
157 	void syncX( ResizeHandle *rh1, ResizeHandle *rh2 );
158 	void syncX( ResizeHandle *rh1, ResizeHandle *rh2, ResizeHandle *rh3 );
159 	/**
160 	 * Connects up the given resize handles so that they are always kept at the
161 	 * same vertical coordinate
162 	 */
163 	void syncY( ResizeHandle *rh1, ResizeHandle *rh2 );
164 	void syncY( ResizeHandle *rh1, ResizeHandle *rh2, ResizeHandle *rh3 );
165 	/**
166 	 * Returns a pointer to the ResizeHandle with the given id, or 0 if no such
167 	 * handle exists
168 	 */
169 	ResizeHandle *resizeHandle( int id );
170 	/**
171 	 * Creates and attaches the resize handle with the given DrawType. If a
172 	 * ResizeHandle with the given id exists, will return a pointer to that
173 	 * instead
174 	 */
175 	ResizeHandle *createResizeHandle( int id, ResizeHandle::DrawType drawType, int xsnap = 1, int ysnap = 1 );
176 	/**
177 	 * Removes the resize handle with the given id
178 	 */
179 	void removeResizeHandle( int id );
180 
181 	Item *p_item;
182 	ResizeHandleMap m_resizeHandleMap;
183 	bool b_showResizeHandles;
184 	bool b_visible;
185 };
186 
187 
188 /**
189 @author David Saxton
190 */
191 class MechanicsItemOverlay : public ResizeOverlay
192 {
193 Q_OBJECT
194 public:
195 	MechanicsItemOverlay( MechanicsItem *parent );
196 	~MechanicsItemOverlay() override;
197 
198 
199 public slots:
200 	void slotUpdateResizeHandles();
201 
202 protected slots:
203 	void slotResizeHandleMoved( int id, double dx, double dy ) override;
204 
205 protected:
206 	ResizeHandle *m_tl;
207 	ResizeHandle *m_tm;
208 	ResizeHandle *m_tr;
209 	ResizeHandle *m_mr;
210 	ResizeHandle *m_br;
211 	ResizeHandle *m_bm;
212 	ResizeHandle *m_bl;
213 	ResizeHandle *m_ml;
214 	ResizeHandle *m_mm;
215 	MechanicsItem *p_mechanicsItem;
216 };
217 
218 
219 /**
220 @author David Saxton
221 */
222 class RectangularOverlay : public ResizeOverlay
223 {
224 Q_OBJECT
225 public:
226 	RectangularOverlay( Item *item, int xsnap = 1, int ysnap = 1 );
227 	void removeTopMiddle();
228 	void removeBotMiddle();
229 	/**
230 	 * Get the size rectangle from the position of the handles. If the size
231 	 * is invalid (e.g. the parent Item does not consider it a valid size,
232 	 * then *ok is set to false; otherwise to true.
233 	 * @returns the sizerect, regardless of whether or not it is valid
234 	 */
235 	QRect getSizeRect( bool *ok = nullptr, bool *widthOk = nullptr, bool *heightOk = nullptr ) const;
236 
237 	bool isValidXPos( ResizeHandle *rh ) override;
238 	bool isValidYPos( ResizeHandle *rh ) override;
239 
240 public slots:
241 	void slotUpdateResizeHandles();
242 
243 protected slots:
244 	void slotResizeHandleMoved( int id, double dx, double dy ) override;
245 
246 
247 protected:
248 	ResizeHandle *m_tl;
249 	ResizeHandle *m_tm;
250 	ResizeHandle *m_tr;
251 	ResizeHandle *m_mr;
252 	ResizeHandle *m_br;
253 	ResizeHandle *m_bm;
254 	ResizeHandle *m_bl;
255 	ResizeHandle *m_ml;
256 };
257 
258 
259 /**
260 @author David Saxton
261 */
262 class LineOverlay : public ResizeOverlay
263 {
264 	Q_OBJECT
265 	public:
266 		LineOverlay( Item * parent );
267 		QPoint startPoint() const;
268 		QPoint endPoint() const;
269 
270 	public slots:
271 		void slotUpdateResizeHandles();
272 
273 	protected slots:
274 		void slotResizeHandleMoved( int id, double dx, double dy ) override;
275 
276 
277 	protected:
278 		ResizeHandle * m_pStart;
279 		ResizeHandle * m_pEnd;
280 };
281 
282 #endif
283