diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index fe0a531630..c7f48904e3 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -280,8 +280,6 @@ public: void reset_focus (Gtk::Widget*); - static PublicEditor* _instance; - /** Emitted frequently with the audible sample, false, and the edit point as * parameters respectively. * diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 9fe579eebc..8415b6b032 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -478,6 +478,7 @@ Editor::Editor () , quantize_dialog (0) , _main_menu_disabler (0) , domain_bounce_info (nullptr) + , track_drag (nullptr) { /* we are a singleton */ @@ -4368,6 +4369,11 @@ Editor::override_visible_track_count () bool Editor::edit_controls_button_event (GdkEventButton* ev) { + if (ev->type == GDK_BUTTON_RELEASE && track_dragging()) { + end_track_drag (); + return true; + } + if ((ev->type == GDK_2BUTTON_PRESS && ev->button == 1) || (ev->type == GDK_BUTTON_RELEASE && Keyboard::is_context_menu_event (ev))) { ARDOUR_UI::instance()->add_route (); } else if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS) { @@ -6270,6 +6276,54 @@ struct TrackViewStripableSorter } }; +static const int track_drag_spacer_height = 25; + +void +Editor::maybe_move_tracks () +{ + for (auto & tv : track_views) { + + if (!tv->marked_for_display () || (tv == track_drag->track)) { + continue; + } + + /* find the track the mouse pointer is within, and if + * we're in the upper or lower half of it (depending on + * drag direction, move the spacer. + */ + + if (track_drag->current >= tv->y_position() && track_drag->current < (tv->y_position() + tv->effective_height())) { + + if (track_drag->bump_track == tv) { + /* already bumped for this track */ + break; + } + + if (track_drag->direction < 0) { + + /* dragging up */ + + if (track_drag->current < (tv->y_position() + (tv->effective_height() / 2))) { + /* in top half of this track, move spacer */ + track_drag->bump_track = tv; + move_selected_tracks (true); + } + + } else if (track_drag->direction > 0) { + + /* dragging down */ + + if (track_drag->current > (tv->y_position() + (tv->effective_height() / 2))) { + track_drag->bump_track = tv; + move_selected_tracks (false); + } + } + + break; + } + } +} + bool Editor::redisplay_track_views () { @@ -6286,21 +6340,24 @@ Editor::redisplay_track_views () track_views.sort (TrackViewStripableSorter ()); - uint32_t position; - TrackViewList::const_iterator i; + if (track_drag) { // && track_drag->spacer) { + maybe_move_tracks (); + } /* n will be the count of tracks plus children (updated by TimeAxisView::show_at), * so we will use that to know where to put things. */ - int n; - for (n = 0, position = 0, i = track_views.begin(); i != track_views.end(); ++i) { - TimeAxisView *tv = (*i); + int n = 0; + uint32_t position = 0; + + for (auto & tv : track_views) { if (tv->marked_for_display ()) { position += tv->show_at (position, n, &edit_controls_vbox); } else { tv->hide (); } + n++; } @@ -7104,3 +7161,74 @@ Editor::default_time_domain () const } return BeatTime; } + +void +Editor::start_track_drag (TimeAxisView& tav, int y, Gtk::Widget& w) +{ + track_drag = new TrackDrag (dynamic_cast (&tav)); + + track_drag->drag_cursor = _cursors->move->gobj(); + track_drag->predrag_cursor = gdk_window_get_cursor (edit_controls_vbox.get_window()->gobj()); + + gdk_window_set_cursor (edit_controls_vbox.get_toplevel()->get_window()->gobj(), track_drag->drag_cursor); + + int xo, yo; + w.translate_coordinates (edit_controls_vbox, 0, y, xo, yo); + + track_drag->have_predrag_cursor = true; + track_drag->bump_track = nullptr; + track_drag->previous = yo; + track_drag->start = yo; +} + +void +Editor::mid_track_drag (GdkEventMotion* ev, Gtk::Widget& w) +{ + int xo, yo; + w.translate_coordinates (edit_controls_vbox, ev->x, ev->y, xo, yo); + + if (track_drag->first_move) { + if (!track_drag->track->selected()) { + set_selected_track (*track_drag->track, Selection::Set, false); + } + track_drag->first_move = false; + } + + track_drag->current = yo; + + if (track_drag->current > track_drag->previous) { + if (track_drag->direction != 1) { + track_drag->bump_track = nullptr; + track_drag->direction = 1; + } + } else if (track_drag->current < track_drag->previous) { + if (track_drag->direction != -1) { + track_drag->bump_track = nullptr; + track_drag->direction = -1; + } + } + + if (track_drag->current == track_drag->previous) { + return; + } + + redisplay_track_views (); + track_drag->previous = yo; +} + +void +Editor::end_track_drag () +{ + if (track_drag->have_predrag_cursor) { + gdk_window_set_cursor (edit_controls_vbox.get_toplevel()->get_window()->gobj(), track_drag->predrag_cursor); + } + + delete track_drag; + track_drag = nullptr; +} + +bool +Editor::track_dragging() const +{ + return (bool) track_drag; +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 49e40e0efe..7699d875ed 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1411,6 +1411,11 @@ private: void insert_patch_change (bool from_context); void fork_selected_regions (); void fork_regions_from_unselected (); + void start_track_drag (TimeAxisView&, int y, Gtk::Widget& w); + void mid_track_drag (GdkEventMotion*, Gtk::Widget& e); + void end_track_drag (); + void maybe_move_tracks (); + bool track_dragging() const; void do_insert_time (); void insert_time (Temporal::timepos_t const &, Temporal::timecnt_t const &, Editing::InsertTimeOption, bool, bool, bool, bool); @@ -2594,6 +2599,35 @@ private: friend class Drag; friend class RegionCutDrag; friend class RegionDrag; + + struct TrackDrag { + RouteTimeAxisView* track; + GdkCursor* drag_cursor; + GdkCursor* predrag_cursor; + TimeAxisView* bump_track; + double start; + double current; + double previous; + bool have_predrag_cursor; + int direction; + bool first_move; + + TrackDrag (RouteTimeAxisView* rtav) + : track (rtav) + , drag_cursor (nullptr) + , predrag_cursor (nullptr) + , bump_track (nullptr) + , start (-1.) + , current (0.) + , previous (0.) + , have_predrag_cursor (false) + , direction (0) + , first_move (true) + {} + + }; + TrackDrag* track_drag; + friend class RegionMoveDrag; friend class TrimDrag; friend class MappingTwistDrag; diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index c12cf6e9a6..b0bf6a0414 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -589,6 +589,11 @@ public: virtual void set_tempo_curve_range (double& max, double& min) const = 0; + virtual void start_track_drag (TimeAxisView&, int y, Gtk::Widget&) = 0; + virtual void mid_track_drag (GdkEventMotion*, Gtk::Widget&) = 0; + virtual void end_track_drag () = 0; + virtual bool track_dragging() const = 0; + /// Singleton instance, set up by Editor::Editor() static PublicEditor* _instance; diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 2f3432c46d..ccb7fbedd8 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -438,7 +438,13 @@ TimeAxisView::controls_ebox_button_press (GdkEventButton* event) _ebox_release_can_act = true; if (maybe_set_cursor (event->y) > 0) { + _resize_drag_start = event->y_root; + + } else { + if (event->button == 1) { + _editor.start_track_drag (*this, event->y, controls_ebox); + } } return true; @@ -453,6 +459,12 @@ TimeAxisView::idle_resize (int32_t h) bool TimeAxisView::controls_ebox_motion (GdkEventMotion* ev) { + if (_editor.track_dragging()) { + _editor.mid_track_drag (ev, controls_ebox); + gdk_event_request_motions (ev); + return true; + } + if (_resize_drag_start >= 0) { /* (ab)use the DragManager to do autoscrolling - basically we @@ -468,13 +480,15 @@ TimeAxisView::controls_ebox_motion (GdkEventMotion* ev) _editor.add_to_idle_resize (this, delta); _resize_drag_start = ev->y_root; _did_resize = true; + gdk_event_request_motions (ev); + return true; } else { /* not dragging but ... */ maybe_set_cursor (ev->y); } - gdk_event_request_motions(ev); - return true; + gdk_event_request_motions (ev); + return false; } bool @@ -518,23 +532,27 @@ TimeAxisView::maybe_set_cursor (int y) bool TimeAxisView::controls_ebox_button_release (GdkEventButton* ev) { - if (_resize_drag_start >= 0) { - if (_have_preresize_cursor) { - gdk_window_set_cursor (controls_ebox.get_window()->gobj(), _preresize_cursor); - _preresize_cursor = 0; - _have_preresize_cursor = false; - } - _editor.stop_canvas_autoscroll (); - _resize_drag_start = -1; - if (_did_resize) { - _did_resize = false; - // don't change selection - return true; - } + if (_editor.track_dragging()) { + _editor.end_track_drag (); + } else { + if (_resize_drag_start >= 0) { + if (_have_preresize_cursor) { + gdk_window_set_cursor (controls_ebox.get_window()->gobj(), _preresize_cursor); + _preresize_cursor = 0; + _have_preresize_cursor = false; + } + _editor.stop_canvas_autoscroll (); + _resize_drag_start = -1; + if (_did_resize) { + _did_resize = false; + // don't change selection + return true; + } } - if (!_ebox_release_can_act) { - return true; + if (!_ebox_release_can_act) { + return true; + } } switch (ev->button) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 13184f3a87..102353344f 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -3941,8 +3941,6 @@ Session::cleanup_sources (CleanupReport& rep) } } - cerr << "Actually unused: " << unused.size() << endl; - if (unused.empty()) { /* Nothing to do */ ret = 0; diff --git a/libs/gtkmm2ext/utils.cc b/libs/gtkmm2ext/utils.cc index 9f24f928e3..144114251a 100644 --- a/libs/gtkmm2ext/utils.cc +++ b/libs/gtkmm2ext/utils.cc @@ -194,10 +194,10 @@ Gtkmm2ext::pixbuf_from_string(const string& name, const Pango::FontDescription& int width, height; pixel_size (name, font, width, height); if (clip_width <= 0) { - clip_width = width - clip_width; + clip_width = width - clip_width; /* this is an addition because clip_width is negative */ } if (clip_height <= 0) { - clip_height = height - clip_height; + clip_height = height - clip_height; /* this is an addition because clip_height is negative */ } }