various changes to controls_layout size management
[ardour.git] / gtk2_ardour / editor_canvas_events.cc
1 /*
2     Copyright (C) 2000 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     $Id$
19 */
20
21 #include <cstdlib>
22 #include <cmath>
23
24 #include <ardour/diskstream.h>
25 #include <ardour/audioplaylist.h>
26
27 #include "editor.h"
28 #include "public_editor.h"
29 #include "regionview.h"
30 #include "streamview.h"
31 #include "crossfade_view.h"
32 #include "audio_time_axis.h"
33 #include "region_gain_line.h"
34 #include "automation_gain_line.h"
35 #include "automation_pan_line.h"
36 #include "automation_time_axis.h"
37 #include "redirect_automation_line.h"
38 #include "canvas_impl.h"
39 #include "simplerect.h"
40
41 #include "i18n.h"
42
43 using namespace sigc;
44 using namespace ARDOUR;
45 using namespace Gtk;
46
47 bool
48 Editor::track_canvas_scroll (GdkEventScroll* ev)
49 {
50         switch (ev->direction) {
51         case GDK_SCROLL_UP:
52                 scroll_tracks_up_line ();
53                 return true;
54                 break;
55
56         case GDK_SCROLL_DOWN:
57                 scroll_tracks_down_line ();
58                 return true;
59                 
60         default:
61                 /* no left/right handling yet */
62                 break;
63         }
64
65         return false;
66 }
67
68 bool
69 Editor::track_canvas_event (GdkEvent *event, ArdourCanvas::Item* item)
70 {
71         gint x, y;
72
73         /* this is the handler for events that are not handled by
74            items.
75         */
76
77         switch (event->type) {
78         case GDK_MOTION_NOTIFY:
79                 /* keep those motion events coming */
80                 track_canvas.get_pointer (x, y);
81                 return track_canvas_motion (event);
82
83         case GDK_BUTTON_RELEASE:
84                 switch (event->button.button) {
85                 case 4:
86                 case 5:
87                         button_release_handler (item, event, NoItem);
88                         break;
89                 }
90                 break;
91
92         case GDK_SCROLL:
93                 track_canvas_scroll (&event->scroll);
94                 break;
95
96         default:
97                 break;
98         }
99
100         return FALSE;
101 }
102
103 bool
104 Editor::track_canvas_motion (GdkEvent *ev)
105 {
106         if (verbose_cursor_visible) {
107                 verbose_canvas_cursor->property_x() = ev->motion.x + 20;
108                 verbose_canvas_cursor->property_y() = ev->motion.y + 20;
109         }
110         return false;
111 }
112
113 bool
114 Editor::typed_event (ArdourCanvas::Item* item, GdkEvent *event, ItemType type)
115 {
116         gint ret = FALSE;
117         
118         switch (event->type) {
119         case GDK_BUTTON_PRESS:
120         case GDK_2BUTTON_PRESS:
121         case GDK_3BUTTON_PRESS:
122                 ret = button_press_handler (item, event, type);
123                 break;
124         case GDK_BUTTON_RELEASE:
125                 ret = button_release_handler (item, event, type);
126                 break;
127         case GDK_MOTION_NOTIFY:
128                 ret = motion_handler (item, event, type);
129                 break;
130
131         case GDK_ENTER_NOTIFY:
132                 ret = enter_handler (item, event, type);
133                 break;
134
135         case GDK_LEAVE_NOTIFY:
136                 ret = leave_handler (item, event, type);
137                 break;
138
139         default:
140                 break;
141         }
142                         
143         return ret;
144 }
145
146 bool
147 Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
148 {
149         gint ret = FALSE;
150         
151         switch (event->type) {
152         case GDK_BUTTON_PRESS:
153         case GDK_2BUTTON_PRESS:
154         case GDK_3BUTTON_PRESS:
155                 clicked_regionview = rv;
156                 clicked_control_point = 0;
157                 clicked_trackview = &rv->get_time_axis_view();
158                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
159                 ret = button_press_handler (item, event, RegionItem);
160                 break;
161
162         case GDK_BUTTON_RELEASE:
163                 ret = button_release_handler (item, event, RegionItem);
164                 break;
165
166         case GDK_MOTION_NOTIFY:
167                 ret = motion_handler (item, event, RegionItem);
168                 break;
169
170         case GDK_ENTER_NOTIFY:
171                 set_entered_regionview (rv);
172                 break;
173
174         case GDK_LEAVE_NOTIFY:
175                 set_entered_regionview (0);
176                 break;
177
178         default:
179                 break;
180         }
181
182         return ret;
183 }
184
185 bool
186 Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, AudioTimeAxisView *tv)
187 {
188         bool ret = FALSE;
189         
190         switch (event->type) {
191         case GDK_BUTTON_PRESS:
192         case GDK_2BUTTON_PRESS:
193         case GDK_3BUTTON_PRESS:
194                 clicked_regionview = 0;
195                 clicked_control_point = 0;
196                 clicked_trackview = tv;
197                 clicked_audio_trackview = tv;
198                 ret = button_press_handler (item, event, StreamItem);
199                 break;
200
201         case GDK_BUTTON_RELEASE:
202                 ret = button_release_handler (item, event, StreamItem);
203                 break;
204
205         case GDK_MOTION_NOTIFY:
206                 ret = motion_handler (item, event, StreamItem);
207                 break;
208
209         case GDK_ENTER_NOTIFY:
210                 break;
211
212         default:
213                 break;
214         }
215
216         return ret;
217 }
218
219
220
221 bool
222 Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationTimeAxisView *atv)
223 {
224         bool ret = false;
225         
226         switch (event->type) {
227         case GDK_BUTTON_PRESS:
228         case GDK_2BUTTON_PRESS:
229         case GDK_3BUTTON_PRESS:
230                 clicked_regionview = 0;
231                 clicked_control_point = 0;
232                 clicked_trackview = atv;
233                 clicked_audio_trackview = 0;
234                 ret = button_press_handler (item, event, AutomationTrackItem);
235                 break;
236
237         case GDK_BUTTON_RELEASE:
238                 ret = button_release_handler (item, event, AutomationTrackItem);
239                 break;
240
241         case GDK_MOTION_NOTIFY:
242                 ret = motion_handler (item, event, AutomationTrackItem);
243                 break;
244
245         case GDK_ENTER_NOTIFY:
246                 ret = enter_handler (item, event, AutomationTrackItem);
247                 break;
248
249         case GDK_LEAVE_NOTIFY:
250                 ret = leave_handler (item, event, AutomationTrackItem);
251                 break;
252
253         default:
254                 break;
255         }
256
257         return ret;
258 }
259
260 bool
261 Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
262 {
263         /* we handle only button 3 press/release events */
264
265         switch (event->type) {
266         case GDK_BUTTON_PRESS:
267                 clicked_regionview = rv;
268                 clicked_control_point = 0;
269                 clicked_trackview = &rv->get_time_axis_view();
270                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
271                 if (event->button.button == 3) {
272                         return button_press_handler (item, event, FadeInItem);
273                 }
274                 break;
275
276         case GDK_BUTTON_RELEASE:
277                 if (event->button.button == 3) {
278                         return button_release_handler (item, event, FadeInItem);
279                 }
280                 break;
281
282         default:
283                 break;
284                 
285         }
286
287         /* proxy for the regionview */
288         
289         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
290 }
291
292 bool
293 Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
294 {
295         bool ret = false;
296         
297         switch (event->type) {
298         case GDK_BUTTON_PRESS:
299         case GDK_2BUTTON_PRESS:
300         case GDK_3BUTTON_PRESS:
301                 clicked_regionview = rv;
302                 clicked_control_point = 0;
303                 clicked_trackview = &rv->get_time_axis_view();
304                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
305                 ret = button_press_handler (item, event, FadeInHandleItem);
306                 break;
307
308         case GDK_BUTTON_RELEASE:
309                 ret = button_release_handler (item, event, FadeInHandleItem);
310                 break;
311
312         case GDK_MOTION_NOTIFY:
313                 ret = motion_handler (item, event, FadeInHandleItem);
314                 break;
315
316         case GDK_ENTER_NOTIFY:
317                 ret = enter_handler (item, event, FadeInHandleItem);
318                 break;
319
320         case GDK_LEAVE_NOTIFY:
321                 ret = leave_handler (item, event, FadeInHandleItem);
322                 break;
323
324         default:
325                 break;
326         }
327
328         return ret;
329 }
330
331 bool
332 Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
333 {
334         /* we handle only button 3 press/release events */
335
336         switch (event->type) {
337         case GDK_BUTTON_PRESS:
338                 clicked_regionview = rv;
339                 clicked_control_point = 0;
340                 clicked_trackview = &rv->get_time_axis_view();
341                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
342                 if (event->button.button == 3) {
343                         return button_press_handler (item, event, FadeOutItem);
344                 }
345                 break;
346
347         case GDK_BUTTON_RELEASE:
348                 if (event->button.button == 3) {
349                         return button_release_handler (item, event, FadeOutItem);
350                 }
351                 break;
352
353         default:
354                 break;
355                 
356         }
357
358         /* proxy for the regionview */
359         
360         return canvas_region_view_event (event, rv->get_canvas_group(), rv);
361 }
362
363 bool
364 Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView *rv)
365 {
366         bool ret = false;
367         
368         switch (event->type) {
369         case GDK_BUTTON_PRESS:
370         case GDK_2BUTTON_PRESS:
371         case GDK_3BUTTON_PRESS:
372                 clicked_regionview = rv;
373                 clicked_control_point = 0;
374                 clicked_trackview = &rv->get_time_axis_view();
375                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
376                 ret = button_press_handler (item, event, FadeOutHandleItem);
377                 break;
378
379         case GDK_BUTTON_RELEASE:
380                 ret = button_release_handler (item, event, FadeOutHandleItem);
381                 break;
382
383         case GDK_MOTION_NOTIFY:
384                 ret = motion_handler (item, event, FadeOutHandleItem);
385                 break;
386
387         case GDK_ENTER_NOTIFY:
388                 ret = enter_handler (item, event, FadeOutHandleItem);
389                 break;
390
391         case GDK_LEAVE_NOTIFY:
392                 ret = leave_handler (item, event, FadeOutHandleItem);
393                 break;
394
395         default:
396                 break;
397         }
398
399         return ret;
400 }
401
402 struct DescendingRegionLayerSorter {
403     bool operator()(Region* a, Region* b) {
404             return a->layer() > b->layer();
405     }
406 };
407
408 bool
409 Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, CrossfadeView* xfv)
410 {
411         /* we handle only button 3 press/release events */
412
413         switch (event->type) {
414         case GDK_BUTTON_PRESS:
415                 clicked_crossfadeview = xfv;
416                 clicked_trackview = &clicked_crossfadeview->get_time_axis_view();
417                 if (event->button.button == 3) {
418                         return button_press_handler (item, event, CrossfadeViewItem);
419                 } 
420                 break;
421
422         case GDK_BUTTON_RELEASE:
423                 if (event->button.button == 3) {
424                         bool ret = button_release_handler (item, event, CrossfadeViewItem);
425                         return ret;
426                 }
427                 break;
428
429         default:
430                 break;
431                 
432         }
433
434         
435         /* proxy for the upper most regionview */
436
437         /* XXX really need to check if we are in the name highlight,
438            and proxy to that when required.
439         */
440         
441         TimeAxisView& tv (xfv->get_time_axis_view());
442         AudioTimeAxisView* atv;
443
444         if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
445
446                 if (atv->is_audio_track()) {
447
448                         AudioPlaylist* pl = atv->get_diskstream()->playlist();
449                         Playlist::RegionList* rl = pl->regions_at (event_frame (event));
450
451                         if (!rl->empty()) {
452                                 DescendingRegionLayerSorter cmp;
453                                 rl->sort (cmp);
454
455                                 AudioRegionView* arv = atv->view->find_view (*(dynamic_cast<AudioRegion*> (rl->front())));
456
457                                 /* proxy */
458                                 
459                                 delete rl;
460
461                                 return canvas_region_view_event (event, arv->get_canvas_group(), arv);
462                         }
463                 }
464         }
465
466         return TRUE;
467 }
468
469 bool
470 Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, ControlPoint* cp)
471 {
472         ItemType type;
473
474         switch (event->type) {
475         case GDK_BUTTON_PRESS:
476         case GDK_2BUTTON_PRESS:
477         case GDK_3BUTTON_PRESS:
478                 clicked_control_point = cp;
479                 clicked_trackview = &cp->line.trackview;
480                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
481                 clicked_regionview = 0;
482                 break;
483
484         default:
485                 break;
486         }
487
488         if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
489                 type = GainControlPointItem;
490         } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
491                 type = GainAutomationControlPointItem;
492         } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
493                 type = PanAutomationControlPointItem;
494         } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) {
495                 type = RedirectAutomationControlPointItem;
496         } else {
497                 return false;
498         }
499
500         return typed_event (item, event, type);
501 }
502
503 bool
504 Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, AutomationLine* al)
505 {
506         ItemType type;
507
508         if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
509                 type = GainLineItem;
510         } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
511                 type = GainAutomationLineItem;
512         } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
513                 type = PanAutomationLineItem;
514         } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) {
515                 type = RedirectAutomationLineItem;
516         } else {
517                 return false;
518         }
519
520         return typed_event (item, event, type);
521 }
522
523 bool
524 Editor::canvas_selection_rect_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
525 {
526         bool ret = false;
527         
528         switch (event->type) {
529         case GDK_BUTTON_PRESS:
530         case GDK_2BUTTON_PRESS:
531         case GDK_3BUTTON_PRESS:
532                 clicked_selection = rect->id;
533                 ret = button_press_handler (item, event, SelectionItem);
534                 break;
535         case GDK_BUTTON_RELEASE:
536                 ret = button_release_handler (item, event, SelectionItem);
537                 break;
538         case GDK_MOTION_NOTIFY:
539                 ret = motion_handler (item, event, SelectionItem);
540                 break;
541                 /* Don't need these at the moment. */
542         case GDK_ENTER_NOTIFY:
543                 ret = enter_handler (item, event, SelectionItem);
544                 break;
545
546         case GDK_LEAVE_NOTIFY:
547                 ret = leave_handler (item, event, SelectionItem);
548                 break;
549
550         default:
551                 break;
552         }
553                         
554         return ret;
555 }
556
557 bool
558 Editor::canvas_selection_start_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
559 {
560         bool ret = false;
561
562         switch (event->type) {
563         case GDK_BUTTON_PRESS:
564         case GDK_2BUTTON_PRESS:
565         case GDK_3BUTTON_PRESS:
566                 clicked_selection = rect->id;
567                 ret = button_press_handler (item, event, StartSelectionTrimItem);
568                 break;
569         case GDK_BUTTON_RELEASE:
570                 ret = button_release_handler (item, event, StartSelectionTrimItem);
571                 break;
572         case GDK_MOTION_NOTIFY:
573                 ret = motion_handler (item, event, StartSelectionTrimItem);
574                 break;
575         case GDK_ENTER_NOTIFY:
576                 ret = enter_handler (item, event, StartSelectionTrimItem);
577                 break;
578
579         case GDK_LEAVE_NOTIFY:
580                 ret = leave_handler (item, event, StartSelectionTrimItem);
581                 break;
582
583         default:
584                 break;
585         }
586                         
587         return ret;
588 }
589
590 bool
591 Editor::canvas_selection_end_trim_event (GdkEvent *event, ArdourCanvas::Item* item, SelectionRect* rect)
592 {
593         bool ret = false;
594
595         switch (event->type) {
596         case GDK_BUTTON_PRESS:
597         case GDK_2BUTTON_PRESS:
598         case GDK_3BUTTON_PRESS:
599                 clicked_selection = rect->id;
600                 ret = button_press_handler (item, event, EndSelectionTrimItem);
601                 break;
602         case GDK_BUTTON_RELEASE:
603                 ret = button_release_handler (item, event, EndSelectionTrimItem);
604                 break;
605         case GDK_MOTION_NOTIFY:
606                 ret = motion_handler (item, event, EndSelectionTrimItem);
607                 break;
608         case GDK_ENTER_NOTIFY:
609                 ret = enter_handler (item, event, EndSelectionTrimItem);
610                 break;
611
612         case GDK_LEAVE_NOTIFY:
613                 ret = leave_handler (item, event, EndSelectionTrimItem);
614                 break;
615
616         default:
617                 break;
618         }
619                         
620         return ret;
621 }
622
623
624 bool
625 Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas::Item* item, AudioRegionView* rv)
626 {
627         bool ret = false;
628         
629         switch (event->type) {
630         case GDK_BUTTON_PRESS:
631         case GDK_2BUTTON_PRESS:
632         case GDK_3BUTTON_PRESS:
633                 clicked_regionview = rv;
634                 clicked_control_point = 0;
635                 clicked_trackview = &clicked_regionview->get_time_axis_view();
636                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
637                 ret = button_press_handler (item, event, AudioRegionViewNameHighlight);
638                 break;
639         case GDK_BUTTON_RELEASE:
640                 ret = button_release_handler (item, event, AudioRegionViewNameHighlight);
641                 break;
642         case GDK_MOTION_NOTIFY:
643                 ret = motion_handler (item, event, AudioRegionViewNameHighlight);
644                 break;
645         case GDK_ENTER_NOTIFY:
646                 ret = enter_handler (item, event, AudioRegionViewNameHighlight);
647                 break;
648
649         case GDK_LEAVE_NOTIFY:
650                 ret = leave_handler (item, event, AudioRegionViewNameHighlight);
651                 break;
652
653         default:
654                 break;
655         }
656
657         return ret;
658 }
659
660 bool
661 Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRegionView* rv)
662 {
663         bool ret = false;
664
665         switch (event->type) {
666         case GDK_BUTTON_PRESS:
667         case GDK_2BUTTON_PRESS:
668         case GDK_3BUTTON_PRESS:
669                 clicked_regionview = rv;
670                 clicked_control_point = 0;
671                 clicked_trackview = &clicked_regionview->get_time_axis_view();
672                 clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
673                 ret = button_press_handler (item, event, AudioRegionViewName);
674                 break;
675         case GDK_BUTTON_RELEASE:
676                 ret = button_release_handler (item, event, AudioRegionViewName);
677                 break;
678         case GDK_MOTION_NOTIFY:
679                 ret = motion_handler (item, event, AudioRegionViewName);
680                 break;
681         case GDK_ENTER_NOTIFY:
682                 ret = enter_handler (item, event, AudioRegionViewName);
683                 break;
684
685         case GDK_LEAVE_NOTIFY:
686                 ret = leave_handler (item, event, AudioRegionViewName);
687                 break;
688
689         default:
690                 break;
691         }
692
693         return ret;
694 }
695
696 bool
697 Editor::canvas_marker_event (GdkEvent *event, ArdourCanvas::Item* item, Marker* marker)
698 {
699         return typed_event (item, event, MarkerItem);
700 }
701
702 bool
703 Editor::canvas_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
704 {
705         return typed_event (item, event, MarkerBarItem);
706 }
707
708 bool
709 Editor::canvas_range_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
710 {
711         return typed_event (item, event, RangeMarkerBarItem);
712 }
713
714 bool
715 Editor::canvas_transport_marker_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
716 {
717         return typed_event (item, event, TransportMarkerBarItem);
718 }
719
720 bool
721 Editor::canvas_tempo_marker_event (GdkEvent *event, ArdourCanvas::Item* item, TempoMarker* marker)
722 {
723         return typed_event (item, event, TempoMarkerItem);
724 }
725
726 bool
727 Editor::canvas_meter_marker_event (GdkEvent *event, ArdourCanvas::Item* item, MeterMarker* marker)
728 {
729         return typed_event (item, event, MeterMarkerItem);
730 }
731
732 bool
733 Editor::canvas_tempo_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
734 {
735         return typed_event (item, event, TempoBarItem);
736 }
737
738 bool
739 Editor::canvas_meter_bar_event (GdkEvent *event, ArdourCanvas::Item* item)
740 {
741         return typed_event (item, event, MeterBarItem);
742 }
743
744 bool
745 Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
746 {
747         return typed_event (item, event, PlayheadCursorItem);
748 }
749
750 bool
751 Editor::canvas_edit_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
752 {
753         return typed_event (item, event, EditCursorItem);
754 }
755
756 bool
757 Editor::canvas_zoom_rect_event (GdkEvent *event, ArdourCanvas::Item* item)
758 {
759         return typed_event (item, event, NoItem);
760 }
761