1 /* 2 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net> 3 * Copyright (C) 2009-2015 David Robillard <d@drobilla.net> 4 * Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com> 5 * Copyright (C) 2013-2014 Colin Fletcher <colin.m.fletcher@googlemail.com> 6 * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org> 7 * Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com> 8 * Copyright (C) 2015-2018 Ben Loftis <ben@harrisonconsoles.com> 9 * Copyright (C) 2016 Tim Mayberry <mojofunk@gmail.com> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License along 22 * with this program; if not, write to the Free Software Foundation, Inc., 23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 */ 25 26 #ifndef __gtk2_ardour_editor_drag_h_ 27 #define __gtk2_ardour_editor_drag_h_ 28 29 #include <list> 30 31 #include <gdk/gdk.h> 32 #include <stdint.h> 33 34 #include "ardour/tempo.h" 35 #include "ardour/types.h" 36 37 #include "canvas/types.h" 38 39 #include "cursor_context.h" 40 #include "editor_items.h" 41 #include "mouse_cursors.h" 42 #include "editing.h" 43 #include "track_selection.h" 44 45 namespace ARDOUR { 46 class Location; 47 class Region; 48 class TempoSection; 49 } 50 51 namespace ArdourCanvas { 52 class Item; 53 class Line; 54 class Rectangle; 55 } 56 57 namespace PBD { 58 class StatefulDiffCommand; 59 } 60 61 class PatchChange; 62 class Editor; 63 class EditorCursor; 64 class TimeAxisView; 65 class MidiTimeAxisView; 66 class Drag; 67 class NoteBase; 68 class RegionView; 69 class TimeAxisView; 70 class RouteTimeAxisView; 71 class RegionSelection; 72 class MidiRegionView; 73 class MeterMarker; 74 class ArdourMarker; 75 class TempoMarker; 76 class ControlPoint; 77 class AudioRegionView; 78 class AutomationLine; 79 class AutomationTimeAxisView; 80 81 /** Class to manage current drags */ 82 class DragManager 83 { 84 public: 85 86 DragManager (Editor* e); 87 ~DragManager (); 88 89 bool motion_handler (GdkEvent *, bool); 90 91 void abort (); 92 void add (Drag *); 93 void set (Drag *, GdkEvent *, Gdk::Cursor* c = MouseCursors::invalid_cursor()); 94 void start_grab (GdkEvent *, Gdk::Cursor* c = MouseCursors::invalid_cursor()); 95 bool end_grab (GdkEvent *); 96 bool have_item (ArdourCanvas::Item *) const; 97 98 void mark_double_click (); 99 100 /** @return true if an end drag or abort is in progress */ ending()101 bool ending () const { 102 return _ending; 103 } 104 active()105 bool active () const { 106 return !_drags.empty (); 107 } 108 109 /** @return current pointer x position in canvas coordinates */ current_pointer_x()110 double current_pointer_x () const { 111 return _current_pointer_x; 112 } 113 114 /** @return current pointer y position in canvas coordinates */ current_pointer_y()115 double current_pointer_y () const { 116 return _current_pointer_y; 117 } 118 119 /** @return current pointer sample */ current_pointer_sample()120 ARDOUR::samplepos_t current_pointer_sample () const { 121 return _current_pointer_sample; 122 } 123 124 /** return drag-motion displays video-frame of drag-location */ 125 bool preview_video () const; 126 127 private: 128 Editor* _editor; 129 std::list<Drag*> _drags; 130 bool _ending; ///< true if end_grab or abort is in progress, otherwise false 131 double _current_pointer_x; ///< canvas-coordinate space x of the current pointer 132 double _current_pointer_y; ///< canvas-coordinate space y of the current pointer 133 ARDOUR::samplepos_t _current_pointer_sample; ///< sample that the pointer is now at 134 bool _old_follow_playhead; ///< state of Editor::follow_playhead() before the drags started 135 }; 136 137 /** Abstract base class for dragging of things within the editor */ 138 class Drag 139 { 140 public: 141 Drag (Editor *, ArdourCanvas::Item *, bool trackview_only = true); ~Drag()142 virtual ~Drag () {} 143 set_manager(DragManager * m)144 void set_manager (DragManager* m) { 145 _drags = m; 146 } 147 148 /** @return the canvas item being dragged */ item()149 ArdourCanvas::Item* item () const { 150 return _item; 151 } 152 153 void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t); 154 bool motion_handler (GdkEvent*, bool); 155 void abort (); 156 157 ARDOUR::MusicSample adjusted_sample (ARDOUR::samplepos_t, GdkEvent const *, bool snap = true) const; 158 ARDOUR::samplepos_t adjusted_current_sample (GdkEvent const *, bool snap = true) const; 159 was_double_click()160 bool was_double_click() const { return _was_double_click; } set_double_click(bool yn)161 void set_double_click (bool yn) { _was_double_click = yn; } 162 163 /** Called to start a grab of an item. 164 * @param e Event that caused the grab to start. 165 * @param c Cursor to use, or 0. 166 */ 167 virtual void start_grab (GdkEvent* e, Gdk::Cursor* c = 0); 168 169 virtual bool end_grab (GdkEvent *); 170 171 /** Called when a drag motion has occurred. 172 * @param e Event describing the motion. 173 * @param f true if this is the first movement, otherwise false. 174 */ 175 virtual void motion (GdkEvent* e, bool f) = 0; 176 177 /** Called when a drag has finished. 178 * @param e Event describing the finish. 179 * @param m true if some movement occurred, otherwise false. 180 */ 181 virtual void finished (GdkEvent* e, bool m) = 0; 182 183 /** Called to abort a drag and return things to how 184 * they were before it started. 185 * @param m true if some movement occurred, otherwise false. 186 */ 187 virtual void aborted (bool m) = 0; 188 189 /** @param m Mouse mode. 190 * @return true if this drag should happen in this mouse mode. 191 */ active(Editing::MouseMode m)192 virtual bool active (Editing::MouseMode m) { 193 return true; 194 } 195 preview_video()196 bool preview_video () const { 197 return _preview_video; 198 } 199 200 /** @return minimum number of pixels (x, y) that should be considered a movement */ move_threshold()201 virtual std::pair<int, int> move_threshold () const { 202 return std::make_pair (1, 1); 203 } 204 allow_vertical_autoscroll()205 virtual bool allow_vertical_autoscroll () const { 206 return true; 207 } 208 209 /** @return true if x movement matters to this drag */ x_movement_matters()210 virtual bool x_movement_matters () const { 211 return true; 212 } 213 214 /** @return true if y movement matters to this drag */ y_movement_matters()215 virtual bool y_movement_matters () const { 216 return true; 217 } 218 initially_vertical()219 bool initially_vertical() const { 220 return _initially_vertical; 221 } 222 223 /** Set up the _pointer_sample_offset */ setup_pointer_sample_offset()224 virtual void setup_pointer_sample_offset () { 225 _pointer_sample_offset = 0; 226 } 227 228 /** Set up the _video_sample_offset - relative to _current_pointer_sample */ setup_video_sample_offset()229 virtual void setup_video_sample_offset () { 230 _video_sample_offset = 0; 231 _preview_video = false; 232 } 233 grab_button()234 int grab_button() const { return _grab_button; } 235 236 protected: 237 grab_x()238 double grab_x () const { 239 return _grab_x; 240 } 241 grab_y()242 double grab_y () const { 243 return _grab_y; 244 } 245 raw_grab_sample()246 ARDOUR::samplepos_t raw_grab_sample () const { 247 return _raw_grab_sample; 248 } 249 grab_sample()250 ARDOUR::samplepos_t grab_sample () const { 251 return _grab_sample; 252 } 253 last_pointer_x()254 double last_pointer_x () const { 255 return _last_pointer_x; 256 } 257 last_pointer_y()258 double last_pointer_y () const { 259 return _last_pointer_y; 260 } 261 last_pointer_sample()262 ARDOUR::samplepos_t last_pointer_sample () const { 263 return _last_pointer_sample; 264 } 265 266 ARDOUR::sampleoffset_t snap_delta (guint const) const; 267 double snap_delta_music (guint const) const; 268 269 double current_pointer_x () const; 270 double current_pointer_y () const; 271 272 /* sets snap delta from unsnapped pos */ 273 void setup_snap_delta (ARDOUR::MusicSample pos); 274 275 boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*, bool commit); 276 277 void show_verbose_cursor_time (samplepos_t); 278 void show_verbose_cursor_duration (samplepos_t, samplepos_t, double xoffset = 0); 279 void show_verbose_cursor_text (std::string const &); 280 void show_view_preview (samplepos_t); 281 282 Editor* _editor; ///< our editor 283 DragManager* _drags; 284 ArdourCanvas::Item* _item; ///< our item 285 /** Offset from the mouse's position for the drag to the start of the thing that is being dragged */ 286 ARDOUR::samplecnt_t _pointer_sample_offset; 287 ARDOUR::samplecnt_t _video_sample_offset; 288 bool _preview_video; 289 bool _x_constrained; ///< true if x motion is constrained, otherwise false 290 bool _y_constrained; ///< true if y motion is constrained, otherwise false 291 bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false 292 293 private: 294 bool _trackview_only; ///< true if pointer y value should always be relative to the top of the trackview group 295 bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false 296 bool _starting_point_passed; ///< true if we called move () with first_move flag, otherwise false 297 bool _initially_vertical; ///< true if after move threshold is passed we appear to be moving vertically; undefined before that 298 bool _was_double_click; ///< true if drag initiated by a double click event 299 double _grab_x; ///< trackview x of the grab start position 300 double _grab_y; ///< y of the grab start position, possibly adjusted if _trackview_only is true 301 double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred 302 double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred 303 ARDOUR::samplepos_t _raw_grab_sample; ///< unsnapped sample that the mouse was at when start_grab was called, or 0 304 ARDOUR::samplepos_t _grab_sample; ///< adjusted_sample that the mouse was at when start_grab was called, or 0 305 ARDOUR::samplepos_t _last_pointer_sample; ///< adjusted_sample the last time a motion occurred 306 307 /* difference between some key position's snapped and unsnapped 308 * samplepos. used for relative snap. 309 */ 310 samplepos_t _snap_delta; 311 double _snap_delta_music; 312 CursorContext::Handle _cursor_ctx; ///< cursor change context 313 bool _constraint_pressed; ///< if the keyboard indicated constraint modifier was pressed on start_grab() 314 int _grab_button; 315 }; 316 317 class RegionDrag; 318 319 /** Container for details about a region being dragged */ 320 class DraggingView 321 { 322 public: 323 DraggingView (RegionView *, RegionDrag *, TimeAxisView* original_tav); 324 325 RegionView* view; ///< the view 326 /** index into RegionDrag::_time_axis_views of the view that this region is currently being displayed on, 327 * or -1 if it is not visible. 328 */ 329 int time_axis_view; 330 /** layer that this region is currently being displayed on. This is a double 331 rather than a layer_t as we use fractional layers during drags to allow the user 332 to indicate a new layer to put a region on. 333 */ 334 double layer; 335 double initial_y; ///< the initial y position of the view before any reparenting 336 samplepos_t initial_position; ///< initial position of the region 337 samplepos_t initial_end; ///< initial end position of the region 338 samplepos_t anchored_fade_length; ///< fade_length when anchored during drag 339 boost::shared_ptr<ARDOUR::Playlist> initial_playlist; 340 TimeAxisView* initial_time_axis_view; 341 }; 342 343 /** Abstract base class for drags that involve region(s) */ 344 class RegionDrag : public Drag, public sigc::trackable 345 { 346 public: 347 RegionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); ~RegionDrag()348 virtual ~RegionDrag () {} 349 350 protected: 351 352 RegionView* _primary; ///< the view that was clicked on (or whatever) to start the drag 353 std::list<DraggingView> _views; ///< information about all views that are being dragged 354 355 /** a list of the non-hidden TimeAxisViews sorted by editor order key */ 356 std::vector<TimeAxisView*> _time_axis_views; 357 int find_time_axis_view (TimeAxisView *) const; 358 int apply_track_delta (const int start, const int delta, const int skip, const bool distance_only = false) const; 359 360 int _visible_y_low; 361 int _visible_y_high; 362 uint32_t _ntracks; 363 364 void setup_video_sample_offset (); 365 366 friend class DraggingView; 367 368 protected: 369 typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet; 370 void add_stateful_diff_commands_for_playlists (PlaylistSet const &); 371 372 private: 373 374 void region_going_away (RegionView *); 375 PBD::ScopedConnection death_connection; 376 }; 377 378 /** Drag the Contents rather than the bounds of a region (i.e. Slip) */ 379 class RegionSlipContentsDrag : public RegionDrag 380 { 381 public: 382 383 RegionSlipContentsDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); ~RegionSlipContentsDrag()384 virtual ~RegionSlipContentsDrag () {} 385 386 virtual void start_grab (GdkEvent *, Gdk::Cursor *); 387 virtual void motion (GdkEvent *, bool); 388 virtual void finished (GdkEvent *, bool); 389 virtual void aborted (bool); 390 }; 391 392 /** Brush on a region to repeat it */ 393 class RegionBrushDrag : public RegionDrag 394 { 395 public: 396 RegionBrushDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); ~RegionBrushDrag()397 virtual ~RegionBrushDrag () {} 398 399 virtual void start_grab (GdkEvent *, Gdk::Cursor *); 400 virtual void motion (GdkEvent *, bool); 401 virtual void finished (GdkEvent *, bool); 402 virtual void aborted (bool); 403 private: 404 typedef std::set<samplepos_t> SamplePositionSet; 405 SamplePositionSet _already_pasted; 406 }; 407 408 /** Drags involving region motion from somewhere */ 409 class RegionMotionDrag : public RegionDrag 410 { 411 public: 412 413 RegionMotionDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); ~RegionMotionDrag()414 virtual ~RegionMotionDrag () {} 415 416 virtual void start_grab (GdkEvent *, Gdk::Cursor *); 417 virtual void motion (GdkEvent *, bool); 418 virtual void finished (GdkEvent *, bool); 419 virtual void aborted (bool); 420 421 /** @return true if the regions being `moved' came from somewhere on the canvas; 422 * false if they came from outside (e.g. from the region list). 423 */ 424 virtual bool regions_came_from_canvas () const = 0; 425 426 protected: 427 428 double compute_x_delta (GdkEvent const *, ARDOUR::MusicSample *); 429 virtual bool y_movement_allowed (int, double, int skip_invisible = 0) const; 430 431 bool _ignore_video_lock; 432 ARDOUR::MusicSample _last_position; ///< last position of the thing being dragged 433 double _total_x_delta; 434 int _last_pointer_time_axis_view; 435 double _last_pointer_layer; 436 private: 437 uint32_t _ndropzone; 438 uint32_t _pdropzone; 439 uint32_t _ddropzone; 440 }; 441 442 443 /** Drags to move (or copy) regions that are already shown in the GUI to 444 * somewhere different. 445 */ 446 class RegionMoveDrag : public RegionMotionDrag 447 { 448 public: 449 RegionMoveDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &, bool); ~RegionMoveDrag()450 virtual ~RegionMoveDrag () {} 451 452 void motion (GdkEvent *, bool); 453 void finished (GdkEvent *, bool); 454 void aborted (bool); 455 456 void clear_draggingview_list (); 457 regions_came_from_canvas()458 bool regions_came_from_canvas () const { 459 return true; 460 } 461 move_threshold()462 std::pair<int, int> move_threshold () const { 463 if (_copy) { 464 return std::make_pair (6, 4); 465 } else { 466 return std::make_pair (2, 4); 467 } 468 } 469 470 void setup_pointer_sample_offset (); 471 472 private: 473 void finished_no_copy ( 474 bool const, 475 bool const, 476 ARDOUR::MusicSample, 477 int32_t const ev_state 478 ); 479 480 void finished_copy ( 481 bool const, 482 bool const, 483 ARDOUR::MusicSample, 484 int32_t const ev_state 485 ); 486 487 RegionView* insert_region_into_playlist ( 488 boost::shared_ptr<ARDOUR::Region>, 489 RouteTimeAxisView*, 490 ARDOUR::layer_t, 491 ARDOUR::MusicSample, 492 double quarter_note, 493 PlaylistSet&, 494 bool for_music = false 495 ); 496 497 void remove_region_from_playlist ( 498 boost::shared_ptr<ARDOUR::Region>, 499 boost::shared_ptr<ARDOUR::Playlist>, 500 PlaylistSet& modified_playlists 501 ); 502 503 504 void collect_new_region_view (RegionView *); 505 RouteTimeAxisView* create_destination_time_axis (boost::shared_ptr<ARDOUR::Region>, TimeAxisView* original); 506 507 bool _copy; 508 RegionView* _new_region_view; 509 }; 510 511 /** Drag to insert a region from somewhere */ 512 class RegionInsertDrag : public RegionMotionDrag 513 { 514 public: 515 RegionInsertDrag (Editor *, boost::shared_ptr<ARDOUR::Region>, RouteTimeAxisView*, ARDOUR::samplepos_t); 516 517 void finished (GdkEvent *, bool); 518 void aborted (bool); 519 regions_came_from_canvas()520 bool regions_came_from_canvas () const { 521 return false; 522 } 523 }; 524 525 /** Region drag in splice mode */ 526 class RegionSpliceDrag : public RegionMoveDrag 527 { 528 public: 529 RegionSpliceDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); 530 531 void motion (GdkEvent *, bool); 532 void finished (GdkEvent *, bool); 533 void aborted (bool); 534 }; 535 536 /** Region drag in ripple mode */ 537 538 class RegionRippleDrag : public RegionMoveDrag 539 { 540 public: 541 RegionRippleDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); ~RegionRippleDrag()542 ~RegionRippleDrag () { delete exclude; } 543 544 void motion (GdkEvent *, bool); 545 void finished (GdkEvent *, bool); 546 void aborted (bool); 547 protected: 548 bool y_movement_allowed (int delta_track, double delta_layer, int skip_invisible = 0) const; 549 550 private: 551 TimeAxisView *prev_tav; // where regions were most recently dragged from 552 TimeAxisView *orig_tav; // where drag started 553 ARDOUR::samplecnt_t prev_amount; 554 ARDOUR::samplepos_t prev_position; 555 ARDOUR::samplecnt_t selection_length; 556 bool allow_moves_across_tracks; // only if all selected regions are on one track 557 ARDOUR::RegionList *exclude; 558 void add_all_after_to_views (TimeAxisView *tav, ARDOUR::samplepos_t where, const RegionSelection &exclude, bool drag_in_progress); 559 void remove_unselected_from_views (ARDOUR::samplecnt_t amount, bool move_regions); 560 561 std::list<boost::shared_ptr<ARDOUR::Region> > _orig_tav_ripples; 562 }; 563 564 /** "Drag" to cut a region (action only on button release) */ 565 class RegionCutDrag : public Drag 566 { 567 public: 568 RegionCutDrag (Editor*, ArdourCanvas::Item*, samplepos_t); 569 ~RegionCutDrag (); 570 571 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 572 void motion (GdkEvent*, bool); 573 void finished (GdkEvent*, bool); 574 void aborted (bool); 575 576 private: 577 }; 578 579 /** Drags to create regions */ 580 class RegionCreateDrag : public Drag 581 { 582 public: 583 RegionCreateDrag (Editor *, ArdourCanvas::Item *, TimeAxisView *); 584 585 void motion (GdkEvent *, bool); 586 void finished (GdkEvent *, bool); 587 void aborted (bool); 588 589 private: 590 MidiTimeAxisView* _view; 591 boost::shared_ptr<ARDOUR::Region> _region; 592 }; 593 594 /** Drags to resize MIDI notes */ 595 class NoteResizeDrag : public Drag 596 { 597 public: 598 NoteResizeDrag (Editor *, ArdourCanvas::Item *); 599 600 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 601 void motion (GdkEvent *, bool); 602 void finished (GdkEvent *, bool); 603 void aborted (bool); 604 allow_vertical_autoscroll()605 bool allow_vertical_autoscroll () const { 606 return false; 607 } 608 609 private: 610 MidiRegionView* region; 611 bool relative; 612 bool at_front; 613 bool _was_selected; 614 double _snap_delta; 615 }; 616 617 /** Drags to move MIDI notes */ 618 class NoteDrag : public Drag 619 { 620 public: 621 NoteDrag (Editor*, ArdourCanvas::Item*); 622 623 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 624 void motion (GdkEvent *, bool); 625 void finished (GdkEvent *, bool); 626 void aborted (bool); 627 628 void setup_pointer_sample_offset (); 629 allow_vertical_autoscroll()630 bool allow_vertical_autoscroll () const { 631 return false; 632 } 633 634 private: 635 636 double total_dx (GdkEvent * event) const; // total movement in quarter notes 637 int8_t total_dy () const; 638 639 MidiRegionView* _region; 640 NoteBase* _primary; 641 double _cumulative_dx; 642 double _cumulative_dy; 643 double _earliest; // earliest quarter note in note selection 644 bool _was_selected; 645 double _note_height; 646 bool _copy; 647 }; 648 649 class NoteCreateDrag : public Drag 650 { 651 public: 652 NoteCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *); 653 ~NoteCreateDrag (); 654 655 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 656 void motion (GdkEvent *, bool); 657 void finished (GdkEvent *, bool); 658 void aborted (bool); 659 active(Editing::MouseMode mode)660 bool active (Editing::MouseMode mode) { 661 return mode == Editing::MouseDraw || mode == Editing::MouseContent; 662 } 663 allow_vertical_autoscroll()664 bool allow_vertical_autoscroll () const { 665 return false; 666 } 667 y_movement_matters()668 bool y_movement_matters () const { 669 return false; 670 } 671 672 private: 673 double y_to_region (double) const; 674 ARDOUR::samplecnt_t grid_samples (samplepos_t) const; 675 676 /** @return minimum number of pixels (x, y) that should be considered a movement */ move_threshold()677 virtual std::pair<int, int> move_threshold () const { 678 return std::make_pair (0, 0); 679 } 680 681 MidiRegionView* _region_view; 682 ArdourCanvas::Rectangle* _drag_rect; 683 samplepos_t _note[2]; 684 }; 685 686 class HitCreateDrag : public Drag 687 { 688 public: 689 HitCreateDrag (Editor *, ArdourCanvas::Item *, MidiRegionView *); 690 ~HitCreateDrag (); 691 692 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 693 void motion (GdkEvent *, bool); 694 void finished (GdkEvent *, bool); 695 void aborted (bool); 696 active(Editing::MouseMode mode)697 bool active (Editing::MouseMode mode) { 698 return mode == Editing::MouseDraw || mode == Editing::MouseContent; 699 } 700 y_movement_matters()701 bool y_movement_matters () const { 702 return false; 703 } 704 705 private: 706 double y_to_region (double) const; 707 ARDOUR::samplecnt_t grid_samples (samplepos_t) const; 708 709 /** @return minimum number of pixels (x, y) that should be considered a movement */ move_threshold()710 virtual std::pair<int, int> move_threshold () const { 711 return std::make_pair (0, 0); 712 } 713 714 MidiRegionView* _region_view; 715 samplepos_t _last_pos; 716 double _y; 717 718 }; 719 720 /** Drag to move MIDI patch changes */ 721 class PatchChangeDrag : public Drag 722 { 723 public: 724 PatchChangeDrag (Editor *, PatchChange *, MidiRegionView *); 725 726 void motion (GdkEvent *, bool); 727 void finished (GdkEvent *, bool); 728 void aborted (bool); 729 y_movement_matters()730 bool y_movement_matters () const { 731 return false; 732 } 733 allow_vertical_autoscroll()734 bool allow_vertical_autoscroll () const { 735 return false; 736 } 737 738 void setup_pointer_sample_offset (); 739 740 private: 741 MidiRegionView* _region_view; 742 PatchChange* _patch_change; 743 double _cumulative_dx; 744 }; 745 746 /** Container for details about audio regions being dragged along with video */ 747 class AVDraggingView 748 { 749 public: 750 AVDraggingView (RegionView *); 751 752 RegionView* view; ///< the view 753 samplepos_t initial_position; ///< initial position of the region 754 }; 755 756 /** Drag of video offset */ 757 class VideoTimeLineDrag : public Drag 758 { 759 public: 760 VideoTimeLineDrag (Editor *e, ArdourCanvas::Item *i); 761 762 void motion (GdkEvent *, bool); 763 void finished (GdkEvent *, bool); 764 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 765 y_movement_matters()766 bool y_movement_matters () const { 767 return false; 768 } 769 allow_vertical_autoscroll()770 bool allow_vertical_autoscroll () const { 771 return false; 772 } 773 774 void aborted (bool); 775 776 protected: 777 std::list<AVDraggingView> _views; ///< information about all audio that are being dragged along 778 779 private: 780 ARDOUR::sampleoffset_t _startdrag_video_offset; 781 ARDOUR::sampleoffset_t _max_backwards_drag; 782 bool _stuck; 783 }; 784 785 /** Drag to trim region(s) */ 786 class TrimDrag : public RegionDrag 787 { 788 public: 789 enum Operation { 790 StartTrim, 791 EndTrim 792 }; 793 794 TrimDrag (Editor *, ArdourCanvas::Item *, RegionView*, std::list<RegionView*> const &, bool preserve_fade_anchor = false); 795 796 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 797 void motion (GdkEvent *, bool); 798 void finished (GdkEvent *, bool); 799 void aborted (bool); 800 y_movement_matters()801 bool y_movement_matters () const { 802 return false; 803 } 804 allow_vertical_autoscroll()805 bool allow_vertical_autoscroll () const { 806 return false; 807 } 808 809 void setup_pointer_sample_offset (); 810 811 private: 812 813 Operation _operation; 814 815 bool _preserve_fade_anchor; 816 bool _jump_position_when_done; 817 }; 818 819 /** Meter marker drag */ 820 class MeterMarkerDrag : public Drag 821 { 822 public: 823 MeterMarkerDrag (Editor *, ArdourCanvas::Item *, bool); 824 825 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 826 void motion (GdkEvent *, bool); 827 void finished (GdkEvent *, bool); 828 void aborted (bool); 829 allow_vertical_autoscroll()830 bool allow_vertical_autoscroll () const { 831 return false; 832 } 833 y_movement_matters()834 bool y_movement_matters () const { 835 return false; 836 } 837 838 void setup_pointer_sample_offset (); 839 840 private: 841 MeterMarker* _marker; 842 ARDOUR::MeterSection* _real_section; 843 844 bool _copy; 845 Editing::GridType _old_grid_type; 846 Editing::SnapMode _old_snap_mode; 847 XMLNode* before_state; 848 }; 849 850 /** Tempo marker drag */ 851 class TempoMarkerDrag : public Drag 852 { 853 public: 854 TempoMarkerDrag (Editor *, ArdourCanvas::Item *, bool); 855 856 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 857 void motion (GdkEvent *, bool); 858 void finished (GdkEvent *, bool); 859 void aborted (bool); 860 allow_vertical_autoscroll()861 bool allow_vertical_autoscroll () const { 862 return false; 863 } 864 y_movement_matters()865 bool y_movement_matters () const { 866 return true; 867 } 868 869 void setup_pointer_sample_offset (); 870 871 private: 872 TempoMarker* _marker; 873 ARDOUR::TempoSection* _real_section; 874 875 bool _copy; 876 bool _movable; 877 ARDOUR::Tempo _grab_bpm; 878 double _grab_qn; 879 XMLNode* _before_state; 880 }; 881 882 /** BBT Ruler drag */ 883 class BBTRulerDrag : public Drag 884 { 885 public: 886 BBTRulerDrag (Editor *, ArdourCanvas::Item *); 887 888 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 889 void motion (GdkEvent *, bool); 890 void finished (GdkEvent *, bool); 891 void aborted (bool); 892 allow_vertical_autoscroll()893 bool allow_vertical_autoscroll () const { 894 return false; 895 } 896 y_movement_matters()897 bool y_movement_matters () const { 898 return false; 899 } 900 901 void setup_pointer_sample_offset (); 902 903 private: 904 double _grab_qn; 905 ARDOUR::TempoSection* _tempo; 906 XMLNode* _before_state; 907 bool _drag_valid; 908 }; 909 910 /** tempo curve twist drag */ 911 class TempoTwistDrag : public Drag 912 { 913 public: 914 TempoTwistDrag (Editor *, ArdourCanvas::Item *); 915 916 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 917 void motion (GdkEvent *, bool); 918 void finished (GdkEvent *, bool); 919 void aborted (bool); 920 allow_vertical_autoscroll()921 bool allow_vertical_autoscroll () const { 922 return false; 923 } 924 y_movement_matters()925 bool y_movement_matters () const { 926 return true; 927 } 928 929 void setup_pointer_sample_offset (); 930 931 private: 932 double _grab_qn; 933 ARDOUR::Tempo _grab_tempo; 934 ARDOUR::TempoSection* _tempo; 935 ARDOUR::TempoSection* _next_tempo; 936 bool _drag_valid; 937 XMLNode* _before_state; 938 }; 939 940 941 /** tempo curve twist drag */ 942 class TempoEndDrag : public Drag 943 { 944 public: 945 TempoEndDrag (Editor *, ArdourCanvas::Item *); 946 947 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 948 void motion (GdkEvent *, bool); 949 void finished (GdkEvent *, bool); 950 void aborted (bool); 951 allow_vertical_autoscroll()952 bool allow_vertical_autoscroll () const { 953 return false; 954 } 955 y_movement_matters()956 bool y_movement_matters () const { 957 return true; 958 } 959 960 void setup_pointer_sample_offset (); 961 962 private: 963 double _grab_qn; 964 ARDOUR::TempoSection* _tempo; 965 XMLNode* _before_state; 966 bool _drag_valid; 967 }; 968 969 /** Drag of the playhead cursor */ 970 class CursorDrag : public Drag 971 { 972 public: 973 CursorDrag (Editor *, EditorCursor&, bool); 974 975 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 976 void motion (GdkEvent *, bool); 977 void finished (GdkEvent *, bool); 978 void aborted (bool); 979 allow_vertical_autoscroll()980 bool allow_vertical_autoscroll () const { 981 return false; 982 } 983 y_movement_matters()984 bool y_movement_matters () const { 985 return true; 986 } 987 988 private: 989 void fake_locate (samplepos_t); 990 991 EditorCursor& _cursor; 992 bool _stop; ///< true to stop the transport on starting the drag, otherwise false 993 double _grab_zoom; ///< editor samples per unit when our grab started 994 995 //used for zooming 996 int _last_mx; 997 int _last_my; 998 int _last_dx; 999 int _last_y_delta; 1000 }; 1001 1002 /** Region fade-in drag */ 1003 class FadeInDrag : public RegionDrag 1004 { 1005 public: 1006 FadeInDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); 1007 1008 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1009 void motion (GdkEvent *, bool); 1010 void finished (GdkEvent *, bool); 1011 void aborted (bool); 1012 y_movement_matters()1013 bool y_movement_matters () const { 1014 return false; 1015 } 1016 allow_vertical_autoscroll()1017 bool allow_vertical_autoscroll () const { 1018 return false; 1019 } 1020 1021 void setup_pointer_sample_offset (); 1022 }; 1023 1024 /** Region fade-out drag */ 1025 class FadeOutDrag : public RegionDrag 1026 { 1027 public: 1028 FadeOutDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); 1029 1030 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1031 void motion (GdkEvent *, bool); 1032 void finished (GdkEvent *, bool); 1033 void aborted (bool); 1034 y_movement_matters()1035 bool y_movement_matters () const { 1036 return false; 1037 } 1038 allow_vertical_autoscroll()1039 bool allow_vertical_autoscroll () const { 1040 return false; 1041 } 1042 1043 void setup_pointer_sample_offset (); 1044 }; 1045 1046 /** Marker drag */ 1047 class MarkerDrag : public Drag 1048 { 1049 public: 1050 MarkerDrag (Editor *, ArdourCanvas::Item *); 1051 ~MarkerDrag (); 1052 1053 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1054 void motion (GdkEvent *, bool); 1055 void finished (GdkEvent *, bool); 1056 void aborted (bool); 1057 allow_vertical_autoscroll()1058 bool allow_vertical_autoscroll () const { 1059 return false; 1060 } 1061 y_movement_matters()1062 bool y_movement_matters () const { 1063 return false; 1064 } 1065 1066 void setup_pointer_sample_offset (); 1067 void setup_video_sample_offset (); 1068 1069 private: 1070 void update_item (ARDOUR::Location *); 1071 1072 ArdourMarker* _marker; ///< marker being dragged 1073 bool _selection_changed; 1074 struct CopiedLocationMarkerInfo { 1075 ARDOUR::Location* location; 1076 std::vector<ArdourMarker*> markers; 1077 bool move_both; 1078 CopiedLocationMarkerInfo (ARDOUR::Location* l, ArdourMarker* m); 1079 }; 1080 1081 typedef std::list<CopiedLocationMarkerInfo> CopiedLocationInfo; 1082 CopiedLocationInfo _copied_locations; 1083 ArdourCanvas::Points _points; 1084 }; 1085 1086 /** Control point drag */ 1087 class ControlPointDrag : public Drag 1088 { 1089 public: 1090 ControlPointDrag (Editor *, ArdourCanvas::Item *); 1091 1092 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1093 void motion (GdkEvent *, bool); 1094 void finished (GdkEvent *, bool); 1095 void aborted (bool); 1096 1097 bool active (Editing::MouseMode m); 1098 allow_vertical_autoscroll()1099 bool allow_vertical_autoscroll () const { 1100 return false; 1101 } 1102 1103 1104 private: 1105 1106 ControlPoint* _point; 1107 double _fixed_grab_x; 1108 double _fixed_grab_y; 1109 double _cumulative_x_drag; 1110 double _cumulative_y_drag; 1111 bool _pushing; 1112 uint32_t _final_index; 1113 static double _zero_gain_fraction; 1114 }; 1115 1116 /** Gain or automation line drag */ 1117 class LineDrag : public Drag 1118 { 1119 public: 1120 LineDrag (Editor *e, ArdourCanvas::Item *i); 1121 1122 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1123 void motion (GdkEvent *, bool); 1124 void finished (GdkEvent *, bool); 1125 void aborted (bool); 1126 allow_vertical_autoscroll()1127 bool allow_vertical_autoscroll () const { 1128 return false; 1129 } 1130 1131 private: 1132 1133 AutomationLine* _line; 1134 double _fixed_grab_x; 1135 double _fixed_grab_y; 1136 double _cumulative_y_drag; 1137 uint32_t _before; 1138 uint32_t _after; 1139 }; 1140 1141 /** Transient feature line drags*/ 1142 class FeatureLineDrag : public Drag 1143 { 1144 public: 1145 FeatureLineDrag (Editor *e, ArdourCanvas::Item *i); 1146 1147 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1148 void motion (GdkEvent *, bool); 1149 void finished (GdkEvent *, bool); 1150 void aborted (bool); 1151 1152 private: 1153 1154 ArdourCanvas::Line* _line; 1155 AudioRegionView* _arv; 1156 1157 double _region_view_grab_x; 1158 double _cumulative_x_drag; 1159 1160 float _before; 1161 uint32_t _max_x; 1162 }; 1163 1164 /** Dragging of a rubberband rectangle for selecting things */ 1165 class RubberbandSelectDrag : public Drag 1166 { 1167 public: 1168 RubberbandSelectDrag (Editor *, ArdourCanvas::Item *); 1169 1170 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1171 void motion (GdkEvent *, bool); 1172 void finished (GdkEvent *, bool); 1173 void aborted (bool); 1174 1175 /** @return minimum number of pixels (x, y) that should be considered a movement */ move_threshold()1176 std::pair<int, int> move_threshold () const { 1177 return std::make_pair (1, 1); 1178 } 1179 1180 void do_select_things (GdkEvent *, bool); 1181 1182 /** Select some things within a rectangle. 1183 * @param button_state The button state from the GdkEvent. 1184 * @param x1 The left-hand side of the rectangle in session samples. 1185 * @param x2 The right-hand side of the rectangle in session samples. 1186 * @param y1 The top of the rectangle in trackview coordinates. 1187 * @param y2 The bottom of the rectangle in trackview coordinates. 1188 * @param drag_in_progress true if the drag is currently happening. 1189 */ 1190 virtual void select_things (int button_state, samplepos_t x1, samplepos_t x2, double y1, double y2, bool drag_in_progress) = 0; 1191 1192 virtual void deselect_things () = 0; 1193 1194 protected: 1195 bool _vertical_only; 1196 }; 1197 1198 /** A general editor RubberbandSelectDrag (for regions, automation points etc.) */ 1199 class EditorRubberbandSelectDrag : public RubberbandSelectDrag 1200 { 1201 public: 1202 EditorRubberbandSelectDrag (Editor *, ArdourCanvas::Item *); 1203 1204 void select_things (int, samplepos_t, samplepos_t, double, double, bool); 1205 void deselect_things (); 1206 }; 1207 1208 /** A RubberbandSelectDrag for selecting MIDI notes */ 1209 class MidiRubberbandSelectDrag : public RubberbandSelectDrag 1210 { 1211 public: 1212 MidiRubberbandSelectDrag (Editor *, MidiRegionView *); 1213 1214 void select_things (int, samplepos_t, samplepos_t, double, double, bool); 1215 void deselect_things (); 1216 1217 private: 1218 MidiRegionView* _region_view; 1219 }; 1220 1221 /** A RubberbandSelectDrag for selecting MIDI notes but with no horizonal component */ 1222 class MidiVerticalSelectDrag : public RubberbandSelectDrag 1223 { 1224 public: 1225 MidiVerticalSelectDrag (Editor *, MidiRegionView *); 1226 1227 void select_things (int, samplepos_t, samplepos_t, double, double, bool); 1228 void deselect_things (); 1229 1230 private: 1231 MidiRegionView* _region_view; 1232 }; 1233 1234 /** Region drag in time-FX mode */ 1235 class TimeFXDrag : public RegionDrag 1236 { 1237 public: 1238 TimeFXDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &); 1239 1240 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1241 void motion (GdkEvent *, bool); 1242 void finished (GdkEvent *, bool); 1243 void aborted (bool); 1244 }; 1245 1246 /** Scrub drag in audition mode */ 1247 class ScrubDrag : public Drag 1248 { 1249 public: 1250 ScrubDrag (Editor *, ArdourCanvas::Item *); 1251 1252 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1253 void motion (GdkEvent *, bool); 1254 void finished (GdkEvent *, bool); 1255 void aborted (bool); 1256 }; 1257 1258 /** Drag in range select mode */ 1259 class SelectionDrag : public Drag 1260 { 1261 public: 1262 enum Operation { 1263 CreateSelection, 1264 SelectionStartTrim, 1265 SelectionEndTrim, 1266 SelectionMove, 1267 SelectionExtend 1268 }; 1269 1270 SelectionDrag (Editor *, ArdourCanvas::Item *, Operation); 1271 1272 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1273 void motion (GdkEvent *, bool); 1274 void finished (GdkEvent *, bool); 1275 void aborted (bool); 1276 1277 void setup_pointer_sample_offset (); 1278 1279 private: 1280 Operation _operation; 1281 bool _add; 1282 TrackSelection _track_selection_at_start; 1283 bool _time_selection_at_start; 1284 samplepos_t start_at_start; 1285 samplepos_t end_at_start; 1286 }; 1287 1288 /** Range marker drag */ 1289 class RangeMarkerBarDrag : public Drag 1290 { 1291 public: 1292 enum Operation { 1293 CreateSkipMarker, 1294 CreateRangeMarker, 1295 CreateTransportMarker, 1296 CreateCDMarker 1297 }; 1298 1299 RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation); 1300 ~RangeMarkerBarDrag (); 1301 1302 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1303 void motion (GdkEvent *, bool); 1304 void finished (GdkEvent *, bool); 1305 void aborted (bool); 1306 allow_vertical_autoscroll()1307 bool allow_vertical_autoscroll () const { 1308 return false; 1309 } 1310 y_movement_matters()1311 bool y_movement_matters () const { 1312 return false; 1313 } 1314 1315 private: 1316 void update_item (ARDOUR::Location *); 1317 1318 Operation _operation; 1319 ArdourCanvas::Rectangle* _drag_rect; 1320 bool _copy; 1321 }; 1322 1323 /** Drag of rectangle to set zoom */ 1324 class MouseZoomDrag : public Drag 1325 { 1326 public: 1327 MouseZoomDrag (Editor *, ArdourCanvas::Item *); 1328 1329 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1330 void motion (GdkEvent *, bool); 1331 void finished (GdkEvent *, bool); 1332 void aborted (bool); 1333 1334 /** @return minimum number of pixels (x, y) that should be considered a movement */ move_threshold()1335 std::pair<int, int> move_threshold () const { 1336 return std::make_pair (4, 4); 1337 } 1338 1339 private: 1340 bool _zoom_out; 1341 }; 1342 1343 /** Drag of a range of automation data (either on an automation track or region gain), 1344 * changing value but not position. 1345 */ 1346 class AutomationRangeDrag : public Drag 1347 { 1348 public: 1349 AutomationRangeDrag (Editor *, AutomationTimeAxisView *, std::list<ARDOUR::AudioRange> const &); 1350 AutomationRangeDrag (Editor *, std::list<RegionView*> const &, std::list<ARDOUR::AudioRange> const &, double y_origin, double y_height); 1351 1352 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1353 void motion (GdkEvent *, bool); 1354 void finished (GdkEvent *, bool); 1355 void aborted (bool); 1356 x_movement_matters()1357 bool x_movement_matters () const { 1358 return false; 1359 } 1360 1361 private: 1362 void setup (std::list<boost::shared_ptr<AutomationLine> > const &); 1363 double y_fraction (double global_y_position) const; 1364 double value (boost::shared_ptr<ARDOUR::AutomationList> list, double x) const; 1365 1366 std::list<ARDOUR::AudioRange> _ranges; 1367 1368 /** A line that is part of the drag */ 1369 struct Line { 1370 boost::shared_ptr<AutomationLine> line; ///< the line 1371 std::list<ControlPoint*> points; ///< points to drag on the line 1372 std::pair<ARDOUR::samplepos_t, ARDOUR::samplepos_t> range; ///< the range of all points on the line, in session samples 1373 XMLNode* state; ///< the XML state node before the drag 1374 }; 1375 1376 std::list<Line> _lines; 1377 double _y_origin; 1378 double _y_height; 1379 bool _nothing_to_drag; 1380 bool _integral; 1381 }; 1382 1383 /** Drag of one edge of an xfade 1384 */ 1385 class CrossfadeEdgeDrag : public Drag 1386 { 1387 public: 1388 CrossfadeEdgeDrag (Editor*, AudioRegionView*, ArdourCanvas::Item*, bool start); 1389 1390 void start_grab (GdkEvent*, Gdk::Cursor* c = 0); 1391 void motion (GdkEvent*, bool); 1392 void finished (GdkEvent*, bool); 1393 void aborted (bool); 1394 y_movement_matters()1395 bool y_movement_matters () const { 1396 return false; 1397 } 1398 move_threshold()1399 virtual std::pair<int, int> move_threshold () const { 1400 return std::make_pair (1, 4); 1401 } 1402 1403 private: 1404 AudioRegionView* arv; 1405 bool start; 1406 }; 1407 1408 class RegionMarkerDrag : public Drag 1409 { 1410 public: 1411 RegionMarkerDrag (Editor*, RegionView*, ArdourCanvas::Item*); 1412 ~RegionMarkerDrag (); 1413 1414 void start_grab (GdkEvent *, Gdk::Cursor* c = 0); 1415 void motion (GdkEvent *, bool); 1416 void finished (GdkEvent *, bool); 1417 void aborted (bool); 1418 allow_vertical_autoscroll()1419 bool allow_vertical_autoscroll () const { 1420 return false; 1421 } 1422 y_movement_matters()1423 bool y_movement_matters () const { 1424 return false; 1425 } 1426 1427 void setup_pointer_sample_offset (); 1428 1429 private: 1430 RegionView* rv; 1431 ArdourMarker* view; 1432 ARDOUR::CueMarker model; 1433 ARDOUR::CueMarker dragging_model; 1434 }; 1435 1436 #endif /* __gtk2_ardour_editor_drag_h_ */ 1437