7e0a846ec96ba27043d7db0664796f23241cadde
[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         //cerr << " font->get_size() = " << font->get_size() << " is_absolute = " << pango_font_description_get_size_is_absolute(font->gobj()) << " to_string = " << font->to_string() << endl;
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         delete line;
287         line = 0;
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