summaryrefslogtreecommitdiff
path: root/gtk2_ardour/editor_drag.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-02-13 12:36:08 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2015-02-13 17:00:30 -0500
commit236f549caa4eb05550b316a49e7c17bdde6cf00e (patch)
tree225b5b436f1207a0c7c89db6dd22d65117ff16b3 /gtk2_ardour/editor_drag.cc
parent83044710626ca6f7ac3fb3f46609166c25f918f6 (diff)
insanely complex fixes for dragging to and from the drop zone.
This probably breaks some of ardour's functionality (e.g. layered mode), but seems to be either just right or very close to it for tracks Conflicts: gtk2_ardour/editor_routes.cc
Diffstat (limited to 'gtk2_ardour/editor_drag.cc')
-rw-r--r--gtk2_ardour/editor_drag.cc180
1 files changed, 150 insertions, 30 deletions
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 2fd642fb29..c09d92b6f9 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -645,14 +645,39 @@ RegionMotionDrag::y_movement_allowed (int delta_track, double delta_layer) const
if (_y_constrained) {
return false;
}
+
+ bool all_in_drop_zone = true;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- int const n = i->time_axis_view + delta_track;
- if (n < 0 || n >= int (_time_axis_views.size())) {
- /* off the top or bottom track */
- return false;
+ int n = i->time_axis_view + delta_track;
+ if (i->time_axis_view < 0) {
+ /* already in the drop zone */
+ if (delta_track > 0) {
+ /* downward motion - might be OK if others are still not in the dropzone,
+ so check at the end of the loop if that is the case.
+ */
+ continue;
+ }
+ /* upward motion, and this view is currently in the drop zone. That's fine, so
+ we have to set all_in_drop_zone correctly to avoid blocking upward motion.
+ */
+ all_in_drop_zone = false;
+ continue;
+ } else {
+
+ all_in_drop_zone = false;
+
+ if (n < 0) {
+ /* off the top */
+ return false;
+ }
}
+ if (n >= int (_time_axis_views.size())) {
+ /* downward motion into drop zone. That's fine. */
+ continue;
+ }
+
RouteTimeAxisView const * to = dynamic_cast<RouteTimeAxisView const *> (_time_axis_views[n]);
if (to == 0 || !to->is_track() || to->track()->data_type() != i->view->region()->data_type()) {
/* not a track, or the wrong type */
@@ -673,7 +698,7 @@ RegionMotionDrag::y_movement_allowed (int delta_track, double delta_layer) const
}
/* all regions being dragged are ok with this change */
- return true;
+ return !all_in_drop_zone;
}
void
@@ -681,15 +706,10 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
{
double delta_layer = 0;
int delta_time_axis_view = 0;
+ int current_pointer_time_axis_view;
assert (!_views.empty ());
- /* Note: time axis views in this method are often expressed as an index into the _time_axis_views vector */
-
- /* Find the TimeAxisView that the pointer is now over */
- pair<TimeAxisView*, double> const r = _editor->trackview_by_y_position (current_pointer_y ());
- TimeAxisView* tv = r.first;
-
if (first_move) {
if (_single_axis) {
if (initially_vertical()) {
@@ -702,6 +722,13 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
}
}
+ /* Note: time axis views in this method are often expressed as an index into the _time_axis_views vector */
+
+ /* Find the TimeAxisView that the pointer is now over */
+
+ pair<TimeAxisView*, double> const r = _editor->trackview_by_y_position (current_pointer_y ());
+ TimeAxisView* tv = r.first;
+
if (tv && tv->view()) {
double layer = r.second;
@@ -710,15 +737,22 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
}
/* Here's the current pointer position in terms of time axis view and layer */
- int const current_pointer_time_axis_view = find_time_axis_view (tv);
+ current_pointer_time_axis_view = find_time_axis_view (tv);
+
double const current_pointer_layer = tv->layer_display() == Overlaid ? 0 : layer;
/* Work out the change in y */
- delta_time_axis_view = current_pointer_time_axis_view - _last_pointer_time_axis_view;
+ if (_last_pointer_time_axis_view < 0) {
+ /* we can only move up */
+ delta_time_axis_view = -1;
+ } else {
+ delta_time_axis_view = current_pointer_time_axis_view - _last_pointer_time_axis_view;
+ }
+
delta_layer = current_pointer_layer - _last_pointer_layer;
}
-
+
/* Work out the change in x */
framepos_t pending_region_position;
double const x_delta = compute_x_delta (event, &pending_region_position);
@@ -738,8 +772,20 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
return;
}
- pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
+ typedef pair<int,double> NewTrackIndexAndPosition;
+ typedef map<boost::shared_ptr<Playlist>,NewTrackIndexAndPosition> PlaylistDropzoneMap;
+ PlaylistDropzoneMap playlist_dropzone_map;
+ int biggest_drop_zone_offset = 0;
+ Coord last_track_bottom_edge;
+
+ if (_time_axis_views.empty()) {
+ last_track_bottom_edge = 0;
+ } else {
+ TimeAxisView* last = _time_axis_views.back();
+ last_track_bottom_edge = last->canvas_display()->canvas_origin ().y + last->effective_height();
+ }
+
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
RegionView* rv = i->view;
@@ -785,11 +831,30 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
if (i->time_axis_view >= 0) {
track_index = i->time_axis_view + delta_time_axis_view;
} else {
- track_index = _time_axis_views.size() - 1 + delta_time_axis_view;
+ /* delta time axis view will be at least -1, because we can only
+ be moving up if some dragged views have i->time_axis_view negative.
+
+ the final real time axis view has index _time_axis_views.size() - 1.
+
+ so for DTAV = -1, the first drop zone track (i->tav == -1) should
+ move to the final TAV.
+
+ the second drop zone track should move to i->tav == -1 (i.e. becomes
+ the first drop zone track). and so on.
+ */
+
+ int index_from_bottom = i->time_axis_view - delta_time_axis_view;
+ int const bottom = _time_axis_views.size() - 1;
+
+ if (index_from_bottom >= 0) {
+ track_index = bottom - index_from_bottom;
+ } else {
+ track_index = index_from_bottom;
+ }
}
-
+
if (track_index < 0 || track_index >= (int) _time_axis_views.size()) {
- continue;
+ goto dropzone;
}
/* The TimeAxisView that this region is now over */
@@ -855,22 +920,49 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
} else {
- /* Only move the region into the empty dropzone at the bottom if the pointer
- * is down there.
- */
-
+ dropzone:
+
if (current_pointer_y() >= 0) {
- Coord last_track_bottom_edge;
- if (!_time_axis_views.empty()) {
- TimeAxisView* last = _time_axis_views.back();
- last_track_bottom_edge = last->canvas_display()->canvas_origin ().y + last->effective_height();
+ NewTrackIndexAndPosition ip;
+ PlaylistDropzoneMap::iterator pdz = playlist_dropzone_map.find (i->view->region()->playlist());
+
+ /* store index of each new playlist as a negative count, starting at -1 */
+
+ if (pdz == playlist_dropzone_map.end()) {
+
+ int n = playlist_dropzone_map.size() + 1;
+
+ /* compute where this new track (which doesn't exist yet) will live
+ on the y-axis.
+ */
+
+ ip.first = -n; /* in time axis units, negative to signify "in drop zone " */
+ ip.second = last_track_bottom_edge; /* where to place the top edge of the regionview */
+
+ /* How high is this region view ? */
+
+ boost::optional<ArdourCanvas::Rect> obbox = rv->get_canvas_group()->bounding_box ();
+ ArdourCanvas::Rect bbox;
+
+ if (obbox) {
+ bbox = obbox.get ();
+ }
+
+ last_track_bottom_edge += bbox.height();
+
+ playlist_dropzone_map.insert (make_pair (i->view->region()->playlist(), ip));
+ i->time_axis_view = -n;
+
} else {
- last_track_bottom_edge = 0;
+ ip = pdz->second;
+ i->time_axis_view = ip.first;
}
- y_delta = last_track_bottom_edge - rv->get_canvas_group()->canvas_origin().y;
- i->time_axis_view = -1;
+ /* values are zero or negative, hence the use of min() */
+ biggest_drop_zone_offset = min (biggest_drop_zone_offset, i->time_axis_view);
+
+ y_delta = ip.second - rv->get_canvas_group()->canvas_origin().y;
}
}
@@ -885,7 +977,35 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
show_verbose_cursor_time (_last_frame_position);
}
- _last_pointer_time_axis_view += delta_time_axis_view;
+ if (tv) {
+
+ /* the pointer is currently over a time axis view */
+
+ if (_last_pointer_time_axis_view < 0) {
+
+ /* last motion event was not over a time axis view */
+
+ if (delta_time_axis_view < 0) {
+ /* was in the drop zone, moving up */
+ _last_pointer_time_axis_view = current_pointer_time_axis_view;
+ } else {
+ /* was in the drop zone, moving down ... not possible */
+ }
+
+ } else {
+
+ /* last motion event was also over a time axis view */
+
+ _last_pointer_time_axis_view = current_pointer_time_axis_view;
+ }
+
+ } else {
+
+ /* the pointer is not over a time axis view */
+
+ _last_pointer_time_axis_view = biggest_drop_zone_offset;
+ }
+
_last_pointer_layer += delta_layer;
}