402f2ac479a9a9e45b9ccd5b0728449e5bed8edc
[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 #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  * 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 = ARDOUR_UI::config()->canvasvar_MarkerTrack.get();
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() = ARDOUR_UI::config()->canvasvar_MarkerTrack.get();
63         canvas_rect->property_fill_color_rgba() = stream_base_color;
64
65         canvas_rect->signal_event().connect (sigc::bind (sigc::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 (sigc::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         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 samples per unit.
142  * this method tells each item upon the time axis of the change
143  *
144  * @param spu the new samples per canvas unit value
145  */
146 int
147 MarkerTimeAxisView::set_samples_per_unit(gdouble spp)
148 {
149         if(spp < 1.0) {
150                 return -1 ;
151         }
152
153         _samples_per_unit = spp ;
154
155         for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
156         {
157                 (*i)->set_samples_per_unit(spp) ;
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, nframes_t start, nframes_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         scoped_connect (mv->GoingAway, boost::bind (&MarkerTimeAxisView::remove_marker_view, this, (void*)this));
215
216          MarkerViewAdded(mv,src) ; /* EMIT_SIGNAL */
217
218         return(mv) ;
219 }
220
221 /**
222  * Returns the named MarkerView or 0 if the named marker does not exist
223  *
224  * @param item_id the unique id of the item to search for
225  * @return the named MarkerView, or 0 if it is not held upon this view
226  */
227 MarkerView*
228 MarkerTimeAxisView::get_named_marker_view(std::string item_id)
229 {
230         MarkerView* mv =  0 ;
231
232         for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
233         {
234                 if(((MarkerView*)*i)->get_item_name() == item_id)
235                 {
236                         mv = ((MarkerView*)*i) ;
237                         break ;
238                 }
239         }
240         return(mv) ;
241 }
242
243 /**
244  * Removes the currently selected MarverView
245  * Note that this method actually destroys the MarkerView too.
246  * We assume that since we own the object, we are allowed to do this
247  *
248  * @param src the identity of the object that initiated the change
249  * @see add_marker_view
250  */
251 void
252 MarkerTimeAxisView::remove_selected_marker_view(void* src)
253 {
254         std::string removed ;
255
256         if (selected_time_axis_item)
257         {
258                 MarkerViewList::iterator i ;
259                 if((i = find (marker_view_list.begin(), marker_view_list.end(), selected_time_axis_item)) != marker_view_list.end())
260                 {
261                         marker_view_list.erase(i) ;
262
263                          MarkerViewRemoved(selected_time_axis_item->get_item_name(),src) ; /* EMIT_SIGNAL */
264
265                         delete(selected_time_axis_item) ;
266                         selected_time_axis_item = 0 ;
267                 }
268         }
269         else
270         {
271                 //No selected marker view
272         }
273 }
274
275 /**
276  * Removes and returns the named MarkerView from the list of MarkerView held by this view helper
277  *
278  * @param item_id the MarkerView unique id to remove
279  * @param src the identity of the object that initiated the change
280  * @see add_marker_view
281  */
282 MarkerView*
283 MarkerTimeAxisView::remove_named_marker_view(std::string item_id, void* src)
284 {
285         MarkerView* mv = 0 ;
286
287         MarkerViewList::iterator i = marker_view_list.begin() ;
288
289         for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
290         {
291                 if(((MarkerView*)*i)->get_item_name() == item_id)
292                 {
293                         mv = ((MarkerView*)*i) ;
294                         marker_view_list.erase(i) ;
295
296                          MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
297
298                         // break from the for loop
299                         break;
300                 }
301                 i++ ;
302         }
303
304         return(mv) ;
305 }
306
307 /**
308  * Removes mv from the list of MarkerView upon this TimeAxis
309  *
310  * @param mv the MarkerView to remove
311  * @param src the identity of the object that initiated the change
312  */
313 void
314 MarkerTimeAxisView::remove_marker_view(MarkerView* mv, void* src)
315 {
316         ENSURE_GUI_THREAD (*this, &MarkerTimeAxisView::remove_marker_view, mv, src)
317
318         MarkerViewList::iterator i;
319
320         if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) {
321                 marker_view_list.erase(i) ;
322
323                 // Assume this remove happened locally, else use remove_named_marker_time_axis
324                 // let listeners know that the named MarkerTimeAxis has been removed
325                  MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
326         }
327 }
328
329
330 /**
331  * Sets the duration of the selected MarkerView to the specified number of seconds
332  *
333  * @param sec the duration to set the MArkerView to, in seconds
334  */
335 void
336 MarkerTimeAxisView::set_marker_duration_sec(double sec)
337 {
338   if(get_selected_time_axis_item() != 0)
339   {
340           get_selected_time_axis_item()->set_duration((nframes_t) (sec * _trackview.editor.session()->frame_rate()), this) ;
341   }
342 }
343
344
345 //---------------------------------------------------------------------------------------//
346 // Selected item methods
347
348 /**
349  * Sets the currently selected item upon this time axis
350  *
351  * @param mv the item to set selected
352  */
353 void
354 MarkerTimeAxisView::set_selected_time_axis_item(MarkerView* mv)
355 {
356         selected_time_axis_item = mv ;
357 }
358
359 /**
360  * Clears any selected item upon this time axis
361  *
362  */
363 void
364 MarkerTimeAxisView::clear_selected_time_axis_item()
365 {
366         selected_time_axis_item = 0 ;
367 }
368
369 /**
370  * Returnsthe currently selected item upon this time axis
371  *
372  * @return the currently selected item pon this time axis
373  */
374 MarkerView*
375 MarkerTimeAxisView::get_selected_time_axis_item()
376 {
377         return(selected_time_axis_item) ;
378 }
379
380
381
382
383 /**
384  * convenience method to re-get the samples per unit and tell items upon this view
385  *
386  */
387 void
388 MarkerTimeAxisView::reset_samples_per_unit ()
389 {
390         set_samples_per_unit(_trackview.editor.get_current_zoom()) ;
391 }