changes to help strp silence
[ardour.git] / gtk2_ardour / editor_drag.h
1 /*
2     Copyright (C) 2009 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 #ifndef __gtk2_ardour_editor_drag_h_
21 #define __gtk2_ardour_editor_drag_h_
22
23 #include <list>
24
25 #include <gdk/gdk.h>
26 #include <stdint.h>
27
28 #include "ardour/types.h"
29
30 #include "canvas.h"
31 #include "editor_items.h"
32
33 namespace ARDOUR {
34         class Location;
35 }
36
37 class Editor;
38 class EditorCursor;
39 class TimeAxisView;
40 class Drag;
41
42 /** Class to manage current drags */
43 class DragManager
44 {
45 public:
46
47         DragManager (Editor* e);
48         ~DragManager ();
49
50         bool motion_handler (GdkEvent *, bool);
51
52         void abort ();
53         void break_drag ();
54         void add (Drag *);
55         void set (Drag *, GdkEvent *, Gdk::Cursor* c = 0);
56         void start_grab (GdkEvent *);
57         bool end_grab (GdkEvent *);
58         bool have_item (ArdourCanvas::Item *) const;
59
60         /** @return true if an end drag or break_drag is in progress */
61         bool ending () const {
62                 return _ending;
63         }
64
65         bool active () const {
66                 return !_drags.empty ();
67         }
68
69         /** @return current pointer x position in trackview coordinates */
70         double current_pointer_x () const {
71                 return _current_pointer_x;
72         }
73
74         /** @return current pointer y position in trackview coordinates */
75         double current_pointer_y () const {
76                 return _current_pointer_y;
77         }
78
79         /** @return current pointer frame */
80         nframes64_t current_pointer_frame () const {
81                 return _current_pointer_frame;
82         }
83
84 private:
85         Editor* _editor;
86         std::list<Drag*> _drags;
87         bool _ending; ///< true if end_grab or break_drag is in progress, otherwise false
88         double _current_pointer_x; ///< trackview x of the current pointer
89         double _current_pointer_y; ///< trackview y of the current pointer
90         nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
91 };
92
93 /** Abstract base class for dragging of things within the editor */
94 class Drag
95 {
96 public:
97         Drag (Editor *, ArdourCanvas::Item *);
98         virtual ~Drag () {}
99
100         void set_manager (DragManager* m) {
101                 _drags = m;
102         }
103
104         /** @return the canvas item being dragged */
105         ArdourCanvas::Item* item () const {
106                 return _item;
107         }
108
109         void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
110         bool motion_handler (GdkEvent*, bool);
111         void break_drag ();
112
113         nframes64_t adjusted_frame (nframes64_t, GdkEvent const *, bool snap = true) const;
114         nframes64_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
115         
116         /** Called to start a grab of an item.
117          *  @param e Event that caused the grab to start.
118          *  @param c Cursor to use, or 0.
119          */
120         virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0);
121
122         virtual bool end_grab (GdkEvent *);
123
124         /** Called when a drag motion has occurred.
125          *  @param e Event describing the motion.
126          *  @param f true if this is the first movement, otherwise false.
127          */
128         virtual void motion (GdkEvent* e, bool f) = 0;
129
130         /** Called when a drag has finished.
131          *  @param e Event describing the finish.
132          *  @param m true if some movement occurred, otherwise false.
133          */
134         virtual void finished (GdkEvent* e, bool m) = 0;
135
136         /** Called to abort a drag and return things to how
137          *  they were before it started.
138          */
139         virtual void aborted () = 0;
140
141         /** @param m Mouse mode.
142          *  @return true if this drag should happen in this mouse mode.
143          */
144         virtual bool active (Editing::MouseMode m) {
145                 return (m != Editing::MouseGain);
146         }
147
148         /** @return minimum number of frames (in x) and pixels (in y) that should be considered a movement */
149         virtual std::pair<nframes64_t, int> move_threshold () const {
150                 return std::make_pair (1, 1);
151         }
152
153         virtual bool allow_vertical_autoscroll () const {
154                 return true;
155         }
156
157         /** @return true if x movement matters to this drag */
158         virtual bool x_movement_matters () const {
159                 return true;
160         }
161
162         /** @return true if y movement matters to this drag */
163         virtual bool y_movement_matters () const {
164                 return true;
165         }
166
167 protected:
168
169         double grab_x () const {
170                 return _grab_x;
171         }
172
173         double grab_y () const {
174                 return _grab_y;
175         }
176
177         double grab_frame () const {
178                 return _grab_frame;
179         }
180
181         double last_pointer_x () const {
182                 return _last_pointer_x;
183         }
184
185         double last_pointer_y () const {
186                 return _last_pointer_y;
187         }
188
189         double last_pointer_frame () const {
190                 return _last_pointer_frame;
191         }
192
193         Editor* _editor; ///< our editor
194         DragManager* _drags;
195         ArdourCanvas::Item* _item; ///< our item
196         /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
197         nframes64_t _pointer_frame_offset;
198         bool _x_constrained; ///< true if x motion is constrained, otherwise false
199         bool _y_constrained; ///< true if y motion is constrained, otherwise false
200         bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
201
202 private:
203
204         bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
205         double _grab_x; ///< trackview x of the grab start position
206         double _grab_y; ///< trackview y of the grab start position
207         double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
208         double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
209         nframes64_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
210         nframes64_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
211 };
212
213
214 /** Abstract base class for drags that involve region(s) */
215 class RegionDrag : public Drag, public sigc::trackable
216 {
217 public:
218         RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
219         virtual ~RegionDrag () {}
220
221 protected:
222
223         RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag
224         std::list<RegionView*> _views; ///< all views that are being dragged
225
226 private:
227         void region_going_away (RegionView *);
228         PBD::ScopedConnection death_connection;
229 };
230
231
232 /** Drags involving region motion from somewhere */
233 class RegionMotionDrag : public RegionDrag
234 {
235 public:
236
237         RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool);
238         virtual ~RegionMotionDrag () {}
239
240         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
241         virtual void motion (GdkEvent *, bool);
242         virtual void finished (GdkEvent *, bool) = 0;
243         virtual void aborted ();
244
245 protected:
246         struct TimeAxisViewSummary {
247                 TimeAxisViewSummary () : height_list(512) {}
248
249                 std::bitset<512> tracks;
250                 std::vector<int32_t> height_list;
251                 int visible_y_low;
252                 int visible_y_high;
253         };
254
255         void copy_regions (GdkEvent *);
256         bool y_movement_disallowed (int, int, int, TimeAxisViewSummary const &) const;
257         std::map<RegionView*, std::pair<RouteTimeAxisView*, int> > find_time_axis_views_and_layers ();
258         double compute_x_delta (GdkEvent const *, nframes64_t *);
259         bool compute_y_delta (
260                 TimeAxisView const *, TimeAxisView*, int32_t, int32_t, TimeAxisViewSummary const &,
261                 int32_t *, int32_t *, int32_t *
262                 );
263
264         TimeAxisViewSummary get_time_axis_view_summary ();
265         bool x_move_allowed () const;
266
267         TimeAxisView* _dest_trackview;
268         ARDOUR::layer_t _dest_layer;
269         bool check_possible (RouteTimeAxisView **, ARDOUR::layer_t *);
270         bool _brushing;
271         nframes64_t _last_frame_position; ///< last position of the thing being dragged
272         double _total_x_delta;
273 };
274
275
276 /** Drags to move (or copy) regions that are already shown in the GUI to
277  *  somewhere different.
278  */
279 class RegionMoveDrag : public RegionMotionDrag
280 {
281 public:
282         RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool, bool);
283         virtual ~RegionMoveDrag () {}
284
285         virtual void start_grab (GdkEvent *, Gdk::Cursor *);
286         void motion (GdkEvent *, bool);
287         void finished (GdkEvent *, bool);
288         void aborted ();
289
290         std::pair<nframes64_t, int> move_threshold () const {
291                 return std::make_pair (4, 4);
292         }
293
294 private:
295         bool _copy;
296 };
297
298 /** Drag to insert a region from somewhere */
299 class RegionInsertDrag : public RegionMotionDrag
300 {
301 public:
302         RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, nframes64_t);
303
304         void finished (GdkEvent *, bool);
305         void aborted ();
306 };
307
308 /** Region drag in splice mode */
309 class RegionSpliceDrag : public RegionMoveDrag
310 {
311 public:
312         RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
313
314         void motion (GdkEvent *, bool);
315         void finished (GdkEvent *, bool);
316         void aborted ();
317 };
318
319 /** Drags to create regions */
320 class RegionCreateDrag : public Drag
321 {
322 public:
323         RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *);
324
325         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
326         void motion (GdkEvent *, bool);
327         void finished (GdkEvent *, bool);
328         void aborted ();
329
330 private:
331         TimeAxisView* _view;
332         TimeAxisView* _dest_trackview;
333 };
334
335 /** Drags to resize MIDI notes */
336 class NoteResizeDrag : public Drag
337 {
338 public:
339         NoteResizeDrag (Editor *, ArdourCanvas::Item *);
340
341         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
342         void motion (GdkEvent *, bool);
343         void finished (GdkEvent *, bool);
344         void aborted ();
345
346 private:
347         MidiRegionView*     region;
348         bool                relative;
349         bool                at_front;
350 };
351
352 class NoteDrag : public Drag
353 {
354   public:
355         NoteDrag (Editor*, ArdourCanvas::Item*);
356
357         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
358         void motion (GdkEvent *, bool);
359         void finished (GdkEvent *, bool);
360         void aborted ();
361
362   private:
363         MidiRegionView* region;
364         double last_x;
365         double last_y;
366         double drag_delta_x;
367         double drag_delta_note;
368         bool   was_selected;
369 };
370
371 /** Drag of region gain */
372 class RegionGainDrag : public Drag
373 {
374 public:
375         RegionGainDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
376
377         void motion (GdkEvent *, bool);
378         void finished (GdkEvent *, bool);
379         bool active (Editing::MouseMode m) {
380                 return (m == Editing::MouseGain);
381         }
382
383         void aborted ();
384 };
385
386 /** Drag to trim region(s) */
387 class TrimDrag : public RegionDrag
388 {
389 public:
390         enum Operation {
391                 StartTrim,
392                 EndTrim,
393                 ContentsTrim,
394         };
395
396         TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &);
397
398         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
399         void motion (GdkEvent *, bool);
400         void finished (GdkEvent *, bool);
401         void aborted ();
402
403         bool y_movement_matters () const {
404                 return false;
405         }
406
407 private:
408
409         Operation _operation;
410         bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
411 };
412
413 /** Meter marker drag */
414 class MeterMarkerDrag : public Drag
415 {
416 public:
417         MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
418
419         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
420         void motion (GdkEvent *, bool);
421         void finished (GdkEvent *, bool);
422         void aborted ();
423
424         bool allow_vertical_autoscroll () const {
425                 return false;
426         }
427
428         bool y_movement_matters () const {
429                 return false;
430         }
431         
432 private:
433         MeterMarker* _marker;
434         bool _copy;
435 };
436
437 /** Tempo marker drag */
438 class TempoMarkerDrag : public Drag
439 {
440 public:
441         TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool);
442
443         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
444         void motion (GdkEvent *, bool);
445         void finished (GdkEvent *, bool);
446         void aborted ();
447
448         bool allow_vertical_autoscroll () const {
449                 return false;
450         }
451
452         bool y_movement_matters () const {
453                 return false;
454         }
455
456 private:
457         TempoMarker* _marker;
458         bool _copy;
459 };
460
461
462 /** Drag of a cursor */
463 class CursorDrag : public Drag
464 {
465 public:
466         CursorDrag (Editor *, ArdourCanvas::Item *, bool);
467
468         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
469         void motion (GdkEvent *, bool);
470         void finished (GdkEvent *, bool);
471         void aborted ();
472
473         bool active (Editing::MouseMode) {
474                 return true;
475         }
476
477         bool allow_vertical_autoscroll () const {
478                 return false;
479         }
480
481         bool y_movement_matters () const {
482                 return false;
483         }
484
485 private:
486         EditorCursor* _cursor; ///< cursor being dragged
487         bool _stop; ///< true to stop the transport on starting the drag, otherwise false
488
489 };
490
491 /** Region fade-in drag */
492 class FadeInDrag : public RegionDrag
493 {
494 public:
495         FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
496
497         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
498         void motion (GdkEvent *, bool);
499         void finished (GdkEvent *, bool);
500         void aborted ();
501
502         bool y_movement_matters () const {
503                 return false;
504         }
505 };
506
507 /** Region fade-out drag */
508 class FadeOutDrag : public RegionDrag
509 {
510 public:
511         FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
512
513         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
514         void motion (GdkEvent *, bool);
515         void finished (GdkEvent *, bool);
516         void aborted ();
517
518         bool y_movement_matters () const {
519                 return false;
520         }
521 };
522
523 /** Marker drag */
524 class MarkerDrag : public Drag
525 {
526 public:
527         MarkerDrag (Editor *, ArdourCanvas::Item *);
528         ~MarkerDrag ();
529
530         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
531         void motion (GdkEvent *, bool);
532         void finished (GdkEvent *, bool);
533         void aborted ();
534
535         bool allow_vertical_autoscroll () const {
536                 return false;
537         }
538
539         bool y_movement_matters () const {
540                 return false;
541         }
542         
543 private:
544         void update_item (ARDOUR::Location *);
545
546         Marker* _marker; ///< marker being dragged
547         std::list<ARDOUR::Location*> _copied_locations;
548         ArdourCanvas::Line* _line;
549         ArdourCanvas::Points _points;
550 };
551
552 /** Control point drag */
553 class ControlPointDrag : public Drag
554 {
555 public:
556         ControlPointDrag (Editor *, ArdourCanvas::Item *);
557
558         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
559         void motion (GdkEvent *, bool);
560         void finished (GdkEvent *, bool);
561         void aborted ();
562
563         bool active (Editing::MouseMode m);
564
565 private:
566
567         ControlPoint* _point;
568         double _time_axis_view_grab_x;
569         double _time_axis_view_grab_y;
570         double _cumulative_x_drag;
571         double _cumulative_y_drag;
572         static double const _zero_gain_fraction;
573 };
574
575 /** Gain or automation line drag */
576 class LineDrag : public Drag
577 {
578 public:
579         LineDrag (Editor *e, ArdourCanvas::Item *i);
580
581         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
582         void motion (GdkEvent *, bool);
583         void finished (GdkEvent *, bool);
584         void aborted ();
585
586         bool active (Editing::MouseMode) {
587                 return true;
588         }
589
590 private:
591
592         AutomationLine* _line;
593         double _time_axis_view_grab_x;
594         double _time_axis_view_grab_y;
595         uint32_t _before;
596         uint32_t _after;
597         double _cumulative_y_drag;
598 };
599
600 /** Dragging of a rubberband rectangle for selecting things */
601 class RubberbandSelectDrag : public Drag
602 {
603 public:
604         RubberbandSelectDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
605
606         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
607         void motion (GdkEvent *, bool);
608         void finished (GdkEvent *, bool);
609         void aborted ();
610
611         std::pair<nframes64_t, int> move_threshold () const {
612                 return std::make_pair (8, 1);
613         }
614 };
615
616 /** Region drag in time-FX mode */
617 class TimeFXDrag : public RegionDrag
618 {
619 public:
620         TimeFXDrag (Editor *e, ArdourCanvas::Item *i, RegionView* p, std::list<RegionView*> const & v) : RegionDrag (e, i, p, v) {}
621
622         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
623         void motion (GdkEvent *, bool);
624         void finished (GdkEvent *, bool);
625         void aborted ();
626 };
627
628 /** Scrub drag in audition mode */
629 class ScrubDrag : public Drag
630 {
631 public:
632         ScrubDrag (Editor *e, ArdourCanvas::Item *i) : Drag (e, i) {}
633
634         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
635         void motion (GdkEvent *, bool);
636         void finished (GdkEvent *, bool);
637         void aborted ();
638 };
639
640 /** Drag in range select mode */
641 class SelectionDrag : public Drag
642 {
643 public:
644         enum Operation {
645                 CreateSelection,
646                 SelectionStartTrim,
647                 SelectionEndTrim,
648                 SelectionMove
649         };
650
651         SelectionDrag (Editor *, ArdourCanvas::Item *, Operation);
652
653         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
654         void motion (GdkEvent *, bool);
655         void finished (GdkEvent *, bool);
656         void aborted ();
657
658 private:
659         Operation _operation;
660         bool _copy;
661         int _original_pointer_time_axis;
662         int _last_pointer_time_axis;
663         std::list<TimeAxisView*> _added_time_axes;
664 };
665
666 /** Range marker drag */
667 class RangeMarkerBarDrag : public Drag
668 {
669 public:
670         enum Operation {
671                 CreateRangeMarker,
672                 CreateTransportMarker,
673                 CreateCDMarker
674         };
675
676         RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
677
678         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
679         void motion (GdkEvent *, bool);
680         void finished (GdkEvent *, bool);
681         void aborted ();
682
683         bool allow_vertical_autoscroll () const {
684                 return false;
685         }
686
687         bool y_movement_matters () const {
688                 return false;
689         }
690
691 private:
692         void update_item (ARDOUR::Location *);
693
694         Operation _operation;
695         ArdourCanvas::SimpleRect* _drag_rect;
696         bool _copy;
697 };
698
699 /** Drag of rectangle to set zoom */
700 class MouseZoomDrag : public Drag
701 {
702 public:
703         MouseZoomDrag (Editor* e, ArdourCanvas::Item *i) : Drag (e, i) {}
704
705         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
706         void motion (GdkEvent *, bool);
707         void finished (GdkEvent *, bool);
708         void aborted ();
709 };
710
711 /** Drag of a range of automation data, changing value but not position */
712 class AutomationRangeDrag : public Drag
713 {
714 public:
715         AutomationRangeDrag (Editor *, ArdourCanvas::Item *, std::list<ARDOUR::AudioRange> const &);
716
717         void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
718         void motion (GdkEvent *, bool);
719         void finished (GdkEvent *, bool);
720         void aborted ();
721
722         bool x_movement_matters () const {
723                 return false;
724         }
725
726 private:
727         std::list<ARDOUR::AudioRange> _ranges;
728         AutomationTimeAxisView* _atav;
729         boost::shared_ptr<AutomationLine> _line;
730         bool _nothing_to_drag;
731 };
732
733 #endif /* __gtk2_ardour_editor_drag_h_ */
734