Merge with 2.0-ongoing R2885.
[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_text() = annotation.c_str();
251         text->property_font_desc() = *font;
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         }
289 }
290
291 void Marker::reparent(ArdourCanvas::Group & parent)
292 {
293         group->reparent(parent);
294         _parent = &parent;
295 }
296
297
298 void
299 Marker::set_line_vpos (double pos, double height)
300 {
301         if (line) {
302                 line->property_y1() = pos;
303                 line->property_y2() = pos + height;
304         }
305 }
306
307 void
308 Marker::add_line (ArdourCanvas::Group* group, double y_origin, double initial_height)
309 {
310         if (!line) {
311
312                 line = new ArdourCanvas::SimpleLine (*group);
313                 line->property_color_rgba() = ARDOUR_UI::config()->canvasvar_EditPoint.get();
314                 line->property_x1() = unit_position + shift;
315                 line->property_y1() = y_origin;
316                 line->property_x2() = unit_position + shift;
317                 line->property_y2() = y_origin + initial_height;
318
319                 line->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
320         }
321
322         show_line ();
323 }
324
325 void
326 Marker::show_line ()
327 {
328         if (line) {
329                 line->raise_to_top();
330                 line->show ();
331         }
332 }
333
334 void 
335 Marker::hide_line ()
336 {
337         if (line) {
338                 line->hide ();
339         }
340 }
341
342 ArdourCanvas::Item&
343 Marker::the_item() const
344 {
345         return *mark;
346 }
347
348 void
349 Marker::set_name (const string& name)
350 {
351         text->property_text() = name.c_str();
352         if (_type == End) {
353           text->property_x() = -(text->property_text_width());
354         }
355 }
356
357 void
358 Marker::set_position (nframes_t frame)
359 {
360         double new_unit_position = editor.frame_to_unit (frame);
361         new_unit_position -= shift;
362         group->move (new_unit_position - unit_position, 0.0);
363         frame_position = frame;
364         unit_position = new_unit_position;
365
366         if (line) {
367                 line->property_x1() = unit_position + shift;
368                 line->property_x2() = unit_position + shift;
369         }
370 }
371
372 void
373 Marker::reposition ()
374 {
375         set_position (frame_position);
376 }       
377
378 void
379 Marker::show ()
380 {
381         group->show();
382 }
383
384 void
385 Marker::hide ()
386 {
387         group->hide();
388 }
389
390 void
391 Marker::set_color_rgba (uint32_t color)
392 {
393         mark->property_fill_color_rgba() = color;
394         mark->property_outline_color_rgba() = color;
395 }
396
397 /***********************************************************************/
398
399 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
400                           ARDOUR::TempoSection& temp)
401         : Marker (editor, parent, rgba, text, Tempo, 0, false),
402           _tempo (temp)
403 {
404         set_position (_tempo.frame());
405         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), mark, this));
406 }
407
408 TempoMarker::~TempoMarker ()
409 {
410 }
411
412 /***********************************************************************/
413
414 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
415                           ARDOUR::MeterSection& m) 
416         : Marker (editor, parent, rgba, text, Meter, 0, false),
417           _meter (m)
418 {
419         set_position (_meter.frame());
420         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_meter_marker_event), mark, this));
421 }
422
423 MeterMarker::~MeterMarker ()
424 {
425 }
426