fix up "other" fade line colors in xfades, and switch to using canvas var "CrossfadeL...
[ardour.git] / gtk2_ardour / imageframe_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
24 #include <gtkmm2ext/gtk_ui.h>
25
26 #include "imageframe_time_axis_view.h"
27 #include "imageframe_time_axis_group.h"
28 #include "imageframe_view.h"
29 #include "imageframe_time_axis.h"
30 #include "region_selection.h"
31 #include "public_editor.h"
32 #include "rgb_macros.h"
33 #include "gui_thread.h"
34 #include "ardour_ui.h"
35
36 #include "i18n.h"
37
38 using namespace ARDOUR ;
39 using namespace Editing;
40
41 //---------------------------------------------------------------------------------------//
42 // Constructor / Desctructor
43
44 /**
45  * Constructs a new ImageFrameTimeAxisView.
46  *
47  * @param ifta the parent ImageFrameTimeAxis of this view helper
48  */
49 ImageFrameTimeAxisView::ImageFrameTimeAxisView (ImageFrameTimeAxis& tv)
50         : _trackview (tv),
51           canvas_group (*_trackview.canvas_display),
52           canvas_rect (canvas_group, 0.0, 0.0, 1000000.0, tv.current_height())
53 {
54         region_color = _trackview.color() ;
55         stream_base_color = ARDOUR_UI::config()->get_canvasvar_ImageTrack() ;
56
57         canvas_rect.property_outline_color_rgba() = ARDOUR_UI::config()->get_canvasvar_ImageTrack();
58         canvas_rect.property_fill_color_rgba() = stream_base_color;
59
60         canvas_rect.signal_event().connect (sigc::bind (sigc::mem_fun (_trackview.editor, &PublicEditor::canvas_imageframe_view_event), (ArdourCanvas::Item*) &canvas_rect, &tv));
61
62         _samples_per_pixel = _trackview.editor.get_current_zoom() ;
63
64         _trackview.editor.ZoomChanged.connect (sigc::mem_fun(*this, &ImageFrameTimeAxisView::reset_samples_per_pixel)) ;
65
66         selected_imageframe_group = 0 ;
67         selected_imageframe_view = 0 ;
68
69         ImageFrameTimeAxisGroup::CatchDeletion.connect (*this, boost::bind (&ImageFrameTimeAxisView::remove_imageframe_group, this, _1), gui_context());
70 }
71
72 /**
73  * Destructor
74  * Responsible for destroying all items tat may have been added to this time axis
75  */
76 ImageFrameTimeAxisView::~ImageFrameTimeAxisView()
77 {
78         // Destroy all the ImageFrameGroups that we have
79
80         for(ImageFrameGroupList::iterator iter = imageframe_groups.begin(); iter != imageframe_groups.end(); ++iter)
81         {
82                 ImageFrameTimeAxisGroup* iftag = (*iter) ;
83
84                 ImageFrameGroupList::iterator next = iter ;
85                 next++ ;
86
87                 // remove the front element
88                 imageframe_groups.erase(iter) ;
89
90                 delete iftag ;
91                 iftag = 0 ;
92
93                 iter = next ;
94         }
95
96 }
97
98
99 //---------------------------------------------------------------------------------------//
100 // ui methods & data
101
102 /**
103  * Sets the height of the time axis view and the item upon it
104  *
105  * @param height the new height
106  */
107 int
108 ImageFrameTimeAxisView::set_height (gdouble h)
109 {
110         /* limit the values to something sane-ish */
111         if (h < 10.0 || h > 1000.0) {
112                 return(-1) ;
113         }
114
115         canvas_rect.property_y2() = h ;
116
117
118         for(ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); ++citer)
119         {
120                 (*citer)->set_item_heights(h) ;
121         }
122
123         return(0) ;
124 }
125
126 /**
127  * Sets the position of this view helper on the canvas
128  *
129  * @param x the x position upon the canvas
130  * @param y the y position npon the canvas
131  */
132 int
133 ImageFrameTimeAxisView::set_position (gdouble x, gdouble y)
134
135 {
136         canvas_group.property_x() = x;
137         canvas_group.property_y() = y;
138
139         return 0;
140 }
141
142 /**
143  * Sets the current samples per unit.
144  * this method tells each item upon the time axis of the change
145  *
146  * @param spu the new samples per canvas unit value
147  */
148 int
149 ImageFrameTimeAxisView::set_samples_per_pixel (double fpp)
150 {
151         if (fpp < 1.0) {
152                 return -1;
153         }
154
155         _samples_per_pixel = fpp;
156
157         for (ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); ++citer) {
158                 (*citer)->set_item_samples_per_pixels (fpp);
159         }
160
161         return 0;
162 }
163
164 /**
165  * Sets the color of the items contained uopn this view helper
166  *
167  * @param color the new base color
168  */
169 void
170 ImageFrameTimeAxisView::apply_color(Gdk::Color& color)
171 {
172         region_color = color ;
173         for(ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); citer++)
174         {
175                 (*citer)->apply_item_color(region_color) ;
176         }
177 }
178
179
180 /**
181  * convenience method to re-get the samples per unit and tell items upon this view
182  *
183  */
184 void
185 ImageFrameTimeAxisView::reset_samples_per_pixel ()
186 {
187         set_samples_per_pixel (_trackview.editor.get_current_zoom());
188 }
189
190
191 //---------------------------------------------------------------------------------------//
192 // Child ImageFrameTimeAxisGroup Accessors/Mutators
193
194 /**
195  * Adds an ImageFrameTimeAxisGroup to the list of items upon this time axis view helper
196  * the new ImageFrameTimeAxisGroup is returned
197  *
198  * @param group_id the unique id of the new group
199  * @param src the identity of the object that initiated the change
200  */
201 ImageFrameTimeAxisGroup*
202 ImageFrameTimeAxisView::add_imageframe_group(std::string group_id, void* src)
203 {
204         ImageFrameTimeAxisGroup* iftag = 0 ;
205
206         //check that there is not already a group with that id
207         if(get_named_imageframe_group(group_id) != 0)
208         {
209                 // iftag = 0 ;
210         }
211         else
212         {
213                 iftag = new ImageFrameTimeAxisGroup(*this, group_id) ;
214                 imageframe_groups.push_front(iftag) ;
215                 ImageFrameGroupAdded(iftag, src) ; /* EMIT_SIGNAL */
216         }
217
218         return(iftag) ;
219 }
220
221 /**
222  * Returns the named ImageFrameTimeAxisGroup or 0 if the named group does not exist on this view helper
223  *
224  * @param group_id the unique id of the group to search for
225  * @return the named ImageFrameTimeAxisGroup, or 0 if it is not held upon this view
226  */
227 ImageFrameTimeAxisGroup*
228 ImageFrameTimeAxisView::get_named_imageframe_group(std::string group_id)
229 {
230         ImageFrameTimeAxisGroup* iftag =  0 ;
231
232         for(ImageFrameGroupList::iterator i = imageframe_groups.begin(); i != imageframe_groups.end(); ++i)
233         {
234                 if (((ImageFrameTimeAxisGroup*)*i)->get_group_name() == group_id)
235                 {
236                         iftag = ((ImageFrameTimeAxisGroup*)*i) ;
237                         break ;
238                 }
239         }
240
241         return(iftag) ;
242 }
243
244
245 /**
246  * Removes and returns the named ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroup held by this view helper
247  *
248  * @param group_id the ImageFrameTimeAxisGroup unique id to remove
249  * @param src the identity of the object that initiated the change
250  * @see add_imageframe_group
251  */
252 ImageFrameTimeAxisGroup*
253 ImageFrameTimeAxisView::remove_named_imageframe_group(std::string group_id, void* src)
254 {
255         ImageFrameTimeAxisGroup* removed = 0 ;
256
257         for(ImageFrameGroupList::iterator iter = imageframe_groups.begin(); iter != imageframe_groups.end(); ++iter)
258         {
259                 if(((ImageFrameTimeAxisGroup*)*iter)->get_group_name() == group_id)
260                 {
261                         removed = (*iter) ;
262                         imageframe_groups.erase(iter) ;
263
264                         if(removed == selected_imageframe_group)
265                         {
266                                 selected_imageframe_group = 0 ;
267                         }
268
269                          ImageFrameGroupRemoved(removed->get_group_name(), src) ; /* EMIT_SIGNAL */
270
271                         // break from the for loop
272                         break ;
273                 }
274                 iter++ ;
275         }
276
277         return(removed) ;
278 }
279
280
281 /**
282  * Removes the specified ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroups upon this TimeAxis.
283  *
284  * @param iftag the ImageFrameView to remove
285  */
286 void
287 ImageFrameTimeAxisView::remove_imageframe_group(ImageFrameTimeAxisGroup* iftag, void* src)
288 {
289         ENSURE_GUI_THREAD (*this, &ImageFrameTimeAxisView::remove_imageframe_group, iftag, src)
290
291         ImageFrameGroupList::iterator i;
292         if((i = find (imageframe_groups.begin(), imageframe_groups.end(), iftag)) != imageframe_groups.end())
293         {
294                 imageframe_groups.erase(i) ;
295
296                  ImageFrameGroupRemoved(iftag->get_group_name(), src) ; /* EMIT_SIGNAL */
297         }
298 }
299
300
301
302
303 //---------------------------------------------------------------------------------------//
304 // Selected group methods
305
306 /**
307  * Sets the currently selected group upon this time axis
308  *
309  * @param ifv the item to set selected
310  */
311 void
312 ImageFrameTimeAxisView::set_selected_imageframe_group(ImageFrameTimeAxisGroup* iftag)
313 {
314         if(selected_imageframe_group)
315         {
316                 selected_imageframe_group->set_selected(false) ;
317         }
318
319         selected_imageframe_group = iftag ;
320         selected_imageframe_group->set_selected(true) ;
321 }
322
323 /**
324  * Clears the currently selected image frame group unpo this time axis
325  *
326 */
327 void
328 ImageFrameTimeAxisView::clear_selected_imageframe_group()
329 {
330         if(selected_imageframe_group)
331         {
332                 selected_imageframe_group->set_selected(false) ;
333         }
334         selected_imageframe_group = 0 ;
335 }
336
337 /**
338  * Returns the currently selected group upon this time axis
339  *
340  * @return the currently selected group upon this time axis
341  */
342 ImageFrameTimeAxisGroup*
343 ImageFrameTimeAxisView::get_selected_imageframe_group() const
344 {
345         return(selected_imageframe_group) ;
346 }
347
348 //---------------------------------------------------------------------------------------//
349 // Selected item methods
350
351 /**
352  * Sets the currently selected imag frame view item
353  *
354  * @param iftag the group the selected item is part
355  * @param ifv the selected item
356  */
357 void
358 ImageFrameTimeAxisView::set_selected_imageframe_view(ImageFrameTimeAxisGroup* iftag, ImageFrameView* ifv)
359 {
360         set_selected_imageframe_group(iftag) ;
361
362         if(selected_imageframe_view)
363         {
364                 selected_imageframe_view->set_selected(false) ;
365         }
366
367         selected_imageframe_view = ifv ;
368         selected_imageframe_view->set_selected(true) ;
369 }
370
371 /**
372  * Clears the currently selected image frame view item
373  *
374  */
375 void
376 ImageFrameTimeAxisView::clear_selected_imageframe_item(bool clear_group)
377 {
378         if(clear_group)
379         {
380                 clear_selected_imageframe_group() ;
381         }
382
383         if(selected_imageframe_view)
384         {
385                 selected_imageframe_view->set_selected(false) ;
386         }
387         selected_imageframe_view = 0 ;
388 }
389
390 /**
391  * Returns the currently selected image frame view item upon this time axis
392  *
393  * @return the currently selected image frame view item
394  */
395 ImageFrameView*
396 ImageFrameTimeAxisView::get_selected_imageframe_view() const
397 {
398         return(selected_imageframe_view) ;
399 }
400
401
402
403
404 void
405 ImageFrameTimeAxisView::set_imageframe_duration_sec(double sec)
406 {
407         if (selected_imageframe_group && selected_imageframe_view) {
408                 selected_imageframe_view->set_duration ((sec * _trackview.editor.session()->frame_rate()), this);
409         }
410 }
411
412
413
414 /**
415  * Removes the currently selected ImageFrame view item
416  *
417  * @param src the identity of the object that initiated the change
418  * @see add_imageframe_group
419  */
420 void
421 ImageFrameTimeAxisView::remove_selected_imageframe_item(void* src)
422 {
423         if(selected_imageframe_group && selected_imageframe_view)
424         {
425                 ImageFrameView* temp_item = selected_imageframe_view ;
426                 selected_imageframe_group->remove_imageframe_item(temp_item, src) ;
427
428                 // XXX although we have removed the item from the group, we need the group id still set within the
429                 //     item as the remove method requires this data when telling others about the deletion
430                 //     to fully specify the item we need the track, group and item id
431                 selected_imageframe_view->remove_this_item(src) ;
432                 clear_selected_imageframe_item(false) ;
433         }
434 }
435