diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc index 0acd002de7..ed1283e024 100644 --- a/gtk2_ardour/automation_region_view.cc +++ b/gtk2_ardour/automation_region_view.cc @@ -104,7 +104,7 @@ AutomationRegionView::canvas_event (GdkEvent* ev) if (ev->type == GDK_BUTTON_PRESS && e.current_mouse_mode() == Editing::MouseObject) { /* XXX: icky dcast to Editor */ - e.drags()->set (new RubberbandSelectDrag (dynamic_cast (&e), group), ev); + e.drags()->set (new EditorRubberbandSelectDrag (dynamic_cast (&e), group), ev); } else if (ev->type == GDK_BUTTON_RELEASE) { diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index e799e89664..cc6917cf77 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -2084,6 +2084,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD friend class ControlPointDrag; friend class LineDrag; friend class RubberbandSelectDrag; + friend class EditorRubberbandSelectDrag; friend class TimeFXDrag; friend class ScrubDrag; friend class SelectionDrag; diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index bba3938d52..435137168c 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3100,45 +3100,51 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool) _editor->rubberband_rect->raise_to_top(); show_verbose_cursor_time (pf); + + do_select_things (event, true); } } +void +RubberbandSelectDrag::do_select_things (GdkEvent* event, bool drag_in_progress) +{ + framepos_t x1; + framepos_t x2; + + if (grab_frame() < last_pointer_frame()) { + x1 = grab_frame (); + x2 = last_pointer_frame (); + } else { + x2 = grab_frame (); + x1 = last_pointer_frame (); + } + + double y1; + double y2; + + if (_drags->current_pointer_y() < grab_y()) { + y1 = _drags->current_pointer_y(); + y2 = grab_y(); + } else { + y2 = _drags->current_pointer_y(); + y1 = grab_y(); + } + + select_things (event->button.state, x1, x2, y1, y2, drag_in_progress); +} + void RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred) { if (movement_occurred) { motion (event, false); - - double y1,y2; - if (_drags->current_pointer_y() < grab_y()) { - y1 = _drags->current_pointer_y(); - y2 = grab_y(); - } else { - y2 = _drags->current_pointer_y(); - y1 = grab_y(); - } - - - Selection::Operation op = ArdourKeyboard::selection_type (event->button.state); - - _editor->begin_reversible_command (_("rubberband selection")); - - if (grab_frame() < last_pointer_frame()) { - _editor->select_all_within (grab_frame(), last_pointer_frame() - 1, y1, y2, _editor->track_views, op, false); - } else { - _editor->select_all_within (last_pointer_frame(), grab_frame() - 1, y1, y2, _editor->track_views, op, false); - } - - _editor->commit_reversible_command (); + do_select_things (event, false); } else { - if (!getenv("ARDOUR_SAE")) { - _editor->selection->clear_tracks(); - } - _editor->selection->clear_regions(); - _editor->selection->clear_points (); - _editor->selection->clear_lines (); + + deselect_things (); + } _editor->rubberband_rect->hide(); @@ -4227,3 +4233,67 @@ PatchChangeDrag::setup_pointer_frame_offset () _pointer_frame_offset = raw_grab_frame() - _region_view->source_beats_to_absolute_frames (_patch_change->patch()->time()); } +MidiRubberbandSelectDrag::MidiRubberbandSelectDrag (Editor* e, MidiRegionView* rv) + : RubberbandSelectDrag (e, rv->get_canvas_frame ()) + , _region_view (rv) +{ + +} + +void +MidiRubberbandSelectDrag::select_things (int button_state, framepos_t x1, framepos_t x2, double y1, double y2, bool drag_in_progress) +{ + framepos_t const p = _region_view->region()->position (); + double const y = _region_view->midi_view()->y_position (); + + x1 = max ((framepos_t) 0, x1 - p); + x2 = max ((framepos_t) 0, x2 - p); + y1 = max (0.0, y1 - y); + y2 = max (0.0, y2 - y); + + _region_view->update_drag_selection ( + _editor->frame_to_pixel (x1), + _editor->frame_to_pixel (x2), + y1, + y2, + Keyboard::modifier_state_contains (button_state, Keyboard::TertiaryModifier) + ); +} + +void +MidiRubberbandSelectDrag::deselect_things () +{ + /* XXX */ +} + +EditorRubberbandSelectDrag::EditorRubberbandSelectDrag (Editor* e, ArdourCanvas::Item* i) + : RubberbandSelectDrag (e, i) +{ + +} + +void +EditorRubberbandSelectDrag::select_things (int button_state, framepos_t x1, framepos_t x2, double y1, double y2, bool drag_in_progress) +{ + if (drag_in_progress) { + /* We just want to select things at the end of the drag, not during it */ + return; + } + + Selection::Operation op = ArdourKeyboard::selection_type (button_state); + + _editor->begin_reversible_command (_("rubberband selection")); + _editor->select_all_within (x1, x2 - 1, y1, y2, _editor->track_views, op, false); + _editor->commit_reversible_command (); +} + +void +EditorRubberbandSelectDrag::deselect_things () +{ + if (!getenv("ARDOUR_SAE")) { + _editor->selection->clear_tracks(); + } + _editor->selection->clear_regions(); + _editor->selection->clear_points (); + _editor->selection->clear_lines (); +} diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 8bc52bc056..44b2d50767 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -761,6 +761,43 @@ public: std::pair move_threshold () const { return std::make_pair (8, 1); } + + void do_select_things (GdkEvent *, bool); + + /** Select some things within a rectangle. + * @param button_state The button state from the GdkEvent. + * @param x1 The left-hand side of the rectangle in session frames. + * @param x2 The right-hand side of the rectangle in session frames. + * @param y1 The top of the rectangle in trackview coordinates. + * @param y2 The bottom of the rectangle in trackview coordinates. + * @param drag_in_progress true if the drag is currently happening. + */ + virtual void select_things (int button_state, framepos_t x1, framepos_t x2, double y1, double y2, bool drag_in_progress) = 0; + + virtual void deselect_things () = 0; +}; + +/** A general editor RubberbandSelectDrag (for regions, automation points etc.) */ +class EditorRubberbandSelectDrag : public RubberbandSelectDrag +{ +public: + EditorRubberbandSelectDrag (Editor *, ArdourCanvas::Item *); + + void select_things (int, framepos_t, framepos_t, double, double, bool); + void deselect_things (); +}; + +/** A RubberbandSelectDrag for selecting MIDI notes */ +class MidiRubberbandSelectDrag : public RubberbandSelectDrag +{ +public: + MidiRubberbandSelectDrag (Editor *, MidiRegionView *); + + void select_things (int, framepos_t, framepos_t, double, double, bool); + void deselect_things (); + +private: + MidiRegionView* _region_view; }; /** Region drag in time-FX mode */ diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index e039983a67..b47934554c 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -792,7 +792,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) && event->type == GDK_BUTTON_PRESS) { - _drags->set (new RubberbandSelectDrag (this, item), event); + _drags->set (new EditorRubberbandSelectDrag (this, item), event); } else if (event->type == GDK_BUTTON_PRESS) { @@ -888,7 +888,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT } return true; } else { - _drags->set (new RubberbandSelectDrag (this, item), event); + _drags->set (new EditorRubberbandSelectDrag (this, item), event); } break; @@ -902,7 +902,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT _drags->set (new RegionCreateDrag (this, item, parent), event); } else { /* rubberband drag to select automation points */ - _drags->set (new RubberbandSelectDrag (this, item), event); + _drags->set (new EditorRubberbandSelectDrag (this, item), event); } break; } diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 11833656d8..6bb1eb98e7 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -51,6 +51,7 @@ #include "canvas_patch_change.h" #include "debug.h" #include "editor.h" +#include "editor_drag.h" #include "ghostregion.h" #include "gui_thread.h" #include "keyboard.h" @@ -462,10 +463,12 @@ MidiRegionView::button_release (GdkEventButton* ev) group->w2i(event_x, event_y); group->ungrab(ev->time); + PublicEditor& editor = trackview.editor (); + switch (_mouse_state) { case Pressed: // Clicked - switch (trackview.editor().current_mouse_mode()) { + switch (editor.current_mouse_mode()) { case MouseObject: case MouseTimeFX: { @@ -480,7 +483,7 @@ MidiRegionView::button_release (GdkEventButton* ev) group->w2i(event_x, event_y); bool success; - Evoral::MusicalTime beats = trackview.editor().get_grid_type_as_beats (success, trackview.editor().pixel_to_frame (event_x)); + Evoral::MusicalTime beats = editor.get_grid_type_as_beats (success, editor.pixel_to_frame (event_x)); if (!success) { beats = 1; @@ -494,7 +497,7 @@ MidiRegionView::button_release (GdkEventButton* ev) case MouseRange: { bool success; - Evoral::MusicalTime beats = trackview.editor().get_grid_type_as_beats (success, trackview.editor().pixel_to_frame (event_x)); + Evoral::MusicalTime beats = editor.get_grid_type_as_beats (success, editor.pixel_to_frame (event_x)); if (!success) { beats = 1; @@ -512,10 +515,8 @@ MidiRegionView::button_release (GdkEventButton* ev) break; case SelectRectDragging: // Select drag done - + editor.drags()->end_grab ((GdkEvent *) ev); _mouse_state = None; - delete _drag_rect; - _drag_rect = 0; break; case AddDragging: // Add drag done @@ -596,27 +597,8 @@ MidiRegionView::motion (GdkEventMotion* ev) if (_pressed_button == 1 && editor.current_mouse_mode() == MouseObject && !Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier())) { - // Select drag start - - group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, - Gdk::Cursor(Gdk::FLEUR), ev->time); - - _last_x = event_x; - _last_y = event_y; - _drag_start_x = event_x; - _drag_start_y = event_y; - - _drag_rect = new ArdourCanvas::SimpleRect(*group); - _drag_rect->property_x1() = event_x; - _drag_rect->property_y1() = event_y; - _drag_rect->property_x2() = event_x; - _drag_rect->property_y2() = event_y; - _drag_rect->property_outline_what() = 0xFF; - _drag_rect->property_outline_color_rgba() - = ARDOUR_UI::config()->canvasvar_MidiSelectRectOutline.get(); - _drag_rect->property_fill_color_rgba() - = ARDOUR_UI::config()->canvasvar_MidiSelectRectFill.get(); + editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast (&editor), this), (GdkEvent *) ev); _mouse_state = SelectRectDragging; return true; @@ -656,7 +638,10 @@ MidiRegionView::motion (GdkEventMotion* ev) return false; - case SelectRectDragging: // Select drag motion + case SelectRectDragging: + editor.drags()->motion_handler ((GdkEvent *) ev, false); + break; + case AddDragging: // Add note drag motion if (ev->is_hint) { @@ -692,18 +677,6 @@ MidiRegionView::motion (GdkEventMotion* ev) } } - if (_drag_rect && _mouse_state == SelectRectDragging) { - - if (event_y > _drag_start_y) { - _drag_rect->property_y2() = event_y; - } - else { - _drag_rect->property_y1() = event_y; - } - - update_drag_selection(_drag_start_x, event_x, _drag_start_y, event_y, Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)); - } - _last_x = event_x; _last_y = event_y; diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 70939ac640..081a68e101 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -311,6 +311,8 @@ protected: private: + friend class MidiRubberbandSelectDrag; + /** Emitted when the selection has been cleared in one MidiRegionView */ static PBD::Signal1 SelectionCleared; PBD::ScopedConnection _selection_cleared_connection; diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index c8352150fc..4107097236 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -389,7 +389,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible { virtual Marker* find_marker_from_location_id (PBD::ID const &, bool) const = 0; virtual void snap_to_with_modifier (framepos_t &, GdkEvent const *, int32_t direction = 0, bool for_mark = false) = 0; - + /// Singleton instance, set up by Editor::Editor() static PublicEditor* _instance;