Merged with trunk R1141
[ardour.git] / gtk2_ardour / marker_time_axis_view.cc
1 /*
2     Copyright (C) 2003 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     $Id$
19 */
20
21 #include <algorithm>
22
23 #include <gtkmm.h>
24 #include <gtkmm2ext/gtk_ui.h>
25
26 #include "marker_time_axis_view.h"
27 #include "marker_time_axis.h"
28 #include "marker_view.h"
29 #include "imageframe_view.h"
30 #include "imageframe_time_axis.h"
31 #include "canvas-simplerect.h"
32 #include "public_editor.h"
33 #include "rgb_macros.h"
34 #include "gui_thread.h"
35
36 #include "i18n.h"
37
38 using namespace ARDOUR ;
39 using namespace Editing;
40
41 //---------------------------------------------------------------------------------------//
42 // Constructor / Desctructor
43                 
44 /**
45  * Construct a new MarkerTimeAxisView helper time axis helper
46  *
47  * @param mta the TimeAxsiView that this objbect is the helper for
48  */
49 MarkerTimeAxisView::MarkerTimeAxisView(MarkerTimeAxis& tv)
50         : _trackview (tv)
51 {
52         region_color = _trackview.color();
53         stream_base_color = color_map[cMarkerTrackBase];
54
55         canvas_group = new ArdourCanvas::Group (*_trackview.canvas_display);
56
57         canvas_rect =  new ArdourCanvas::SimpleRect (*canvas_group);
58         canvas_rect->property_x1() = 0.0;
59         canvas_rect->property_y1() = 0.0;
60         canvas_rect->property_x2() = max_frames;
61         canvas_rect->property_y2() = (double)20;
62         canvas_rect->property_outline_color_rgba() = color_map[cMarkerTrackOutline];
63         canvas_rect->property_fill_color_rgba() = stream_base_color;
64                    
65         canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_marker_time_axis_view_event), canvas_rect, &_trackview));
66
67         _samples_per_unit = _trackview.editor.get_current_zoom() ;
68
69         _trackview.editor.ZoomChanged.connect (mem_fun(*this, &MarkerTimeAxisView::reset_samples_per_unit));
70 }
71
72 /**
73  * Destructor
74  * Reposinsibly for destroying all marker items that may have been added to this time axis view
75  *
76  */
77 MarkerTimeAxisView::~MarkerTimeAxisView()
78 {
79         // destroy everything upon this view
80         for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
81         {
82                 MarkerView* mv = (*iter) ;
83                 
84                 MarkerViewList::iterator next = iter ;
85                 next++ ;
86                 marker_view_list.erase(iter) ;
87
88                 delete mv ;
89                 mv = 0 ;
90                 
91                 iter = next ;
92         }
93         
94         if(canvas_rect)
95         {
96                 delete canvas_rect;
97                 canvas_rect = 0 ;
98         }
99         
100         if(canvas_group)
101         {
102                 delete canvas_group;
103                 canvas_group = 0 ;
104         }
105 }
106
107
108 //---------------------------------------------------------------------------------------//
109 // ui methods & data
110
111 /**
112  * Sets the height of the time axis view and the item upon it
113  *
114  * @param height the new height
115  */
116 int
117 MarkerTimeAxisView::set_height(gdouble h)
118 {
119         if (h < 10.0 || h > 1000.0)
120         {
121                 return -1 ;
122         }
123         
124         canvas_rect->property_y2() = h;
125
126         for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
127         {
128                 (*i)->set_height(h) ;
129         }
130
131         return 0;
132 }
133
134 /**
135  * Sets the position of this view helper on the canvas
136  *
137  * @param x the x position upon the canvas
138  * @param y the y position upon the canvas
139  */
140 int
141 MarkerTimeAxisView::set_position(gdouble x, gdouble y)
142 {
143         canvas_group->property_x() = x;
144         canvas_group->property_y() = y;
145         return 0;
146 }
147
148 /**
149  * Sets the current samples per unit.
150  * this method tells each item upon the time axis of the change
151  * 
152  * @param spu the new samples per canvas unit value
153  */
154 int
155 MarkerTimeAxisView::set_samples_per_unit(gdouble spp)
156 {
157         if(spp < 1.0) {
158                 return -1 ;
159         }
160         
161         _samples_per_unit = spp ;
162
163         for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
164         {
165                 (*i)->set_samples_per_unit(spp) ;
166         }
167         return(0) ;
168 }
169
170 /**
171  * Sets the color of the items contained upon this view helper
172  *
173  * @param color the new base color
174  */
175 void
176 MarkerTimeAxisView::apply_color(Gdk::Color& color)
177 {
178         region_color = color;
179
180         for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); i++)
181         {
182                 (*i)->set_color (region_color) ;
183         }
184 }
185
186
187 //---------------------------------------------------------------------------------------//
188 // Child MarkerView Accessors/Mutators
189                 
190 /**
191  * Adds a marker view to the list of items upon this time axis view helper
192  * the new MarkerView is returned
193  *
194  * @param ifv the ImageFrameView that the new item is marking up
195  * @param mark_text the text to be displayed uopn the new marker item
196  * @param mark_id the unique id of the new item
197  * @param start the position the new item should be placed upon the time line
198  * @param duration the duration the new item should be placed upon the timeline
199  * @param src the identity of the object that initiated the change
200  */      
201 MarkerView*
202 MarkerTimeAxisView::add_marker_view(ImageFrameView* ifv, std::string mark_type, std::string mark_id, nframes_t start, nframes_t dur, void* src)
203 {
204         if(ifv->has_marker_view_item(mark_id))
205         {
206                 return(0) ;
207         }
208         
209         MarkerView* mv = new MarkerView(canvas_group,
210                  &_trackview,
211                  ifv,
212                  _trackview.editor.get_current_zoom(),
213                  region_color,
214                  mark_type,
215                  mark_id,
216                  start,
217                  dur) ;
218         
219         ifv->add_marker_view_item(mv, src) ;
220         marker_view_list.push_front(mv) ;
221         
222         mv->GoingAway.connect(bind (mem_fun(*this,&MarkerTimeAxisView::remove_marker_view), (void*)this)) ;
223         
224          MarkerViewAdded(mv,src) ; /* EMIT_SIGNAL */
225         
226         return(mv) ;
227 }
228
229 /**
230  * Returns the named MarkerView or 0 if the named marker does not exist
231  *
232  * @param item_id the unique id of the item to search for
233  * @return the named MarkerView, or 0 if it is not held upon this view
234  */
235 MarkerView*
236 MarkerTimeAxisView::get_named_marker_view(std::string item_id)
237 {
238         MarkerView* mv =  0 ;
239         
240         for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
241         {
242                 if(((MarkerView*)*i)->get_item_name() == item_id)
243                 {
244                         mv = ((MarkerView*)*i) ;
245                         break ;
246                 }
247         }
248         return(mv) ;
249 }
250
251 /**
252  * Removes the currently selected MarverView
253  * Note that this method actually destroys the MarkerView too.
254  * We assume that since we own the object, we are allowed to do this
255  *
256  * @param src the identity of the object that initiated the change
257  * @see add_marker_view
258  */
259 void
260 MarkerTimeAxisView::remove_selected_marker_view(void* src)
261 {
262         std::string removed ;
263         
264         if (selected_time_axis_item)
265         {
266                 MarkerViewList::iterator i ;
267                 if((i = find (marker_view_list.begin(), marker_view_list.end(), selected_time_axis_item)) != marker_view_list.end())
268                 {
269                         marker_view_list.erase(i) ;
270                         
271                          MarkerViewRemoved(selected_time_axis_item->get_item_name(),src) ; /* EMIT_SIGNAL */
272
273                         delete(selected_time_axis_item) ;
274                         selected_time_axis_item = 0 ;
275                 }
276         }
277         else
278         {
279                 //No selected marker view
280         }
281 }
282
283 /**
284  * Removes and returns the named MarkerView from the list of MarkerView held by this view helper
285  *
286  * @param item_id the MarkerView unique id to remove
287  * @param src the identity of the object that initiated the change
288  * @see add_marker_view
289  */
290 MarkerView*
291 MarkerTimeAxisView::remove_named_marker_view(std::string item_id, void* src)
292 {
293         MarkerView* mv = 0 ;
294         
295         MarkerViewList::iterator i = marker_view_list.begin() ;
296         
297         for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
298         {
299                 if(((MarkerView*)*i)->get_item_name() == item_id)
300                 {
301                         mv = ((MarkerView*)*i) ;
302                         marker_view_list.erase(i) ;
303                                                 
304                          MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
305                         
306                         // break from the for loop
307                         break;
308                 }
309                 i++ ;
310         }
311         
312         return(mv) ;
313 }
314
315 /**
316  * Removes mv from the list of MarkerView upon this TimeAxis
317  *
318  * @param mv the MarkerView to remove
319  * @param src the identity of the object that initiated the change
320  */
321 void
322 MarkerTimeAxisView::remove_marker_view(MarkerView* mv, void* src)
323 {
324         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MarkerTimeAxisView::remove_marker_view), mv, src));
325         
326         MarkerViewList::iterator i;
327
328         if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) {
329                 marker_view_list.erase(i) ;
330                 
331                 // Assume this remove happened locally, else use remove_named_marker_time_axis
332                 // let listeners know that the named MarkerTimeAxis has been removed
333                  MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
334         }
335 }
336
337
338 /**
339  * Sets the duration of the selected MarkerView to the specified number of seconds
340  *
341  * @param sec the duration to set the MArkerView to, in seconds
342  */
343 void
344 MarkerTimeAxisView::set_marker_duration_sec(double sec)
345 {
346   if(get_selected_time_axis_item() != 0)
347   {
348           get_selected_time_axis_item()->set_duration((nframes_t) (sec * _trackview.editor.current_session()->frame_rate()), this) ;
349   }
350 }
351
352
353 //---------------------------------------------------------------------------------------//
354 // Selected item methods
355
356 /**
357  * Sets the currently selected item upon this time axis
358  *
359  * @param mv the item to set selected
360  */
361 void
362 MarkerTimeAxisView::set_selected_time_axis_item(MarkerView* mv)
363 {
364         selected_time_axis_item = mv ;
365 }
366
367 /**
368  * Clears any selected item upon this time axis
369  *
370  */
371 void
372 MarkerTimeAxisView::clear_selected_time_axis_item()
373 {
374         selected_time_axis_item = 0 ;
375 }
376                 
377 /**
378  * Returnsthe currently selected item upon this time axis
379  *
380  * @return the currently selected item pon this time axis
381  */
382 MarkerView*
383 MarkerTimeAxisView::get_selected_time_axis_item()
384 {
385         return(selected_time_axis_item) ;
386 }
387
388
389
390
391 /**
392  * convenience method to re-get the samples per unit and tell items upon this view
393  *
394  */
395 void
396 MarkerTimeAxisView::reset_samples_per_unit ()
397 {
398         set_samples_per_unit(_trackview.editor.get_current_zoom()) ;
399 }