d5517b4bcedeed72ae4c536a8bda071f1921771a
[ardour.git] / gtk2_ardour / marker.cc
1 /*
2     Copyright (C) 2001 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <sigc++/bind.h>
22 #include <ardour/tempo.h>
23
24 #include "marker.h"
25 #include "public_editor.h"
26 #include "utils.h"
27 #include "canvas_impl.h"
28
29 #include "i18n.h"
30
31 Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, const string& annotation, 
32                 Type type, nframes_t frame, bool handle_events)
33
34         : editor (ed), _type(type)
35 {
36         double label_offset = 0;
37         bool annotate_left = false;
38
39         /* Shapes we use:
40
41           Mark:
42
43            (0,0) -> (6,0)
44              ^        |
45              |        V
46            (0,5)    (6,5)
47                \    / 
48                (3,10)
49
50
51            TempoMark:
52            MeterMark:
53
54                (3,0)
55               /      \
56            (0,5) -> (6,5)
57              ^        |
58              |        V
59            (0,10)<-(6,10)
60
61
62            Start:
63
64            0,0\ 
65             |  \        
66             |   \ 6,6
67             |   /
68             |  /
69            0,12 
70
71            End:
72
73                /12,0
74               /     | 
75              /      |
76            6,6      |
77              \      |
78               \     |
79                \    |
80                12,12
81
82              
83            TransportStart:
84
85              0,0
86               | \ 
87               |  \ 
88               |   \ 
89               |    \
90               |     \  
91              0,13 --- 13,13
92
93            TransportEnd:
94
95                     /13,0
96                    /   |
97                   /    |
98                  /     |
99                 /      |
100                /       |
101              0,13 ------ 13,13
102              
103
104              PunchIn:
105
106              0,0 ------> 13,0
107               |       /
108               |      /
109               |     /
110               |    / 
111               |   / 
112               |  / 
113              0,13
114
115              PunchOut
116
117            0,0 -->-13,0
118             \       | 
119              \      |
120               \     |
121                \    |
122                 \   |
123                  \  |
124                  13,13
125              
126            
127         */
128
129         switch (type) {
130         case Mark:
131                 points = new ArdourCanvas::Points ();
132
133                 points->push_back (Gnome::Art::Point (0.0, 0.0));
134                 points->push_back (Gnome::Art::Point (6.0, 0.0));
135                 points->push_back (Gnome::Art::Point (6.0, 5.0));
136                 points->push_back (Gnome::Art::Point (3.0, 10.0));              
137                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
138                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
139                 
140                 shift = 3;
141                 label_offset = 8.0;
142                 break;
143
144         case Tempo:
145         case Meter:
146
147                 points = new ArdourCanvas::Points ();
148                 points->push_back (Gnome::Art::Point (3.0, 0.0));
149                 points->push_back (Gnome::Art::Point (6.0, 5.0));               
150                 points->push_back (Gnome::Art::Point (6.0, 10.0));              
151                 points->push_back (Gnome::Art::Point (0.0, 10.0));              
152                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
153                 points->push_back (Gnome::Art::Point (3.0, 0.0));               
154
155                 shift = 3;
156                 label_offset = 8.0;
157                 break;
158
159         case Start:
160                 points = new ArdourCanvas::Points ();
161                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
162                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
163                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
164                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
165
166                 shift = 0;
167                 label_offset = 13.0;
168                 break;
169
170         case End:
171                 points = new ArdourCanvas::Points ();
172                 points->push_back (Gnome::Art::Point (6.5, 6.5));
173                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
174                 points->push_back (Gnome::Art::Point (13.0, 13.0));                     
175                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
176                 
177                 shift = 13;
178                 label_offset = 6.0;
179                 annotate_left = true;
180                 break;
181
182         case LoopStart:
183                 points = new ArdourCanvas::Points ();
184                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
185                 points->push_back (Gnome::Art::Point (13.0, 13.0));             
186                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
187                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
188                 
189                 shift = 0;
190                 label_offset = 12.0;
191                 break;
192
193         case LoopEnd:
194                 points = new ArdourCanvas::Points ();
195                 points->push_back (Gnome::Art::Point (13.0,  0.0));
196                 points->push_back (Gnome::Art::Point (13.0, 13.0));     
197                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
198                 points->push_back (Gnome::Art::Point (13.0, 0.0));
199                 
200                 shift = 13;
201                 label_offset = 0.0;
202                 annotate_left = true;
203                 break;
204
205         case  PunchIn:
206                 points = new ArdourCanvas::Points ();
207                 points->push_back (Gnome::Art::Point (0.0, 0.0));
208                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
209                 points->push_back (Gnome::Art::Point (0.0, 13.0));      
210                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
211
212                 shift = 0;
213                 label_offset = 13.0;
214                 break;
215                 
216         case  PunchOut:
217                 points = new ArdourCanvas::Points ();
218                 points->push_back (Gnome::Art::Point (0.0, 0.0));
219                 points->push_back (Gnome::Art::Point (12.0, 0.0));                      
220                 points->push_back (Gnome::Art::Point (12.0, 12.0));             
221                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
222
223                 shift = 13;
224                 label_offset = 0.0;
225                 annotate_left = true;
226                 break;
227                 
228         }
229
230         frame_position = frame;
231         unit_position = editor.frame_to_unit (frame);
232
233         /* adjust to properly locate the tip */
234
235         unit_position -= shift;
236
237         group = new Group (parent, unit_position, 1.0);
238
239         mark = new Polygon (*group);
240         mark->property_points() = *points;
241         mark->property_fill_color_rgba() = rgba;
242         mark->property_outline_color_rgba() = rgba;
243         mark->property_width_pixels() = 1;
244         Pango::FontDescription font = get_font_for_style (N_("MarkerText"));
245         
246         text = new Text (*group);
247         text->property_text() = annotation.c_str();
248         text->property_font_desc() = font;
249         if (annotate_left) {
250           text->property_x() = -(text->property_text_width());
251         } else {
252           text->property_x() = label_offset;
253         }
254         text->property_y() = 0.0;
255         text->property_anchor() = Gtk::ANCHOR_NW;
256         text->property_fill_color() = "black";
257
258         editor.ZoomChanged.connect (mem_fun (*this, &Marker::reposition));
259
260         mark->set_data ("marker", this);
261
262         if (handle_events) {
263                 group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
264         }
265
266 }
267
268 Marker::~Marker ()
269 {
270         /* destroying the parent group destroys its contents, namely any polygons etc. that we added */
271         delete text;
272         delete mark;
273         delete points;
274 }
275
276 ArdourCanvas::Item&
277 Marker::the_item() const
278 {
279         return *mark;
280 }
281
282 void
283 Marker::set_name (const string& name)
284 {
285         text->property_text() = name.c_str();
286         if (_type == End) {
287           text->property_x() = -(text->property_text_width());
288         }
289 }
290
291 void
292 Marker::set_position (nframes_t frame)
293 {
294         double new_unit_position = editor.frame_to_unit (frame);
295         new_unit_position -= shift;
296         group->move (new_unit_position - unit_position, 0.0);
297         frame_position = frame;
298         unit_position = new_unit_position;
299 }
300
301 void
302 Marker::reposition ()
303 {
304         set_position (frame_position);
305 }       
306
307 void
308 Marker::show ()
309 {
310         group->show();
311 }
312
313 void
314 Marker::hide ()
315 {
316         group->hide();
317 }
318
319 void
320 Marker::set_color_rgba (uint32_t color)
321 {
322         mark->property_fill_color_rgba() = color;
323 }
324
325 /***********************************************************************/
326
327 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
328                           ARDOUR::TempoSection& temp)
329         : Marker (editor, parent, rgba, text, Tempo, 0, false),
330           _tempo (temp)
331 {
332         set_position (_tempo.frame());
333         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), mark, this));
334 }
335
336 TempoMarker::~TempoMarker ()
337 {
338 }
339
340 /***********************************************************************/
341
342 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
343                           ARDOUR::MeterSection& m) 
344         : Marker (editor, parent, rgba, text, Meter, 0, false),
345           _meter (m)
346 {
347         set_position (_meter.frame());
348         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_meter_marker_event), mark, this));
349 }
350
351 MeterMarker::~MeterMarker ()
352 {
353 }
354