tweak event/leave event delivery so that it applies to items being deleted as well...
[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 "public_editor.h"
31 #include "rgb_macros.h"
32 #include "gui_thread.h"
33 #include "ardour_ui.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 = ARDOUR_UI::config()->get_canvasvar_MarkerTrack();
53
54         canvas_group = new ArdourCanvas::Group (*_trackview.canvas_display);
55
56         canvas_rect =  new ArdourCanvas::Rectangle (*canvas_group);
57         canvas_rect->property_x1() = 0.0;
58         canvas_rect->property_y1() = 0.0;
59         canvas_rect->property_x2() = max_framepos;
60         canvas_rect->property_y2() = (double)20;
61         canvas_rect->property_outline_color_rgba() = ARDOUR_UI::config()->get_canvasvar_MarkerTrack();
62         canvas_rect->property_fill_color_rgba() = stream_base_color;
63
64         canvas_rect->signal_event().connect (sigc::bind (sigc::mem_fun (_trackview.editor, &PublicEditor::canvas_marker_time_axis_view_event), canvas_rect, &_trackview));
65
66         _samples_per_pixel = _trackview.editor.get_current_zoom() ;
67
68         _trackview.editor.ZoomChanged.connect (sigc::mem_fun(*this, &MarkerTimeAxisView::reset_samples_per_pixel));
69         MarkerView::CatchDeletion.connect (*this, boost::bind (&MarkerTimeAxisView::remove_marker_view, this, _1), gui_context());
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         delete canvas_rect;
95         canvas_rect = 0 ;
96
97         delete canvas_group;
98         canvas_group = 0 ;
99 }
100
101
102 //---------------------------------------------------------------------------------------//
103 // ui methods & data
104
105 /**
106  * Sets the height of the time axis view and the item upon it
107  *
108  * @param height the new height
109  */
110 int
111 MarkerTimeAxisView::set_height(gdouble h)
112 {
113         if (h < 10.0 || h > 1000.0) {
114                 return -1;
115         }
116
117         canvas_rect->property_y2() = h;
118
119         for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) {
120                 (*i)->set_y_position_and_height(0, 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 upon the canvas
131  */
132 int
133 MarkerTimeAxisView::set_position(gdouble x, gdouble y)
134 {
135         canvas_group->property_x() = x;
136         canvas_group->property_y() = y;
137         return 0;
138 }
139
140 /**
141  * Sets the current frames per pixel.
142  * this method tells each item upon the time axis of the change
143  *
144  * @param fpp the new frames per pixel value
145  */
146 int
147 MarkerTimeAxisView::set_samples_per_pixel (double fpp)
148 {
149         if (spp < 1.0) {
150                 return -1;
151         }
152
153         _samples_per_pixel = fpp;
154
155         for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) {
156                 (*i)->set_samples_per_pixel (spp);
157         }
158         
159         return 0;
160 }
161
162 /**
163  * Sets the color of the items contained upon this view helper
164  *
165  * @param color the new base color
166  */
167 void
168 MarkerTimeAxisView::apply_color(Gdk::Color& color)
169 {
170         region_color = color;
171
172         for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); i++)
173         {
174                 (*i)->set_color (region_color) ;
175         }
176 }
177
178
179 //---------------------------------------------------------------------------------------//
180 // Child MarkerView Accessors/Mutators
181
182 /**
183  * Adds a marker view to the list of items upon this time axis view helper
184  * the new MarkerView is returned
185  *
186  * @param ifv the ImageFrameView that the new item is marking up
187  * @param mark_text the text to be displayed uopn the new marker item
188  * @param mark_id the unique id of the new item
189  * @param start the position the new item should be placed upon the time line
190  * @param duration the duration the new item should be placed upon the timeline
191  * @param src the identity of the object that initiated the change
192  */
193 MarkerView*
194 MarkerTimeAxisView::add_marker_view(ImageFrameView* ifv, std::string mark_type, std::string mark_id, framepos_t start, framecnt_t dur, void* src)
195 {
196         if(ifv->has_marker_view_item(mark_id))
197         {
198                 return(0) ;
199         }
200
201         MarkerView* mv = new MarkerView(canvas_group,
202                  &_trackview,
203                  ifv,
204                  _trackview.editor.get_current_zoom(),
205                  region_color,
206                  mark_type,
207                  mark_id,
208                  start,
209                  dur) ;
210
211         ifv->add_marker_view_item(mv, src) ;
212         marker_view_list.push_front(mv) ;
213
214         MarkerViewAdded(mv,src) ; /* EMIT_SIGNAL */
215
216         return(mv) ;
217 }
218
219 /**
220  * Returns the named MarkerView or 0 if the named marker does not exist
221  *
222  * @param item_id the unique id of the item to search for
223  * @return the named MarkerView, or 0 if it is not held upon this view
224  */
225 MarkerView*
226 MarkerTimeAxisView::get_named_marker_view(std::string item_id)
227 {
228         MarkerView* mv =  0 ;
229
230         for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
231         {
232                 if(((MarkerView*)*i)->get_item_name() == item_id)
233                 {
234                         mv = ((MarkerView*)*i) ;
235                         break ;
236                 }
237         }
238         return(mv) ;
239 }
240
241 /**
242  * Removes the currently selected MarverView
243  * Note that this method actually destroys the MarkerView too.
244  * We assume that since we own the object, we are allowed to do this
245  *
246  * @param src the identity of the object that initiated the change
247  * @see add_marker_view
248  */
249 void
250 MarkerTimeAxisView::remove_selected_marker_view(void* src)
251 {
252         std::string removed ;
253
254         if (selected_time_axis_item)
255         {
256                 MarkerViewList::iterator i ;
257                 if((i = find (marker_view_list.begin(), marker_view_list.end(), selected_time_axis_item)) != marker_view_list.end())
258                 {
259                         marker_view_list.erase(i) ;
260
261                          MarkerViewRemoved(selected_time_axis_item->get_item_name(),src) ; /* EMIT_SIGNAL */
262
263                         delete(selected_time_axis_item) ;
264                         selected_time_axis_item = 0 ;
265                 }
266         }
267         else
268         {
269                 //No selected marker view
270         }
271 }
272
273 /**
274  * Removes and returns the named MarkerView from the list of MarkerView held by this view helper
275  *
276  * @param item_id the MarkerView unique id to remove
277  * @param src the identity of the object that initiated the change
278  * @see add_marker_view
279  */
280 MarkerView*
281 MarkerTimeAxisView::remove_named_marker_view(std::string item_id, void* src)
282 {
283         MarkerView* mv = 0 ;
284
285         MarkerViewList::iterator i = marker_view_list.begin() ;
286
287         for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
288         {
289                 if(((MarkerView*)*i)->get_item_name() == item_id)
290                 {
291                         mv = ((MarkerView*)*i) ;
292                         marker_view_list.erase(i) ;
293
294                          MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
295
296                         // break from the for loop
297                         break;
298                 }
299                 i++ ;
300         }
301
302         return(mv) ;
303 }
304
305 /**
306  * Removes mv from the list of MarkerView upon this TimeAxis
307  *
308  * @param mv the MarkerView to remove
309  * @param src the identity of the object that initiated the change
310  */
311 void
312 MarkerTimeAxisView::remove_marker_view (MarkerView* mv)
313 {
314         ENSURE_GUI_THREAD (*this, &MarkerTimeAxisView::remove_marker_view, mv, src)
315
316         MarkerViewList::iterator i;
317
318         if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) {
319                 marker_view_list.erase(i) ;
320
321                 // Assume this remove happened locally, else use remove_named_marker_time_axis
322                 // let listeners know that the named MarkerTimeAxis has been removed
323                  MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
324         }
325 }
326
327 /**
328  * Sets the duration of the selected MarkerView to the specified number of seconds
329  *
330  * @param sec the duration to set the MArkerView to, in seconds
331  */
332 void
333 MarkerTimeAxisView::set_marker_duration_sec(double sec)
334 {
335   if(get_selected_time_axis_item() != 0)
336   {
337           get_selected_time_axis_item()->set_duration((sec * _trackview.editor.session()->frame_rate()), this);
338   }
339 }
340
341
342 //---------------------------------------------------------------------------------------//
343 // Selected item methods
344
345 /**
346  * Sets the currently selected item upon this time axis
347  *
348  * @param mv the item to set selected
349  */
350 void
351 MarkerTimeAxisView::set_selected_time_axis_item(MarkerView* mv)
352 {
353         selected_time_axis_item = mv ;
354 }
355
356 /**
357  * Clears any selected item upon this time axis
358  *
359  */
360 void
361 MarkerTimeAxisView::clear_selected_time_axis_item()
362 {
363         selected_time_axis_item = 0 ;
364 }
365
366 /**
367  * Returnsthe currently selected item upon this time axis
368  *
369  * @return the currently selected item pon this time axis
370  */
371 MarkerView*
372 MarkerTimeAxisView::get_selected_time_axis_item()
373 {
374         return(selected_time_axis_item) ;
375 }
376
377
378
379
380 /**
381  * convenience method to re-get the samples per unit and tell items upon this view
382  *
383  */
384 void
385 MarkerTimeAxisView::reset_samples_per_pixel ()
386 {
387         set_samples_per_pixel (_trackview.editor.get_current_zoom());
388 }