working track drag-n-drop, re-picked from a 2nd implementation on a branch
This commit is contained in:
parent
fdd91cc325
commit
f92d821a72
|
@ -6184,6 +6184,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 ()
|
||||
{
|
||||
|
@ -6200,21 +6248,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++;
|
||||
}
|
||||
|
||||
|
@ -7016,3 +7067,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<RouteTimeAxisView*> (&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;
|
||||
}
|
||||
|
|
|
@ -1416,8 +1416,7 @@ private:
|
|||
void start_track_drag (TimeAxisView&, int y, Gtk::Widget& w);
|
||||
void mid_track_drag (GdkEventMotion*, Gtk::Widget& e);
|
||||
void end_track_drag ();
|
||||
void maybe_place_drag_spacer ();
|
||||
void get_layout_relative_coordinates (Gtk::Widget&, int x, int y, int &xo, int &yo);
|
||||
void maybe_move_tracks ();
|
||||
bool track_dragging() const;
|
||||
|
||||
void do_insert_time ();
|
||||
|
@ -2607,29 +2606,27 @@ private:
|
|||
|
||||
struct TrackDrag {
|
||||
RouteTimeAxisView* track;
|
||||
Gtk::EventBox* spacer;
|
||||
GdkCursor* drag_cursor;
|
||||
GdkCursor* predrag_cursor;
|
||||
TimeAxisView* bump_track;
|
||||
int spacer_order;
|
||||
double start;
|
||||
double current;
|
||||
double previous;
|
||||
bool have_predrag_cursor;
|
||||
int direction;
|
||||
bool first_move;
|
||||
|
||||
TrackDrag (RouteTimeAxisView* rtav)
|
||||
: track (rtav)
|
||||
, spacer (nullptr)
|
||||
, drag_cursor (nullptr)
|
||||
, predrag_cursor (nullptr)
|
||||
, bump_track (nullptr)
|
||||
, spacer_order (-1)
|
||||
, start (-1.)
|
||||
, current (0.)
|
||||
, previous (0.)
|
||||
, have_predrag_cursor (false)
|
||||
, direction (0)
|
||||
, first_move (true)
|
||||
{}
|
||||
|
||||
};
|
||||
|
|
|
@ -591,7 +591,6 @@ public:
|
|||
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 void get_layout_relative_coordinates (Gtk::Widget&, int x, int y, int &xo, int &yo) = 0;
|
||||
virtual bool track_dragging() const = 0;
|
||||
|
||||
/// Singleton instance, set up by Editor::Editor()
|
||||
|
|
|
@ -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
|
||||
|
@ -519,28 +533,28 @@ bool
|
|||
TimeAxisView::controls_ebox_button_release (GdkEventButton* ev)
|
||||
{
|
||||
if (_editor.track_dragging()) {
|
||||
return false;
|
||||
_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 (_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
|
||||
if (!_ebox_release_can_act) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_ebox_release_can_act) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (ev->button) {
|
||||
case 1:
|
||||
if (selectable()) {
|
||||
|
|
Loading…
Reference in New Issue