merge from 2.0-ongoing @ 3581
[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 */
19
20 #include <sigc++/bind.h>
21 #include <ardour/tempo.h>
22
23 #include "marker.h"
24 #include "public_editor.h"
25 #include "utils.h"
26 #include "canvas_impl.h"
27 #include "ardour_ui.h"
28 #include "simpleline.h"
29
30 #include "i18n.h"
31
32 using namespace ARDOUR;
33
34 Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, const string& annotation, 
35                 Type type, nframes_t frame, bool handle_events)
36
37         : editor (ed), _parent(&parent), _type(type)
38 {
39         double label_offset = 0;
40         bool annotate_left = false;
41
42         /* Shapes we use:
43
44           Mark:
45
46            (0,0) -> (6,0)
47              ^        |
48              |        V
49            (0,5)    (6,5)
50                \    / 
51                (3,10)
52
53
54            TempoMark:
55            MeterMark:
56
57                (3,0)
58               /      \
59            (0,5) -> (6,5)
60              ^        |
61              |        V
62            (0,10)<-(6,10)
63
64
65            Start:
66
67            0,0\ 
68             |  \        
69             |   \ 6,6
70             |   /
71             |  /
72            0,12 
73
74            End:
75
76                /12,0
77               /     | 
78              /      |
79            6,6      |
80              \      |
81               \     |
82                \    |
83                12,12
84
85              
86            TransportStart:
87
88              0,0
89               | \ 
90               |  \ 
91               |   \ 
92               |    \
93               |     \  
94              0,13 --- 13,13
95
96            TransportEnd:
97
98                     /13,0
99                    /   |
100                   /    |
101                  /     |
102                 /      |
103                /       |
104              0,13 ------ 13,13
105              
106
107              PunchIn:
108
109              0,0 ------> 13,0
110               |       /
111               |      /
112               |     /
113               |    / 
114               |   / 
115               |  / 
116              0,13
117
118              PunchOut
119
120            0,0 -->-13,0
121             \       | 
122              \      |
123               \     |
124                \    |
125                 \   |
126                  \  |
127                  13,13
128              
129            
130         */
131
132         switch (type) {
133         case Mark:
134                 points = new ArdourCanvas::Points ();
135
136                 points->push_back (Gnome::Art::Point (0.0, 0.0));
137                 points->push_back (Gnome::Art::Point (6.0, 0.0));
138                 points->push_back (Gnome::Art::Point (6.0, 5.0));
139                 points->push_back (Gnome::Art::Point (3.0, 10.0));              
140                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
141                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
142                 
143                 shift = 3;
144                 label_offset = 8.0;
145                 break;
146
147         case Tempo:
148         case Meter:
149
150                 points = new ArdourCanvas::Points ();
151                 points->push_back (Gnome::Art::Point (3.0, 0.0));
152                 points->push_back (Gnome::Art::Point (6.0, 5.0));               
153                 points->push_back (Gnome::Art::Point (6.0, 10.0));              
154                 points->push_back (Gnome::Art::Point (0.0, 10.0));              
155                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
156                 points->push_back (Gnome::Art::Point (3.0, 0.0));               
157
158                 shift = 3;
159                 label_offset = 8.0;
160                 break;
161
162         case Start:
163                 points = new ArdourCanvas::Points ();
164                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
165                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
166                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
167                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
168
169                 shift = 0;
170                 label_offset = 13.0;
171                 break;
172
173         case End:
174                 points = new ArdourCanvas::Points ();
175                 points->push_back (Gnome::Art::Point (6.5, 6.5));
176                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
177                 points->push_back (Gnome::Art::Point (13.0, 13.0));                     
178                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
179                 
180                 shift = 13;
181                 label_offset = 6.0;
182                 annotate_left = true;
183                 break;
184
185         case LoopStart:
186                 points = new ArdourCanvas::Points ();
187                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
188                 points->push_back (Gnome::Art::Point (13.0, 13.0));             
189                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
190                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
191                 
192                 shift = 0;
193                 label_offset = 12.0;
194                 break;
195
196         case LoopEnd:
197                 points = new ArdourCanvas::Points ();
198                 points->push_back (Gnome::Art::Point (13.0,  0.0));
199                 points->push_back (Gnome::Art::Point (13.0, 13.0));     
200                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
201                 points->push_back (Gnome::Art::Point (13.0, 0.0));
202                 
203                 shift = 13;
204                 label_offset = 0.0;
205                 annotate_left = true;
206                 break;
207
208         case  PunchIn:
209                 points = new ArdourCanvas::Points ();
210                 points->push_back (Gnome::Art::Point (0.0, 0.0));
211                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
212                 points->push_back (Gnome::Art::Point (0.0, 13.0));      
213                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
214
215                 shift = 0;
216                 label_offset = 13.0;
217                 break;
218                 
219         case  PunchOut:
220                 points = new ArdourCanvas::Points ();
221                 points->push_back (Gnome::Art::Point (0.0, 0.0));
222                 points->push_back (Gnome::Art::Point (12.0, 0.0));                      
223                 points->push_back (Gnome::Art::Point (12.0, 12.0));             
224                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
225
226                 shift = 13;
227                 label_offset = 0.0;
228                 annotate_left = true;
229                 break;
230                 
231         }
232
233         frame_position = frame;
234         unit_position = editor.frame_to_unit (frame);
235
236         /* adjust to properly locate the tip */
237
238         unit_position -= shift;
239
240         group = new Group (parent, unit_position, 1.0);
241
242         mark = new Polygon (*group);
243         mark->property_points() = *points;
244         mark->property_fill_color_rgba() = rgba;
245         mark->property_outline_color_rgba() = rgba;
246         mark->property_width_pixels() = 1;
247         Pango::FontDescription* font = get_font_for_style (N_("MarkerText"));
248
249         text = new Text (*group);
250         text->property_font_desc() = *font;
251         text->property_text() = annotation.c_str();
252
253         delete font;
254         
255         if (annotate_left) {
256                 text->property_x() = -(text->property_text_width());
257         } else {
258                 text->property_x() = label_offset;
259         }
260         text->property_y() = 0.0;
261         text->property_anchor() = Gtk::ANCHOR_NW;
262         text->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerLabel.get();
263
264         editor.ZoomChanged.connect (mem_fun (*this, &Marker::reposition));
265
266         mark->set_data ("marker", this);
267
268         if (handle_events) {
269                 group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
270         }
271
272         line = 0;
273
274 }
275
276
277 Marker::~Marker ()
278 {
279         drop_references ();
280
281         /* destroying the parent group destroys its contents, namely any polygons etc. that we added */
282         delete text;
283         delete mark;
284         delete points;
285
286         if (line) {
287                 delete line;
288                 line = 0;
289         }
290 }
291
292 void Marker::reparent(ArdourCanvas::Group & parent)
293 {
294         group->reparent(parent);
295         _parent = &parent;
296 }
297
298
299 void
300 Marker::set_line_vpos (double pos, double height)
301 {
302         if (line) {
303                 line->property_y1() = pos;
304                 line->property_y2() = pos + height;
305         }
306 }
307
308 void
309 Marker::add_line (ArdourCanvas::Group* group, double y_origin, double initial_height)
310 {
311         if (!line) {
312
313                 line = new ArdourCanvas::SimpleLine (*group);
314                 line->property_color_rgba() = ARDOUR_UI::config()->canvasvar_EditPoint.get();
315                 line->property_x1() = unit_position + shift;
316                 line->property_y1() = y_origin;
317                 line->property_x2() = unit_position + shift;
318                 line->property_y2() = y_origin + initial_height;
319
320                 line->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
321         }
322
323         show_line ();
324 }
325
326 void
327 Marker::show_line ()
328 {
329         if (line) {
330                 line->raise_to_top();
331                 line->show ();
332         }
333 }
334
335 void 
336 Marker::hide_line ()
337 {
338         if (line) {
339                 line->hide ();
340         }
341 }
342
343 ArdourCanvas::Item&
344 Marker::the_item() const
345 {
346         return *mark;
347 }
348
349 void
350 Marker::set_name (const string& name)
351 {
352         text->property_text() = name.c_str();
353         if (_type == End) {
354           text->property_x() = -(text->property_text_width());
355         }
356 }
357
358 void
359 Marker::set_position (nframes_t frame)
360 {
361         double new_unit_position = editor.frame_to_unit (frame);
362         new_unit_position -= shift;
363         group->move (new_unit_position - unit_position, 0.0);
364         frame_position = frame;
365         unit_position = new_unit_position;
366
367         if (line) {
368                 line->property_x1() = unit_position + shift;
369                 line->property_x2() = unit_position + shift;
370         }
371 }
372
373 void
374 Marker::reposition ()
375 {
376         set_position (frame_position);
377 }       
378
379 void
380 Marker::show ()
381 {
382         group->show();
383 }
384
385 void
386 Marker::hide ()
387 {
388         group->hide();
389 }
390
391 void
392 Marker::set_color_rgba (uint32_t color)
393 {
394         mark->property_fill_color_rgba() = color;
395         mark->property_outline_color_rgba() = color;
396 }
397
398 /***********************************************************************/
399
400 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
401                           ARDOUR::TempoSection& temp)
402         : Marker (editor, parent, rgba, text, Tempo, 0, false),
403           _tempo (temp)
404 {
405         set_position (_tempo.frame());
406         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), mark, this));
407 }
408
409 TempoMarker::~TempoMarker ()
410 {
411 }
412
413 /***********************************************************************/
414
415 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
416                           ARDOUR::MeterSection& m) 
417         : Marker (editor, parent, rgba, text, Meter, 0, false),
418           _meter (m)
419 {
420         set_position (_meter.frame());
421         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_meter_marker_event), mark, this));
422 }
423
424 MeterMarker::~MeterMarker ()
425 {
426 }
427