fix keyboard event handling for host-provided plugin GUIs
[ardour2.git] / gtk2_ardour / imageframe_time_axis_group.cc
blob5dc76978b06dec938f1be6232f0e3ce6f2d10f9d
1 /*
2 Copyright (C) 2003 Paul Davis
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.
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.
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.
20 #include <algorithm>
22 #include <gtkmm.h>
23 #include <gtkmm2ext/gtk_ui.h>
25 #include "imageframe_time_axis_group.h"
26 #include "imageframe_time_axis_view.h"
27 #include "imageframe_view.h"
28 #include "imageframe_time_axis.h"
29 #include "canvas-simplerect.h"
30 #include "region_selection.h"
31 #include "public_editor.h"
32 #include "gui_thread.h"
34 #include "i18n.h"
36 using namespace ARDOUR ;
38 //---------------------------------------------------------------------------------------//
39 // Constructor / Desctructor
41 /**
42 * Constructs a new ImageFrameTimeAxisGroup.
44 * @param iftav the parent ImageFrameTimeAxis of this view helper
45 * @param group_id the unique name/id of this group
47 ImageFrameTimeAxisGroup::ImageFrameTimeAxisGroup(ImageFrameTimeAxisView& iftav, const string & group_id)
48 : _view_helper(iftav), _group_id(group_id)
50 selected_imageframe_item = 0 ;
51 is_selected = false ;
54 /**
55 * Destructor
56 * Responsible for destroying any Items that may have been added to this group
59 ImageFrameTimeAxisGroup::~ImageFrameTimeAxisGroup()
61 // Destroy all the ImageFramViews that we have
62 for(ImageFrameViewList::iterator iter = imageframe_views.begin(); iter != imageframe_views.end(); ++iter)
64 ImageFrameView* ifv = *iter ;
66 ImageFrameViewList::iterator next = iter ;
67 next++ ;
69 imageframe_views.erase(iter) ;
71 delete ifv ;
72 ifv = 0 ;
74 iter = next ;
77 GoingAway() ; /* EMIT_SIGNAL */
81 //---------------------------------------------------------------------------------------//
82 // Name/Id Accessors/Mutators
84 /**
85 * Set the name/Id of this group.
87 * @param new_name the new name of this group
88 * @param src the identity of the object that initiated the change
90 void
91 ImageFrameTimeAxisGroup::set_group_name(const string & new_name, void* src)
93 if(_group_id != new_name)
95 std::string temp_name = _group_id ;
96 _group_id = new_name ;
97 NameChanged(_group_id, temp_name, src) ; /* EMIT_SIGNAL */
102 * Returns the id of this group
103 * The group id must be unique upon a time axis
105 * @return the id of this group
107 std::string
108 ImageFrameTimeAxisGroup::get_group_name() const
110 return(_group_id) ;
114 //---------------------------------------------------------------------------------------//
115 // ui methods & data
118 * Sets the height of the time axis view and the item upon it
120 * @param height the new height
123 ImageFrameTimeAxisGroup::set_item_heights(gdouble h)
125 /* limit the values to something sane-ish */
126 if (h < 10.0 || h > 1000.0)
128 return(-1) ;
131 // set the heights of all the imaeg frame views within the group
132 for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); ++citer)
134 (*citer)->set_height(h) ;
137 return(0) ;
141 * Sets the current samples per unit.
142 * this method tells each item upon the time axis of the change
144 * @param spu the new samples per canvas unit value
146 int
147 ImageFrameTimeAxisGroup::set_item_samples_per_units(gdouble spp)
149 if(spp < 1.0)
151 return(-1) ;
154 for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); ++citer)
156 (*citer)->set_samples_per_unit(spp) ;
159 return(0) ;
163 * Sets the color of the items contained uopn this view helper
165 * @param color the new base color
167 void
168 ImageFrameTimeAxisGroup::apply_item_color(Gdk::Color& color)
170 region_color = color ;
171 for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); citer++)
173 (*citer)->set_color (region_color) ;
179 //---------------------------------------------------------------------------------------//
180 // child ImageFrameView methods
183 * Adds an ImageFrameView to the list of items upon this time axis view helper
184 * the new ImageFrameView is returned
186 * @param item_id the unique id of the new item
187 * @param image_id the id/name of the image data we are usin
188 * @param start the position the new item should be placed upon the time line
189 * @param duration the duration the new item should be placed upon the timeline
190 * @param rgb_data the rgb data of the image
191 * @param width the original image width of the rgb_data (not the size to display)
192 * @param height the irigianl height of the rgb_data
193 * @param num_channels the number of channles within the rgb_data
194 * @param src the identity of the object that initiated the change
196 ImageFrameView*
197 ImageFrameTimeAxisGroup::add_imageframe_item(const string & frame_id, nframes_t start, nframes_t duration, unsigned char* rgb_data, uint32_t width, uint32_t height, uint32_t num_channels, void* src)
199 ImageFrameView* ifv = 0 ;
201 //check that there is not already an imageframe with that id
202 if(get_named_imageframe_item(frame_id) == 0)
204 ifv = new ImageFrameView(frame_id,
205 _view_helper.canvas_item()->property_parent(),
206 &(_view_helper.trackview()),
207 this,
208 _view_helper.trackview().editor.get_current_zoom(),
209 region_color,
210 start,
211 duration,
212 rgb_data,
213 width,
214 height,
215 num_channels) ;
217 imageframe_views.push_front(ifv) ;
219 ifv->GoingAway.connect(bind(mem_fun(*this,&ImageFrameTimeAxisGroup::remove_imageframe_item), (void*)this)) ;
221 ImageFrameAdded(ifv, src) ; /* EMIT_SIGNAL */
224 return(ifv) ;
229 * Returns the named ImageFrameView or 0 if the named view does not exist on this view helper
231 * @param item_id the unique id of the item to search for
232 * @return the named ImageFrameView, or 0 if it is not held upon this view
234 ImageFrameView*
235 ImageFrameTimeAxisGroup::get_named_imageframe_item(const string & frame_id)
237 ImageFrameView* ifv = 0 ;
239 for (ImageFrameViewList::const_iterator i = imageframe_views.begin(); i != imageframe_views.end(); ++i)
241 if (((ImageFrameView*)*i)->get_item_name() == frame_id)
243 ifv = ((ImageFrameView*)*i) ;
244 break ;
247 return(ifv) ;
251 * Removes the currently selected ImageFrameView
253 * @param src the identity of the object that initiated the change
254 * @todo need to remoev this, the selected item within group is no longer
255 * used in favour of a time axis selected item
256 * @see add_imageframe_view
258 void
259 ImageFrameTimeAxisGroup::remove_selected_imageframe_item(void* src)
261 std::string frame_id ;
263 if(selected_imageframe_item)
265 ImageFrameViewList::iterator i ;
267 if((i = find(imageframe_views.begin(), imageframe_views.end(), selected_imageframe_item)) != imageframe_views.end())
269 imageframe_views.erase(i) ;
270 frame_id = selected_imageframe_item->get_item_name() ;
272 // note that we delete the item here
273 delete(selected_imageframe_item) ;
274 selected_imageframe_item = 0 ;
276 std::string track_id = _view_helper.trackview().name() ;
277 ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */
280 else
282 //cerr << "No Selected ImageFrame" << endl ;
288 * Removes and returns the named ImageFrameView from the list of ImageFrameViews held by this view helper
290 * @param item_id the ImageFrameView unique id to remove
291 * @param src the identity of the object that initiated the change
292 * @see add_imageframe_view
294 ImageFrameView*
295 ImageFrameTimeAxisGroup::remove_named_imageframe_item(const string & frame_id, void* src)
297 ImageFrameView* removed = 0 ;
299 for(ImageFrameViewList::iterator iter = imageframe_views.begin(); iter != imageframe_views.end(); ++iter)
301 ImageFrameView* tempItem = *iter ;
302 if(tempItem->get_item_name() == frame_id)
304 removed = tempItem ;
305 imageframe_views.erase(iter) ;
307 if (removed == selected_imageframe_item)
309 selected_imageframe_item = 0 ;
312 std::string track_id = _view_helper.trackview().name() ;
313 ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */
315 // break from the for loop
316 break ;
318 iter++ ;
321 return(removed) ;
325 * Removes ifv from the list of ImageFrameViews upon this TimeAxis.
326 * if ifv is not upon this TimeAxis, this method takes no action
328 * @param ifv the ImageFrameView to remove
330 void
331 ImageFrameTimeAxisGroup::remove_imageframe_item(ImageFrameView* ifv, void* src)
333 ENSURE_GUI_THREAD(bind (mem_fun(*this, &ImageFrameTimeAxisGroup::remove_imageframe_item), ifv, src));
335 ImageFrameViewList::iterator i;
336 if((i = find (imageframe_views.begin(), imageframe_views.end(), ifv)) != imageframe_views.end())
338 imageframe_views.erase(i) ;
340 std::string frame_id = ifv->get_item_name() ;
341 std::string track_id = _view_helper.trackview().name() ;
342 ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */
346 //---------------------------------------------------------------------------------------//
347 // Selected group methods
350 * Sets the currently selected item upon this time axis
352 * @param ifv the item to set selected
354 //void
355 //ImageFrameTimeAxisGroup::set_selected_imageframe_item(ImageFrameView* ifv)
357 // if(selected_imageframe_item)
358 // {
359 // selected_imageframe_item->set_selected(false, this) ;
360 // }
362 // selected_imageframe_item = ifv ;
364 // if(!ifv->get_selected())
365 // {
366 // selected_imageframe_item->set_selected(true, this) ;
367 // }
372 * Sets the currently selected item upon this time axis to the named item
374 * @param item_id the name/id of the item to set selected
376 //void
377 //ImageFrameTimeAxisGroup::set_selected_imageframe_item(std::string frame_id)
379 // selected_imageframe_item = get_named_imageframe_item(frame_id) ;
384 * Returns the currently selected item upon this time axis
386 * @return the currently selected item pon this time axis
388 // ImageFrameView*
389 // ImageFrameTimeAxisGroup::get_selected_imageframe_item()
390 // {
391 // return(selected_imageframe_item) ;
392 // }
397 * Returns whether this grou pis currently selected
399 * @returns true if this group is currently selected
401 bool
402 ImageFrameTimeAxisGroup::get_selected() const
404 return(is_selected) ;
409 * Sets he selected state of this group
411 * @param yn set true if this group is selected, false otherwise
413 void
414 ImageFrameTimeAxisGroup::set_selected(bool yn)
416 is_selected = yn ;
421 //---------------------------------------------------------------------------------------//
422 // Handle time axis removal
425 * Handles the Removal of this VisualTimeAxis
426 * This _needs_ to be called to alert others of the removal properly, ie where the source
427 * of the removal came from.
429 * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method
430 * just now to capture the source of the removal
432 * @param src the identity of the object that initiated the change
434 void
435 ImageFrameTimeAxisGroup::remove_this_group(void* src)
438 defer to idle loop, otherwise we'll delete this object
439 while we're still inside this function ...
441 Glib::signal_idle().connect(bind(ptr_fun(&ImageFrameTimeAxisGroup::idle_remove_this_group), this, src));
445 * Callback used to remove this group during the gtk idle loop
446 * This is used to avoid deleting the obejct while inside the remove_this_group
447 * method
449 * @param group the ImageFrameTimeAxisGroup to remove
450 * @param src the identity of the object that initiated the change
452 gint
453 ImageFrameTimeAxisGroup::idle_remove_this_group(ImageFrameTimeAxisGroup* group, void* src)
455 delete group ;
456 group = 0 ;
457 group->GroupRemoved(group->get_group_name(), src) ; /* EMIT_SIGNAL */
458 return(false) ;