1 /***************************************************************************
2                              qgsmodelsnapper.h
3                              -------------------
4     begin                : March 2020
5     copyright            : (C) 2020 by Nyall Dawson
6     email                : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  ***************************************************************************/
16 #ifndef QGSMODELSNAPPER_H
17 #define QGSMODELSNAPPER_H
18 
19 #include "qgis_gui.h"
20 #include "qgis_sip.h"
21 #include <QPen>
22 
23 
24 #define SIP_NO_FILE
25 
26 /**
27  * \ingroup gui
28  * \class QgsModelSnapper
29  * \brief Manages snapping grids and preset snap lines in a layout, and handles
30  * snapping points to the nearest grid coordinate/snap line when possible.
31  * \since QGIS 3.14
32  */
33 class GUI_EXPORT QgsModelSnapper
34 {
35 
36   public:
37 
38     /**
39      * Constructor for QgsModelSnapper, attached to the specified \a layout.
40      */
41     QgsModelSnapper();
42 
43     /**
44      * Sets the snap \a tolerance (in pixels) to use when snapping.
45      * \see snapTolerance()
46      */
47     void setSnapTolerance( int snapTolerance );
48 
49     /**
50      * Returns the snap tolerance (in pixels) to use when snapping.
51      * \see setSnapTolerance()
52      */
snapTolerance()53     int snapTolerance() const { return mTolerance; }
54 
55     /**
56      * Returns TRUE if snapping to grid is enabled.
57      * \see setSnapToGrid()
58      */
snapToGrid()59     bool snapToGrid() const { return mSnapToGrid; }
60 
61     /**
62      * Sets whether snapping to grid is \a enabled.
63      * \see snapToGrid()
64      */
65     void setSnapToGrid( bool enabled );
66 
67     /**
68      * Snaps a layout coordinate \a point. If \a point was snapped, \a snapped will be set to TRUE.
69      *
70      * The \a scaleFactor argument should be set to the transformation from
71      * scalar transform from layout coordinates to pixels, i.e. the
72      * graphics view transform().m11() value.
73      *
74      * This method considers snapping to the grid, snap lines, etc.
75      *
76      * If the \a horizontalSnapLine and \a verticalSnapLine arguments are specified, then the snapper
77      * will automatically display and position these lines to indicate snapping positions to item bounds.
78      *
79      * A list of items to ignore during the snapping can be specified via the \a ignoreItems list.
80 
81      * \see snapRect()
82      */
83     QPointF snapPoint( QPointF point, double scaleFactor, bool &snapped SIP_OUT, bool snapHorizontal = true, bool snapVertical = true ) const;
84 
85     /**
86      * Snaps a layout coordinate \a rect. If \a rect was snapped, \a snapped will be set to TRUE.
87      *
88      * Snapping occurs by moving the rectangle alone. The rectangle will not be resized
89      * as a result of the snap operation.
90      *
91      * The \a scaleFactor argument should be set to the transformation from
92      * scalar transform from layout coordinates to pixels, i.e. the
93      * graphics view transform().m11() value.
94      *
95      * This method considers snapping to the grid, snap lines, etc.
96      *
97      * If the \a horizontalSnapLine and \a verticalSnapLine arguments are specified, then the snapper
98      * will automatically display and position these lines to indicate snapping positions to item bounds.
99      *
100      * A list of items to ignore during the snapping can be specified via the \a ignoreItems list.
101      *
102      * \see snapPoint()
103      */
104     QRectF snapRect( const QRectF &rect, double scaleFactor, bool &snapped SIP_OUT, bool snapHorizontal = true, bool snapVertical = true ) const;
105 
106     /**
107      * Snaps a layout coordinate \a rect. If \a rect was snapped, \a snapped will be set to TRUE.
108      *
109      * The \a scaleFactor argument should be set to the transformation from
110      * scalar transform from layout coordinates to pixels, i.e. the
111      * graphics view transform().m11() value.
112      *
113      * This method considers snapping to the grid, snap lines, etc.
114      *
115      * If the \a horizontalSnapLine and \a verticalSnapLine arguments are specified, then the snapper
116      * will automatically display and position these lines to indicate snapping positions to item bounds.
117      *
118      * A list of items to ignore during the snapping can be specified via the \a ignoreItems list.
119      *
120      * \see snapPoint()
121      */
122     QRectF snapRectWithResize( const QRectF &rect, double scaleFactor, bool &snapped SIP_OUT, bool snapHorizontal = true, bool snapVertical = true ) const;
123 
124     /**
125      * Snaps a layout coordinate \a point to the grid. If \a point
126      * was snapped horizontally, \a snappedX will be set to TRUE. If \a point
127      * was snapped vertically, \a snappedY will be set to TRUE.
128      *
129      * The \a scaleFactor argument should be set to the transformation from
130      * scalar transform from layout coordinates to pixels, i.e. the
131      * graphics view transform().m11() value.
132      *
133      * If snapToGrid() is disabled, this method will return the point
134      * unchanged.
135      *
136      * \see snapPointsToGrid()
137      */
138     QPointF snapPointToGrid( QPointF point, double scaleFactor, bool &snappedX SIP_OUT, bool &snappedY SIP_OUT ) const;
139 
140     /**
141      * Snaps a set of \a points to the grid. If the points
142      * were snapped, \a snapped will be set to TRUE.
143      *
144      * The \a scaleFactor argument should be set to the transformation from
145      * scalar transform from layout coordinates to pixels, i.e. the
146      * graphics view transform().m11() value.
147      *
148      * If snapToGrid() is disabled, this method will not attempt to snap the points.
149      *
150      * The returned value is the smallest delta which the points need to be shifted by in order to align
151      * one of the points to the grid.
152      *
153      * \see snapPointToGrid()
154      */
155     QPointF snapPointsToGrid( const QList< QPointF > &points, double scaleFactor, bool &snappedX SIP_OUT, bool &snappedY SIP_OUT ) const;
156 
157   private:
158 
159     int mTolerance = 5;
160     bool mSnapToGrid = false;
161 
162 };
163 
164 #endif //QGSMODELSNAPPER_H
165