1 /***************************************************************************
2     File                 : ArrowMarker.h
3     Project              : SciDAVis
4     --------------------------------------------------------------------
5     Copyright            : (C) 2006 by Ion Vasilief
6     Email (use @ for *)  : ion_vasilief*yahoo.fr
7     Description          : Arrow marker (extension to QwtPlotMarker)
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *  This program is free software; you can redistribute it and/or modify   *
14  *  it under the terms of the GNU General Public License as published by   *
15  *  the Free Software Foundation; either version 2 of the License, or      *
16  *  (at your option) any later version.                                    *
17  *                                                                         *
18  *  This program is distributed in the hope that it will be useful,        *
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
21  *  GNU General Public License for more details.                           *
22  *                                                                         *
23  *   You should have received a copy of the GNU General Public License     *
24  *   along with this program; if not, write to the Free Software           *
25  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
26  *   Boston, MA  02110-1301  USA                                           *
27  *                                                                         *
28  ***************************************************************************/
29 #ifndef ARROWMARKER_H
30 #define ARROWMARKER_H
31 
32 #include "PlotEnrichement.h"
33 
34 /*!\brief Draws lines and arrows on a QwtPlot.
35  *
36  * \section design Design Ideas
37  * Move all the code for editing the end points from CanvasPicker here, so that we have it all in
38  * one place. This approach will make adding new editable markers (e.g. polygons) much easier, and
39  * it will allow this to be done in plug-ins.
40  *
41  * \sa ImageMarker, Legend
42  */
43 class ArrowMarker : public QObject, public PlotEnrichement
44 {
45 public:
46     enum Operation { None, MoveStart, MoveEnd, MoveBoth };
47     ArrowMarker();
48 
49     //! Pixel coordinates of the start point
50     QPoint startPoint() const;
51     //! Sets the start point in pixel coordinates
52     void setStartPoint(const QPoint &p);
53 
54     //! Pixel coordinates of the end point
55     QPoint endPoint() const;
56     //! Sets the end point in pixel coordinates
57     void setEndPoint(const QPoint &p);
58 
59     //! Axes values coordinates of the start point
60     QwtDoublePoint startPointCoord();
61     //! Sets the start point in axes values coordinates
62     void setStartPoint(double x, double y);
63 
64     //! Axes values coordinates of the end point
65     QwtDoublePoint endPointCoord();
66     //! Sets the end point in axes values coordinates
67     void setEndPoint(double x, double y);
68 
69     void setColor(const QColor &c);
color()70     QColor color() { return linePen().color(); };
71 
72     //! Sets the width of the arrow line
73     void setWidth(int w);
74     //! The width of the arrow line
width()75     int width() { return linePen().width(); };
76 
77     //! Sets the pen style for the arrow line
78     void setStyle(Qt::PenStyle s);
79     //! The pen style of the arrow line
style()80     Qt::PenStyle style() { return linePen().style(); };
81     void setCapStyle(Qt::PenCapStyle c);
capStyle()82     Qt::PenCapStyle capStyle() { return linePen().capStyle(); };
83     void setJoinStyle(Qt::PenJoinStyle);
joinStyle()84     Qt::PenJoinStyle joinStyle() { return linePen().joinStyle(); };
85 
86     //! Specifies weather the start arrow should be drawn
87     void drawStartArrow(bool on = true) { d_start_arrow = on; };
hasStartArrow()88     bool hasStartArrow() { return d_start_arrow; };
89 
90     //! Specifies weather the end arrow should be drawn
91     void drawEndArrow(bool on = true) { d_end_arrow = on; };
hasEndArrow()92     bool hasEndArrow() { return d_end_arrow; };
93 
94     //! Length of the arrow head
headLength()95     int headLength() { return d_head_length; };
96     //! Sets the length of the arrow head
97     void setHeadLength(int l);
98 
99     //! The angle of the arrow head
headAngle()100     int headAngle() { return d_head_angle; };
101     //! Sets the angle of the arrow head
102     void setHeadAngle(int a);
103 
filledArrowHead()104     bool filledArrowHead() { return d_fill_head; };
105     //! Specifies weather the arrow head should be filled with a brush
106     void fillArrowHead(bool fill = true);
107 
108     //! Returns the shortest distance to the arrow line or to one of the arrow heads
109     double dist(int x, int y);
110 
111     //! Returns the length of the arrow line
112     double length();
113 
114     //! Returns the bounding rectangle in paint coordinates.
rect()115     QRect rect() const { return QRect(startPoint(), endPoint()).normalized(); };
116 
117     //! Returns the bounding rectangle in plot coordinates.
118     QwtDoubleRect boundingRect() const;
119     void setBoundingRect(double xs, double ys, double xe, double ye);
120 
121     //! Recalculates the bounding rectangle in values coordinates using the pixel coordinats when the scales change
122     void updateBoundingRect();
123 
124     //! Returns the state of #d_editable.
editable()125     bool editable() const { return d_editable; }
126     //! Starts/ends editing of end points by the user.
127     void setEditable(bool yes);
128 
129     //! Filters events for the canvas while #d_editable is true.
130     bool eventFilter(QObject *o, QEvent *e);
131 
132 private:
133     void draw(QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRect &r) const;
134     double theta(int xs, int ys, int xe, int ye) const;
135 
136     //! Flag specifying if the start arrow is visible
137     bool d_start_arrow;
138 
139     //! Flag specifying if the end arrow is visible
140     bool d_end_arrow;
141 
142     //! Flag specifying if the arrow head is filled with a brush
143     bool d_fill_head;
144 
145     //! Angle of the arrow head
146     int d_head_angle;
147 
148     //! Length of the arrow head
149     int d_head_length;
150 
151     //! Custom dash pattern
152     QString d_custom_dash;
153 
154     //! Pixel coordinates of the start point
155     QPoint d_start;
156 
157     //! Pixel coordinates of the end point
158     QPoint d_end;
159 
160     //! Bounding rectangle of the arrow in axes values coordinates
161     QwtDoubleRect d_rect;
162     //! Whether start and end point can be moved by the user.
163     bool d_editable;
164 
165     //! What editing operation is in progress.
166     Operation d_op;
167 
168     /*!\brief Difference between mouse position where a MoveBoth operation started and startPoint().
169      * When only one point is being moved, we can simply setStartPoint() or setEndPoint() to the
170      * current mouse position, but when the editing starts in the middle of the line, we
171      * need to remember this bit.
172      */
173     QPoint d_op_startat;
174 };
175 #endif
176