NOOP, re-indent using tabs
[ardour.git] / libs / canvas / arrow.cc
1 /*
2     Copyright (C) 2011 Paul Davis
3     Author: Carl Hetherington <cth@carlh.net>
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     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 /** @file  canvas/arrow.cc
22  *  @brief Implementation of the Arrow canvas object.
23  */
24
25 #include "pbd/compose.h"
26
27 #include "canvas/arrow.h"
28 #include "canvas/debug.h"
29 #include "canvas/polygon.h"
30 #include "canvas/line.h"
31
32 using namespace ArdourCanvas;
33
34 /** Construct an Arrow.
35  *  @param parent Parent canvas group.
36  */
37 Arrow::Arrow (Group* parent)
38         : Group (parent)
39 {
40         assert (parent);
41
42         /* set up default arrow heads at each end */
43         for (int i = 0; i < 2; ++i) {
44                 _heads[i].polygon = new Polygon (this);
45                 _heads[i].outward = true;
46                 _heads[i].width = 4;
47                 _heads[i].height = 4;
48                 setup_polygon (i);
49                 CANVAS_DEBUG_NAME (_heads[i].polygon, string_compose ("arrow head %1", i));
50         }
51         
52         _line = new Line (this);
53         CANVAS_DEBUG_NAME (_line, "arrow line");
54 }
55
56 /** Set whether to show an arrow head at one end or other
57  *  of the line.
58  *  @param which 0 or 1 to specify the arrow head to set up.
59  *  @param true if this arrow head should be shown.
60  */
61 void
62 Arrow::set_show_head (int which, bool show)
63 {
64         assert (which == 0 || which == 1);
65         
66         begin_change ();
67         
68         if (!show) {
69                 delete _heads[which].polygon;
70                 _heads[which].polygon = 0;
71         } else {
72                 setup_polygon (which);
73         }
74
75         _bounding_box_dirty = true;
76         end_change ();
77 }
78
79 /** Set whether a given arrow head points into the line or
80  *  away from it.
81  *  @param which 0 or 1 to specify the arrow head to set up.
82  *  @param true if this arrow head should point out from the line,
83  *  otherwise false to point in.
84  */
85 void
86 Arrow::set_head_outward (int which, bool outward)
87 {
88         assert (which == 0 || which == 1);
89         
90         begin_change ();
91
92         _heads[which].outward = outward;
93
94         setup_polygon (which);
95         _bounding_box_dirty = true;
96         end_change ();
97 }
98
99 /** Set the height of a given arrow head.
100  *  @param which 0 or 1 to specify the arrow head to set up.
101  *  @param height Height of the arrow head in pixels.
102  */
103 void
104 Arrow::set_head_height (int which, Distance height)
105 {
106         assert (which == 0 || which == 1);
107         
108         begin_change ();
109         
110         _heads[which].height = height;
111
112         setup_polygon (which);
113         _bounding_box_dirty = true;
114         end_change ();
115 }
116
117 /** Set the width of a given arrow head.
118  *  @param which 0 or 1 to specify the arrow head to set up.
119  *  @param width Width of the arrow head in pixels.
120  */
121 void
122 Arrow::set_head_width (int which, Distance width)
123 {
124         assert (which == 0 || which == 1);
125         
126         begin_change ();
127         
128         _heads[which].width = width;
129
130         setup_polygon (which);
131         _bounding_box_dirty = true;
132         end_change ();
133 }
134
135 /** Set the width of our line, and the outline of our arrow(s).
136  *  @param width New width in pixels.
137  */
138 void
139 Arrow::set_outline_width (Distance width)
140 {
141         _line->set_outline_width (width);
142         if (_heads[0].polygon) {
143                 _heads[0].polygon->set_outline_width (width);
144         }
145         if (_heads[1].polygon) {
146                 _heads[1].polygon->set_outline_width (width);
147         }
148 }
149
150 /** Set the x position of our line.
151  *  @param x New x position in pixels (in our coordinate system).
152  */
153 void
154 Arrow::set_x (Coord x)
155 {
156         _line->set_x0 (x);
157         _line->set_x1 (x);
158         for (int i = 0; i < 2; ++i) {
159                 if (_heads[i].polygon) {
160                         _heads[i].polygon->set_x_position (x - _heads[i].width / 2);
161                 }
162         }
163                 
164 }
165
166 /** Set the y position of end 0 of our line.
167  *  @param y0 New y0 position in pixels (in our coordinate system).
168  */
169 void
170 Arrow::set_y0 (Coord y0)
171 {
172         _line->set_y0 (y0);
173         if (_heads[0].polygon) {
174                 _heads[0].polygon->set_y_position (y0);
175         }
176 }
177
178 /** Set the y position of end 1 of our line.
179  *  @param y1 New y1 position in pixels (in our coordinate system).
180  */
181 void
182 Arrow::set_y1 (Coord y1)
183 {
184         _line->set_y1 (y1);
185         if (_heads[1].polygon) {
186                 _heads[1].polygon->set_y_position (y1 - _heads[1].height);
187         }
188 }
189
190 /** @return x position of our line in pixels (in our coordinate system) */
191 Coord
192 Arrow::x () const
193 {
194         return _line->x0 ();
195 }
196
197 /** @return y position of end 1 of our line in pixels (in our coordinate system) */
198 Coord
199 Arrow::y1 () const
200 {
201         return _line->y1 ();
202 }
203
204 /** Set up the polygon used to represent a particular arrow head.
205  *  @param which 0 or 1 to specify the arrow head to set up.
206  */
207 void
208 Arrow::setup_polygon (int which)
209 {
210         assert (which == 0 || which == 1);
211         
212         Points points;
213
214         if ((which == 0 && _heads[which].outward) || (which == 1 && !_heads[which].outward)) {
215                 /* this is an arrow head pointing towards -ve y */
216                 points.push_back (Duple (_heads[which].width / 2, 0));
217                 points.push_back (Duple (_heads[which].width, _heads[which].height));
218                 points.push_back (Duple (0, _heads[which].height));
219         } else {
220                 /* this is an arrow head pointing towards +ve y */
221                 points.push_back (Duple (0, 0));
222                 points.push_back (Duple (_heads[which].width, 0));
223                 points.push_back (Duple (_heads[which].width / 2, _heads[which].height));
224                 points.push_back (Duple (0, 0));
225         }
226
227         _heads[which].polygon->set (points);
228 }
229
230 /** Set the color of our line and arrow heads.
231  *  @param color New color.
232  */
233 void
234 Arrow::set_color (Color color)
235 {
236         _line->set_outline_color (color);
237         for (int i = 0; i < 2; ++i) {
238                 if (_heads[i].polygon) {
239                         _heads[i].polygon->set_outline_color (color);
240                         _heads[i].polygon->set_fill_color (color);
241                 }
242         }
243 }
244
245 bool
246 Arrow::covers (Duple const & point) const
247 {
248         if (_heads[0].polygon && _heads[0].polygon->covers (point)) {
249                 return true;
250         }
251         if (_line && _line->covers (point)) {
252                 return true;
253         }
254
255         if (_heads[1].polygon && _heads[1].polygon->covers (point)) {
256                 return true;
257         }
258
259         return false;
260 }