make selected marker line resize as canvas size changes
[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
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), _parent(&parent), _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
250         delete font;
251         
252         if (annotate_left) {
253                 text->property_x() = -(text->property_text_width());
254         } else {
255                 text->property_x() = label_offset;
256         }
257         text->property_y() = 0.0;
258         text->property_anchor() = Gtk::ANCHOR_NW;
259         text->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerLabel.get();
260
261         editor.ZoomChanged.connect (mem_fun (*this, &Marker::reposition));
262
263         mark->set_data ("marker", this);
264
265         if (handle_events) {
266                 group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
267         }
268
269         line = 0;
270         line_points = 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                 delete line_points;
287         }
288 }
289
290 void Marker::reparent(ArdourCanvas::Group & parent)
291 {
292         group->reparent(parent);
293         _parent = &parent;
294 }
295
296 void
297 Marker::set_line_length (double len)
298 {
299         if (line) {
300                 line_points->back().set_y (len);
301                 line->property_points() = *line_points;
302         }
303 }
304
305 void
306 Marker::add_line (ArdourCanvas::Group* group, double initial_height)
307 {
308         if (!line) {
309
310                 line_points = new ArdourCanvas::Points ();
311                 line_points->push_back (Gnome::Art::Point (unit_position + shift, 0.0));
312                 line_points->push_back (Gnome::Art::Point (unit_position + shift, initial_height));                     
313                 
314                 line = new ArdourCanvas::Line (*group);
315                 line->property_width_pixels() = 1;
316                 line->property_points() = *line_points;
317                 line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_EditPoint.get();
318 #if 0
319                 line->property_first_arrowhead() = TRUE;
320                 line->property_last_arrowhead() = TRUE;
321                 line->property_arrow_shape_a() = 11.0;
322                 line->property_arrow_shape_b() = 0.0;
323                 line->property_arrow_shape_c() = 9.0;
324 #endif
325                 line->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_marker_event), mark, this));
326         }
327
328         show_line ();
329 }
330
331 void
332 Marker::show_line ()
333 {
334         if (line) {
335                 line->raise_to_top();
336                 line->show ();
337         }
338 }
339
340 void 
341 Marker::hide_line ()
342 {
343         if (line) {
344                 line->hide ();
345         }
346 }
347
348 ArdourCanvas::Item&
349 Marker::the_item() const
350 {
351         return *mark;
352 }
353
354 void
355 Marker::set_name (const string& name)
356 {
357         text->property_text() = name.c_str();
358         if (_type == End) {
359           text->property_x() = -(text->property_text_width());
360         }
361 }
362
363 void
364 Marker::set_position (nframes_t frame)
365 {
366         double new_unit_position = editor.frame_to_unit (frame);
367         new_unit_position -= shift;
368         group->move (new_unit_position - unit_position, 0.0);
369         frame_position = frame;
370         unit_position = new_unit_position;
371
372         if (line) {
373                 (*line_points)[0].set_x (unit_position + shift);
374                 (*line_points)[1].set_x (unit_position + shift);
375                 line->property_points() = *line_points;
376         }
377 }
378
379 void
380 Marker::reposition ()
381 {
382         set_position (frame_position);
383 }       
384
385 void
386 Marker::show ()
387 {
388         group->show();
389 }
390
391 void
392 Marker::hide ()
393 {
394         group->hide();
395 }
396
397 void
398 Marker::set_color_rgba (uint32_t color)
399 {
400         mark->property_fill_color_rgba() = color;
401         mark->property_outline_color_rgba() = color;
402 }
403
404 /***********************************************************************/
405
406 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
407                           ARDOUR::TempoSection& temp)
408         : Marker (editor, parent, rgba, text, Tempo, 0, false),
409           _tempo (temp)
410 {
411         set_position (_tempo.frame());
412         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), mark, this));
413 }
414
415 TempoMarker::~TempoMarker ()
416 {
417 }
418
419 /***********************************************************************/
420
421 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
422                           ARDOUR::MeterSection& m) 
423         : Marker (editor, parent, rgba, text, Meter, 0, false),
424           _meter (m)
425 {
426         set_position (_meter.frame());
427         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_meter_marker_event), mark, this));
428 }
429
430 MeterMarker::~MeterMarker ()
431 {
432 }
433