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