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