make marker labels and regionview name text (now drawn with pixbufs) be color-adjusta...
[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 <gtkmm2ext/utils.h>
31
32 #include "i18n.h"
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
41         /* Shapes we use:
42
43           Mark:
44
45            (0,0) -> (6,0)
46              ^        |
47              |        V
48            (0,5)    (6,5)
49                \    / 
50                (3,10)
51
52
53            TempoMark:
54            MeterMark:
55
56                (3,0)
57               /      \
58            (0,5) -> (6,5)
59              ^        |
60              |        V
61            (0,10)<-(6,10)
62
63
64            Start:
65
66            0,0\ 
67             |  \        
68             |   \ 6,6
69             |   /
70             |  /
71            0,12 
72
73            End:
74
75                /12,0
76               /     | 
77              /      |
78            6,6      |
79              \      |
80               \     |
81                \    |
82                12,12
83
84              
85            TransportStart:
86
87              0,0
88               | \ 
89               |  \ 
90               |   \ 
91               |    \
92               |     \  
93              0,13 --- 13,13
94
95            TransportEnd:
96
97                     /13,0
98                    /   |
99                   /    |
100                  /     |
101                 /      |
102                /       |
103              0,13 ------ 13,13
104              
105
106              PunchIn:
107
108              0,0 ------> 13,0
109               |       /
110               |      /
111               |     /
112               |    / 
113               |   / 
114               |  / 
115              0,13
116
117              PunchOut
118
119            0,0 -->-13,0
120             \       | 
121              \      |
122               \     |
123                \    |
124                 \   |
125                  \  |
126                  13,13
127              
128            
129         */
130
131         switch (type) {
132         case Mark:
133                 points = new ArdourCanvas::Points ();
134
135                 points->push_back (Gnome::Art::Point (0.0, 0.0));
136                 points->push_back (Gnome::Art::Point (6.0, 0.0));
137                 points->push_back (Gnome::Art::Point (6.0, 5.0));
138                 points->push_back (Gnome::Art::Point (3.0, 10.0));              
139                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
140                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
141                 
142                 shift = 3;
143                 label_offset = 8.0;
144                 break;
145
146         case Tempo:
147         case Meter:
148
149                 points = new ArdourCanvas::Points ();
150                 points->push_back (Gnome::Art::Point (3.0, 0.0));
151                 points->push_back (Gnome::Art::Point (6.0, 5.0));               
152                 points->push_back (Gnome::Art::Point (6.0, 10.0));              
153                 points->push_back (Gnome::Art::Point (0.0, 10.0));              
154                 points->push_back (Gnome::Art::Point (0.0, 5.0));               
155                 points->push_back (Gnome::Art::Point (3.0, 0.0));               
156
157                 shift = 3;
158                 label_offset = 8.0;
159                 break;
160
161         case Start:
162                 points = new ArdourCanvas::Points ();
163                 points->push_back (Gnome::Art::Point (0.0, 0.0));               
164                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
165                 points->push_back (Gnome::Art::Point (0.0, 13.0));              
166                 points->push_back (Gnome::Art::Point (0.0, 0.0));       
167
168                 shift = 0;
169                 label_offset = 13.0;
170                 break;
171
172         case End:
173                 points = new ArdourCanvas::Points ();
174                 points->push_back (Gnome::Art::Point (6.5, 6.5));
175                 points->push_back (Gnome::Art::Point (13.0, 0.0));              
176                 points->push_back (Gnome::Art::Point (13.0, 13.0));                     
177                 points->push_back (Gnome::Art::Point (6.5, 6.5));               
178                 
179                 shift = 13;
180                 label_offset = 6.0;
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                 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                 break;
226                 
227         }
228
229         frame_position = frame;
230         unit_position = editor.frame_to_unit (frame);
231
232         /* adjust to properly locate the tip */
233
234         unit_position -= shift;
235
236         group = new Group (parent, unit_position, 1.0);
237
238         mark = new Polygon (*group);
239         mark->property_points() = *points;
240         mark->property_fill_color_rgba() = rgba;
241         mark->property_outline_color_rgba() = rgba;
242         mark->property_width_pixels() = 1;
243
244         /* setup name pixbuf sizes */
245         name_font = get_font_for_style (N_("MarkerText"));
246
247         Gtk::Label foo;
248         Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout (X_("Hg")); /* ascender + descender */
249         int width;
250
251         layout->set_font_description (*name_font);
252         Gtkmm2ext::get_ink_pixel_size (layout, width, name_height);
253
254         name_pixbuf = new ArdourCanvas::Pixbuf(*group);
255         name_pixbuf->property_x() = label_offset;
256         name_pixbuf->property_y() = (13 / 2) - (name_height / 2);
257
258         set_name (annotation);
259
260         editor.ZoomChanged.connect (mem_fun (*this, &Marker::reposition));
261         ColorsChanged.connect (mem_fun (*this, &Marker::color_handler));
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
271 }
272
273
274 Marker::~Marker ()
275 {
276         drop_references ();
277
278         /* destroying the parent group destroys its contents, namely any polygons etc. that we added */
279         delete name_pixbuf;
280         delete mark;
281         delete points;
282
283         if (line) {
284                 delete line;
285                 line = 0;
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 y_origin, 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() = y_origin;
314                 line->property_x2() = unit_position + shift;
315                 line->property_y2() = y_origin + 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::color_handler ()
348 {
349         set_name (_annotation);
350 }
351
352 void
353 Marker::set_name (const string& new_name)
354 {
355         int name_width = pixel_width (new_name, *name_font) + 2;
356
357         _annotation = new_name;
358         name_pixbuf->property_pixbuf() = pixbuf_from_ustring(new_name, name_font, 
359                                                              ARDOUR_UI::config()->canvasvar_MarkerLabel.get(), 
360                                                              name_width, name_height);
361
362         if (_type == End || _type == LoopEnd || _type == PunchOut) {
363                 name_pixbuf->property_x() = - (name_width);
364         }
365 }
366
367 void
368 Marker::set_position (nframes_t frame)
369 {
370         double new_unit_position = editor.frame_to_unit (frame);
371         new_unit_position -= shift;
372         group->move (new_unit_position - unit_position, 0.0);
373         frame_position = frame;
374         unit_position = new_unit_position;
375
376         if (line) {
377                 line->property_x1() = unit_position + shift;
378                 line->property_x2() = unit_position + shift;
379         }
380 }
381
382 void
383 Marker::reposition ()
384 {
385         set_position (frame_position);
386 }       
387
388 void
389 Marker::show ()
390 {
391         group->show();
392 }
393
394 void
395 Marker::hide ()
396 {
397         group->hide();
398 }
399
400 void
401 Marker::set_color_rgba (uint32_t color)
402 {
403         mark->property_fill_color_rgba() = color;
404         mark->property_outline_color_rgba() = color;
405 }
406
407 /***********************************************************************/
408
409 TempoMarker::TempoMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
410                           ARDOUR::TempoSection& temp)
411         : Marker (editor, parent, rgba, text, Tempo, 0, false),
412           _tempo (temp)
413 {
414         set_position (_tempo.frame());
415         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_tempo_marker_event), mark, this));
416 }
417
418 TempoMarker::~TempoMarker ()
419 {
420 }
421
422 /***********************************************************************/
423
424 MeterMarker::MeterMarker (PublicEditor& editor, ArdourCanvas::Group& parent, guint32 rgba, const string& text, 
425                           ARDOUR::MeterSection& m) 
426         : Marker (editor, parent, rgba, text, Meter, 0, false),
427           _meter (m)
428 {
429         set_position (_meter.frame());
430         group->signal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_meter_marker_event), mark, this));
431 }
432
433 MeterMarker::~MeterMarker ()
434 {
435 }
436