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