summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2009-01-06 03:18:09 +0000
committerCarl Hetherington <carl@carlh.net>2009-01-06 03:18:09 +0000
commitf2058a3f8739c6a7e9f7408f31d3b94ddb50673f (patch)
tree2050e2386dc670b16259805d1ecdbf8fb350fe5b /gtk2_ardour
parent780b75363915bd328877cba33766b1ac177b45c1 (diff)
Comment and (hopefully) simplify Editor::region_drag_motion_callback, fixing problems with dragging regions
to and from tracks in "stacked" display mode. As a side-effect, enable dragging of regions between layers, though I'm not entirely sure where this is useful or desirable just yet; dragging regions between layers currently works in the GUI but has no effect on the model. git-svn-id: svn://localhost/ardour2/branches/3.0@4389 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/audio_streamview.cc10
-rw-r--r--gtk2_ardour/draginfo.h2
-rw-r--r--gtk2_ardour/editor.cc16
-rw-r--r--gtk2_ardour/editor.h9
-rw-r--r--gtk2_ardour/editor_canvas.cc6
-rw-r--r--gtk2_ardour/editor_canvas_events.cc8
-rw-r--r--gtk2_ardour/editor_mouse.cc433
-rw-r--r--gtk2_ardour/editor_ops.cc14
-rw-r--r--gtk2_ardour/editor_rulers.cc5
-rw-r--r--gtk2_ardour/route_time_axis.cc16
-rw-r--r--gtk2_ardour/route_time_axis.h1
-rw-r--r--gtk2_ardour/streamview.cc18
-rw-r--r--gtk2_ardour/streamview.h8
-rw-r--r--gtk2_ardour/time_axis_view.cc38
-rw-r--r--gtk2_ardour/time_axis_view.h11
15 files changed, 375 insertions, 220 deletions
diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc
index f79955b100..85812b43d6 100644
--- a/gtk2_ardour/audio_streamview.cc
+++ b/gtk2_ardour/audio_streamview.cc
@@ -308,7 +308,7 @@ AudioStreamView::add_crossfade (boost::shared_ptr<Crossfade> crossfade)
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
if ((*i)->crossfade == crossfade) {
- if (!crossfades_visible || layer_display == Stacked) {
+ if (!crossfades_visible || _layer_display == Stacked) {
(*i)->hide();
} else {
(*i)->show ();
@@ -340,7 +340,7 @@ AudioStreamView::add_crossfade (boost::shared_ptr<Crossfade> crossfade)
cv->set_valid (true);
crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade));
crossfade_views.push_back (cv);
- if (!Config->get_xfades_visible() || !crossfades_visible || layer_display == Stacked) {
+ if (!Config->get_xfades_visible() || !crossfades_visible || _layer_display == Stacked) {
cv->hide ();
}
}
@@ -373,7 +373,7 @@ AudioStreamView::redisplay_diskstream ()
for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
(*xi)->set_valid (false);
- if ((*xi)->visible() && layer_display != Stacked) {
+ if ((*xi)->visible() && _layer_display != Stacked) {
(*xi)->show ();
}
}
@@ -806,7 +806,7 @@ void
AudioStreamView::reveal_xfades_involving (AudioRegionView& rv)
{
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
- if ((*i)->crossfade->involves (rv.audio_region()) && (*i)->visible() && layer_display != Stacked) {
+ if ((*i)->crossfade->involves (rv.audio_region()) && (*i)->visible() && _layer_display != Stacked) {
(*i)->show ();
}
}
@@ -836,7 +836,7 @@ AudioStreamView::update_contents_height ()
StreamView::update_contents_height ();
for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
- if (layer_display == Overlaid) {
+ if (_layer_display == Overlaid) {
(*i)->show ();
(*i)->set_height (height);
} else {
diff --git a/gtk2_ardour/draginfo.h b/gtk2_ardour/draginfo.h
index 6d3a6b8de3..e0fccb7f70 100644
--- a/gtk2_ardour/draginfo.h
+++ b/gtk2_ardour/draginfo.h
@@ -57,7 +57,9 @@ struct DragInfo {
void (Editor::*motion_callback)(ArdourCanvas::Item*, GdkEvent*);
void (Editor::*finished_callback)(ArdourCanvas::Item*, GdkEvent*);
TimeAxisView* source_trackview;
+ ARDOUR::layer_t source_layer;
TimeAxisView* dest_trackview;
+ ARDOUR::layer_t dest_layer;
bool x_constrained;
bool y_constrained;
bool copy;
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 051eb6dd8a..5121fe0425 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -2722,19 +2722,23 @@ Editor::get_state ()
-TimeAxisView *
+/** @param y y offset from the top of all trackviews.
+ * @return pair: TimeAxisView that y is over, layer index.
+ * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
+ * in stacked region display mode, otherwise 0.
+ */
+std::pair<TimeAxisView *, layer_t>
Editor::trackview_by_y_position (double y)
{
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
- TimeAxisView *tv;
-
- if ((tv = (*iter)->covers_y_position (y)) != 0) {
- return tv;
+ std::pair<TimeAxisView*, int> const r = (*iter)->covers_y_position (y);
+ if (r.first) {
+ return r;
}
}
- return 0;
+ return std::make_pair ( (TimeAxisView *) 0, 0);
}
void
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 834313f9ae..732aea59ad 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -25,6 +25,7 @@
#include <set>
#include <string>
#include <sys/time.h>
+#include <bitset>
#include <glibmm/ustring.h>
@@ -51,6 +52,7 @@
#include <ardour/location.h>
#include <ardour/audioregion.h>
#include <ardour/track.h>
+#include <ardour/types.h>
#include "audio_clock.h"
#include "gtk-custom-ruler.h"
@@ -1071,7 +1073,7 @@ class Editor : public PublicEditor
/* track views */
TrackViewList track_views;
- TimeAxisView *trackview_by_y_position (double ypos);
+ std::pair<TimeAxisView*, ARDOUR::layer_t> trackview_by_y_position (double);
static Gdk::Cursor* cross_hair_cursor;
static Gdk::Cursor* trimmer_cursor;
@@ -1442,7 +1444,7 @@ class Editor : public PublicEditor
void region_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*);
void create_region_drag_motion_callback (ArdourCanvas::Item*, GdkEvent*);
void create_region_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*);
- bool check_region_drag_possible (RouteTimeAxisView**);
+ bool check_region_drag_possible (RouteTimeAxisView**, ARDOUR::layer_t*);
void possibly_copy_regions_during_grab (GdkEvent*);
void region_drag_splice_motion_callback (ArdourCanvas::Item*, GdkEvent*);
void region_drag_splice_finished_callback (ArdourCanvas::Item*, GdkEvent*);
@@ -2361,6 +2363,9 @@ public:
bool idle_resize();
friend gboolean _idle_resize (gpointer);
std::vector<TimeAxisView*> pending_resizes;
+
+ void visible_order_range (int*, int*) const;
+ bool y_movement_disallowed (int, int, int, int, int, std::bitset<512> const &, std::vector<int32_t> const &) const;
};
#endif /* __ardour_editor_h__ */
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index 62de67cd22..89cf608989 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -462,10 +462,10 @@ Editor::idle_drop_paths (vector<ustring> paths, nframes64_t frame, double ypos)
void
Editor::drop_paths_part_two (const vector<ustring>& paths, nframes64_t frame, double ypos)
{
- TimeAxisView* tvp;
AudioTimeAxisView* tv;
- if ((tvp = trackview_by_y_position (ypos)) == 0) {
+ std::pair<TimeAxisView*, int> const tvp = trackview_by_y_position (ypos);
+ if (tvp.first == 0) {
/* drop onto canvas background: create new tracks */
@@ -477,7 +477,7 @@ Editor::drop_paths_part_two (const vector<ustring>& paths, nframes64_t frame, do
do_embed (paths, Editing::ImportDistinctFiles, ImportAsTrack, frame);
}
- } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
+ } else if ((tv = dynamic_cast<AudioTimeAxisView*> (tvp.first)) != 0) {
/* check that its an audio track, not a bus */
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index b05d4e6c4c..478fc1afe4 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -93,7 +93,9 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
if (!current_stepping_trackview) {
step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
- if (!(current_stepping_trackview = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize))) {
+ std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
+ current_stepping_trackview = p.first;
+ if (!current_stepping_trackview) {
return false;
}
}
@@ -126,7 +128,9 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
if (!current_stepping_trackview) {
step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500);
- if (!(current_stepping_trackview = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize))) {
+ std::pair<TimeAxisView*, int> const p = trackview_by_y_position (ev->y + vertical_adjustment.get_value() - canvas_timebars_vsize);
+ current_stepping_trackview = p.first;
+ if (!current_stepping_trackview) {
return false;
}
}
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index 0e101957f2..c51e650f6f 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -2571,7 +2571,7 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
Marker* dragged_marker = (Marker*) drag_info.data;
Marker* marker;
Location *real_location;
- Location *copy_location;
+ Location *copy_location = 0;
if (drag_info.pointer_frame_offset <= drag_info.current_pointer_frame) {
newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
@@ -3385,7 +3385,9 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
drag_info.last_frame_position = (nframes64_t) (clicked_regionview->region()->position() / speed);
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
drag_info.source_trackview = &clicked_regionview->get_time_axis_view();
+ drag_info.source_layer = clicked_regionview->region()->layer();
drag_info.dest_trackview = drag_info.source_trackview;
+ drag_info.dest_layer = drag_info.source_layer;
// we want a move threshold
drag_info.want_move_threshold = true;
show_verbose_time_cursor (drag_info.last_frame_position, 10);
@@ -3404,6 +3406,7 @@ Editor::start_create_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
drag_info.data = clicked_axisview;
drag_info.source_trackview = clicked_axisview;
drag_info.dest_trackview = drag_info.source_trackview;
+ drag_info.dest_layer = drag_info.source_layer;
drag_info.motion_callback = &Editor::create_region_drag_motion_callback;
drag_info.finished_callback = &Editor::create_region_drag_finished_callback;
@@ -3433,6 +3436,7 @@ Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
drag_info.source_trackview = &clicked_regionview->get_time_axis_view();
drag_info.dest_trackview = drag_info.source_trackview;
+ drag_info.dest_layer = drag_info.source_layer;
drag_info.last_frame_position = (nframes64_t) (clicked_regionview->region()->position() / speed);
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
// we want a move threshold
@@ -3469,6 +3473,7 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event)
drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
drag_info.source_trackview = &clicked_regionview->get_time_axis_view();
drag_info.dest_trackview = drag_info.source_trackview;
+ drag_info.dest_layer = drag_info.source_layer;
// we want a move threshold
drag_info.want_move_threshold = true;
drag_info.brushing = true;
@@ -3545,12 +3550,13 @@ Editor::possibly_copy_regions_during_grab (GdkEvent* event)
}
bool
-Editor::check_region_drag_possible (RouteTimeAxisView** tv)
+Editor::check_region_drag_possible (RouteTimeAxisView** tv, layer_t* layer)
{
/* Which trackview is this ? */
- TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y);
- (*tv) = dynamic_cast<RouteTimeAxisView*>(tvp);
+ std::pair<TimeAxisView*, int> const tvp = trackview_by_y_position (drag_info.current_pointer_y);
+ (*tv) = dynamic_cast<RouteTimeAxisView*> (tvp.first);
+ (*layer) = tvp.second;
/* The region motion is only processed if the pointer is over
an audio track.
@@ -3577,8 +3583,9 @@ void
Editor::region_drag_splice_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
RouteTimeAxisView* tv;
+ layer_t layer;
- if (!check_region_drag_possible (&tv)) {
+ if (!check_region_drag_possible (&tv, &layer)) {
return;
}
@@ -3640,75 +3647,206 @@ Editor::region_drag_splice_finished_callback (ArdourCanvas::Item* item, GdkEvent
}
void
+Editor::visible_order_range (int* low, int* high) const
+{
+ *low = TimeAxisView::max_order ();
+ *high = 0;
+
+ for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
+
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
+
+ if (!rtv->hidden()) {
+
+ if (*high < rtv->order()) {
+ *high = rtv->order ();
+ }
+
+ if (*low > rtv->order()) {
+ *low = rtv->order ();
+ }
+ }
+ }
+}
+
+/** @param new_order New track order.
+ * @param old_order Old track order.
+ * @param visible_y_low Lowest visible order.
+ * @param visible_y_high Highest visible order.
+ * @param tracks Bitset of tracks indexed by order; 0 means a audio/MIDI track, 1 means something else.
+ * @param heigh_list Heights of tracks indexed by order.
+ * @return true if y movement should not happen, otherwise false.
+ */
+bool
+Editor::y_movement_disallowed (
+ int new_order, int old_order, int y_span, int visible_y_low, int visible_y_high,
+ bitset<512> const & tracks, vector<int32_t> const & height_list
+ ) const
+{
+ if (new_order != old_order) {
+
+ /* this isn't the pointer track */
+
+ if (y_span > 0) {
+
+ /* moving up the canvas */
+ if ( (new_order - y_span) >= visible_y_low) {
+
+ int32_t n = 0;
+
+ /* work out where we'll end up with this y span, taking hidden TimeAxisViews into account */
+ int32_t visible_tracks = 0;
+ while (visible_tracks < y_span ) {
+ visible_tracks++;
+ while (height_list[new_order - (visible_tracks - n)] == 0) {
+ /* passing through a hidden track */
+ n--;
+ }
+ }
+
+ if (tracks[new_order - (y_span - n)] != 0x00) {
+ /* moving to a non-track; disallow */
+ return true;
+ }
+
+
+ } else {
+ /* moving beyond the lowest visible track; disallow */
+ return true;
+ }
+
+ } else if (y_span < 0) {
+
+ /* moving down the canvas */
+ if ((new_order - y_span) <= visible_y_high) {
+
+ int32_t visible_tracks = 0;
+ int32_t n = 0;
+ while (visible_tracks > y_span ) {
+ visible_tracks--;
+
+ while (height_list[new_order - (visible_tracks - n)] == 0) {
+ /* passing through a hidden track */
+ n++;
+ }
+ }
+
+ if (tracks[new_order - (y_span - n)] != 0x00) {
+ /* moving to a non-track; disallow */
+ return true;
+ }
+
+
+ } else {
+
+ /* moving beyond the highest visible track; disallow */
+ return true;
+ }
+ }
+
+ } else {
+
+ /* this is the pointer's track */
+
+ if ((new_order - y_span) > visible_y_high) {
+ /* we will overflow */
+ return true;
+ } else if ((new_order - y_span) < visible_y_low) {
+ /* we will overflow */
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+void
Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
{
double x_delta;
double y_delta = 0;
nframes64_t pending_region_position = 0;
- int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order;
- int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen
+ int32_t pointer_y_span = 0, canvas_pointer_y_span = 0;
+ int32_t layer_span = 0;
+
bool clamp_y_axis = false;
- vector<int32_t> height_list(512) ;
vector<int32_t>::iterator j;
- RouteTimeAxisView* tv;
possibly_copy_regions_during_grab (event);
- if (!check_region_drag_possible (&tv)) {
+ /* tv will become the TimeAxisView that we're currently pointing at, and
+ current_layer the current layer on that TimeAxisView */
+ RouteTimeAxisView* tv;
+ layer_t current_layer;
+ if (!check_region_drag_possible (&tv, &current_layer)) {
return;
}
- original_pointer_order = drag_info.dest_trackview->order ();
+ /* the order of the track that we were pointing at last time we entered this method */
+ int32_t const last_pointer_order = drag_info.dest_trackview->order ();
+ /* the layer that we were pointing at last time we entered this method */
+ layer_t const last_pointer_layer = drag_info.dest_layer;
/************************************************************
- Y-Delta Computation
+ Y DELTA COMPUTATION
************************************************************/
+ /* Height of TimeAxisViews, indexed by order */
+ /* XXX: hard-coded limit of TimeAxisViews */
+ vector<int32_t> height_list (512);
+
if (drag_info.brushing) {
clamp_y_axis = true;
pointer_y_span = 0;
goto y_axis_done;
}
- if ((pointer_y_span = (drag_info.dest_trackview->order() - tv->order())) != 0) {
+ /* the change in track order between this callback and the last */
+ pointer_y_span = drag_info.dest_trackview->order() - tv->order();
+ /* the change in layer between this callback and the last */
+ layer_span = drag_info.dest_layer - current_layer;
+
+ if (pointer_y_span != 0) {
int32_t children = 0;
- // XXX hard coding track limit, oh my, so very very bad
- bitset <1024> tracks (0x00);
+ /* XXX: hard-coded limit of tracks */
+ bitset <512> tracks (0x00);
+
+ int visible_y_high;
+ int visible_y_low;
+ visible_order_range (&visible_y_low, &visible_y_high);
+
/* get a bitmask representing the visible tracks */
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
- RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*> (*i);
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
TimeAxisView::Children children_list;
- /* zeroes are audio tracks. ones are other types. */
+ /* zeroes are audio/MIDI tracks. ones are other types. */
- if (!rtv2->hidden()) {
+ if (!rtv->hidden()) {
- if (visible_y_high < rtv2->order()) {
- visible_y_high = rtv2->order();
- }
- if (visible_y_low > rtv2->order()) {
- visible_y_low = rtv2->order();
- }
-
- if (!rtv2->is_track()) {
- tracks = tracks |= (0x01 << rtv2->order());
+ if (!rtv->is_track()) {
+ /* not an audio nor MIDI track */
+ tracks = tracks |= (0x01 << rtv->order());
}
- height_list[rtv2->order()] = (*i)->current_height();
+ height_list[rtv->order()] = (*i)->current_height();
children = 1;
- if ((children_list = rtv2->get_child_list()).size() > 0) {
+ if ((children_list = rtv->get_child_list()).size() > 0) {
for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) {
- tracks = tracks |= (0x01 << (rtv2->order() + children));
- height_list[rtv2->order() + children] = (*j)->current_height();
+ tracks = tracks |= (0x01 << (rtv->order() + children));
+ height_list[rtv->order() + children] = (*j)->current_height();
children++;
}
}
}
}
- /* find the actual span according to the canvas */
+
+ /* find the actual span, in terms of the number of visible tracks;
+ to do this, we reduce |pointer_y_span| by the number of hidden tracks */
canvas_pointer_y_span = pointer_y_span;
if (drag_info.dest_trackview->order() >= tv->order()) {
@@ -3726,94 +3864,48 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
}
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
- RegionView* rv2 = (*i);
- double ix1, ix2, iy1, iy2;
- int32_t n = 0;
+
+ RegionView* rv = (*i);
- if (rv2->region()->locked()) {
+ if (rv->region()->locked()) {
continue;
}
- rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
- rv2->get_canvas_frame()->i2w (ix1, iy1);
+ double ix1, ix2, iy1, iy2;
+ rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
+ rv->get_canvas_frame()->i2w (ix1, iy1);
iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize;
- TimeAxisView* tvp2 = trackview_by_y_position (iy1);
- RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
+ std::pair<TimeAxisView*, int> const tvp = trackview_by_y_position (iy1);
+ assert (tvp.first);
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
- if (rtv2->order() != original_pointer_order) {
- /* this isn't the pointer track */
-
- if (canvas_pointer_y_span > 0) {
-
- /* moving up the canvas */
- if ((rtv2->order() - canvas_pointer_y_span) >= visible_y_low) {
-
- int32_t visible_tracks = 0;
- while (visible_tracks < canvas_pointer_y_span ) {
- visible_tracks++;
-
- while (height_list[rtv2->order() - (visible_tracks - n)] == 0) {
- /* we're passing through a hidden track */
- n--;
- }
- }
-
- if (tracks[rtv2->order() - (canvas_pointer_y_span - n)] != 0x00) {
- clamp_y_axis = true;
- }
-
- } else {
- clamp_y_axis = true;
- }
-
- } else if (canvas_pointer_y_span < 0) {
-
- /*moving down the canvas*/
+ /* I know this method has a slightly excessive argument list, but I think
+ it's nice to separate the code out all the same, since it has such a simple result,
+ and it makes it clear that there are no other side-effects.
+ */
+ clamp_y_axis = y_movement_disallowed (
+ rtv->order(), last_pointer_order, canvas_pointer_y_span, visible_y_low, visible_y_high,
+ tracks, height_list
+ );
- if ((rtv2->order() - (canvas_pointer_y_span - n)) <= visible_y_high) { // we will overflow
-
-
- int32_t visible_tracks = 0;
-
- while (visible_tracks > canvas_pointer_y_span ) {
- visible_tracks--;
-
- while (height_list[rtv2->order() - (visible_tracks - n)] == 0) {
- n++;
- }
- }
- if ( tracks[rtv2->order() - ( canvas_pointer_y_span - n)] != 0x00) {
- clamp_y_axis = true;
-
- }
- } else {
-
- clamp_y_axis = true;
- }
- }
-
- } else {
-
- /* this is the pointer's track */
- if ((rtv2->order() - pointer_y_span) > visible_y_high) { // we will overflow
- clamp_y_axis = true;
- } else if ((rtv2->order() - pointer_y_span) < visible_y_low) { // we will underflow
- clamp_y_axis = true;
- }
- }
if (clamp_y_axis) {
break;
}
}
- } else if (drag_info.dest_trackview == tv) {
- clamp_y_axis = true;
- }
+ } else if (drag_info.dest_trackview == tv) {
+
+ if (current_layer == last_pointer_layer) {
+ /* No movement; clamp */
+ clamp_y_axis = true;
+ }
+ }
y_axis_done:
if (!clamp_y_axis) {
- drag_info.dest_trackview = tv;
+ drag_info.dest_trackview = tv;
+ drag_info.dest_layer = current_layer;
}
/************************************************************
@@ -3861,8 +3953,6 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
pending_region_position = drag_info.last_frame_position;
}
- // printf ("3: pending_region_position= %lu %lu\n", pending_region_position, drag_info.last_frame_position );
-
bool x_move_allowed;
if (Config->get_edit_mode() == Lock) {
@@ -3888,16 +3978,15 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
x_delta = -((double) (drag_info.last_frame_position - pending_region_position) / frames_per_unit);
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
- RegionView* rv2 = (*i);
+ RegionView* rv = (*i);
// If any regionview is at zero, we need to know so we can stop further leftward motion.
double ix1, ix2, iy1, iy2;
- rv2->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
- rv2->get_canvas_frame()->i2w (ix1, iy1);
+ rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
+ rv->get_canvas_frame()->i2w (ix1, iy1);
if (-x_delta > ix1 + horizontal_adjustment.get_value()) {
- // do_move = false;
x_delta = 0;
pending_region_position = drag_info.last_frame_position;
break;
@@ -3922,9 +4011,9 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
PREPARE TO MOVE
************************************************************/
- if (x_delta == 0 && (pointer_y_span == 0)) {
+ if (x_delta == 0 && pointer_y_span == 0 && layer_span == 0) {
/* haven't reached next snap point, and we're not switching
- trackviews. nothing to do.
+ trackviews nor layers. nothing to do.
*/
return;
}
@@ -3947,7 +4036,6 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
RegionView* rv = (*i);
- int32_t temp_pointer_y_span = pointer_y_span;
if (rv->region()->locked()) {
continue;
@@ -3994,68 +4082,73 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
rv->fake_set_opaque (true);
}
- TimeAxisView* tvp2 = trackview_by_y_position (iy1);
- RouteTimeAxisView* canvas_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
- RouteTimeAxisView* temp_rtv;
+ std::pair<TimeAxisView*, int> pos = trackview_by_y_position (iy1);
+ RouteTimeAxisView* canvas_rtv = dynamic_cast<RouteTimeAxisView*> (pos.first);
- if ((pointer_y_span != 0) && !clamp_y_axis) {
- y_delta = 0;
- int32_t x = 0;
- for (j = height_list.begin(); j!= height_list.end(); j++) {
- if (x == canvas_rtv->order()) {
- /* we found the track the region is on */
- if (x != original_pointer_order) {
- /*this isn't from the same track we're dragging from */
- temp_pointer_y_span = canvas_pointer_y_span;
- }
- while (temp_pointer_y_span > 0) {
- /* we're moving up canvas-wise,
- so we need to find the next track height
- */
- if (j != height_list.begin()) {
- j--;
- }
- if (x != original_pointer_order) {
- /* we're not from the dragged track, so ignore hidden tracks. */
- if ((*j) == 0) {
- temp_pointer_y_span++;
- }
- }
- y_delta -= (*j);
- temp_pointer_y_span--;
- }
+ if (pointer_y_span != 0 && !clamp_y_axis) {
- while (temp_pointer_y_span < 0) {
- y_delta += (*j);
- if (x != original_pointer_order) {
- if ((*j) == 0) {
- temp_pointer_y_span--;
- }
- }
-
- if (j != height_list.end()) {
- j++;
- }
- temp_pointer_y_span++;
- }
- /* find out where we'll be when we move and set height accordingly */
+ /* INTER-TRACK MOVEMENT */
+
+ /* move through the height list to the track that the region is going to */
+ vector<int32_t>::iterator j = height_list.begin ();
+ int32_t x = 0;
+ while (j != height_list.end () && x != canvas_rtv->order ()) {
+ ++x;
+ ++j;
+ }
- tvp2 = trackview_by_y_position (iy1 + y_delta);
- temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
- rv->set_height (temp_rtv->current_height());
+ y_delta = 0;
+ int32_t temp_pointer_y_span = pointer_y_span;
- /* if you un-comment the following, the region colours will follow the track colours whilst dragging,
- personally, i think this can confuse things, but never mind.
+ if (j != height_list.end ()) {
+
+ while (temp_pointer_y_span > 0) {
+ /* we're moving up canvas-wise,
+ so we need to find the next track height
*/
-
- //const GdkColor& col (temp_rtv->view->get_region_color());
- //rv->set_color (const_cast<GdkColor&>(col));
- break;
+ if (j != height_list.begin()) {
+ j--;
+ }
+
+ y_delta -= (*j);
+ temp_pointer_y_span--;
+ }
+
+ while (temp_pointer_y_span < 0) {
+
+ y_delta += (*j);
+
+ if (j != height_list.end()) {
+ j++;
+ }
+
+ temp_pointer_y_span++;
}
- x++;
+
+ /* find out where we'll be when we move and set height accordingly */
+
+ std::pair<TimeAxisView*, int> const pos = trackview_by_y_position (iy1 + y_delta);
+ RouteTimeAxisView const * temp_rtv = dynamic_cast<RouteTimeAxisView*> (pos.first);
+ rv->set_height (temp_rtv->view()->child_height());
+
+ /* if you un-comment the following, the region colours will follow
+ the track colours whilst dragging; personally
+ i think this can confuse things, but never mind.
+ */
+
+ //const GdkColor& col (temp_rtv->view->get_region_color());
+ //rv->set_color (const_cast<GdkColor&>(col));
}
}
+ if (pointer_y_span == 0 && layer_span != 0 && !clamp_y_axis) {
+
+ /* INTER-LAYER MOVEMENT in the same track */
+ assert (tv->view ());
+ y_delta = tv->view()->child_height () * layer_span;
+ }
+
+
if (drag_info.brushing) {
mouse_brush_insert_region (rv, pending_region_position);
} else {
@@ -4092,6 +4185,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
pair<PlaylistSet::iterator,bool> insert_result, frozen_insert_result;
nframes64_t drag_delta;
bool changed_tracks, changed_position;
+ std::pair<TimeAxisView*, int> tvp;
/* first_move is set to false if the regionview has been moved in the
motion handler.
@@ -4147,7 +4241,8 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
begin_reversible_command (op_string);
changed_position = (drag_info.last_frame_position != (nframes64_t) (clicked_regionview->region()->position()));
- changed_tracks = (trackview_by_y_position (drag_info.current_pointer_y) != &clicked_regionview->get_time_axis_view());
+ tvp = trackview_by_y_position (drag_info.current_pointer_y);
+ changed_tracks = (tvp.first != &clicked_regionview->get_time_axis_view());
drag_delta = clicked_regionview->region()->position() - drag_info.last_frame_position;
@@ -4161,8 +4256,8 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
rv->get_canvas_frame()->i2w (ix1, iy1);
iy1 += vertical_adjustment.get_value() - canvas_timebars_vsize;
- TimeAxisView* dest_tv = trackview_by_y_position (iy1);
- RouteTimeAxisView* dest_rtv = dynamic_cast<RouteTimeAxisView*>(dest_tv);
+ std::pair<TimeAxisView*, int> const dest_tv = trackview_by_y_position (iy1);
+ RouteTimeAxisView* dest_rtv = dynamic_cast<RouteTimeAxisView*> (dest_tv.first);
nframes64_t where;
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 61ea85568f..467b8539f9 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -2261,7 +2261,6 @@ Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y)
{
double wx, wy;
double cx, cy;
- TimeAxisView *tv;
nframes64_t where;
RouteTimeAxisView *rtv = 0;
boost::shared_ptr<Playlist> playlist;
@@ -2281,12 +2280,13 @@ Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y)
/* clearly outside canvas area */
return;
}
-
- if ((tv = trackview_by_y_position (cy)) == 0) {
+
+ std::pair<TimeAxisView*, int> tv = trackview_by_y_position (cy);
+ if (tv.first == 0) {
return;
}
- if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) == 0) {
+ if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv.first)) == 0) {
return;
}
@@ -2307,7 +2307,6 @@ void
Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y) {
double wx, wy;
double cx, cy;
- TimeAxisView *tv;
nframes_t where;
RouteTimeAxisView *dest_rtv = 0;
RouteTimeAxisView *source_rtv = 0;
@@ -2323,11 +2322,12 @@ Editor::insert_route_list_drag (boost::shared_ptr<Route> route, int x, int y) {
where = event_frame (&event, &cx, &cy);
- if ((tv = trackview_by_y_position (cy)) == 0) {
+ std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (cy);
+ if (tv.first == 0) {
return;
}
- if ((dest_rtv = dynamic_cast<RouteTimeAxisView*>(tv)) == 0) {
+ if ((dest_rtv = dynamic_cast<RouteTimeAxisView*> (tv.first)) == 0) {
return;
}
diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc
index a4344c3ffa..0d355832f2 100644
--- a/gtk2_ardour/editor_rulers.cc
+++ b/gtk2_ardour/editor_rulers.cc
@@ -843,8 +843,9 @@ Editor::update_ruler_visibility ()
}
gdouble bottom_track_pos = vertical_adjustment.get_value() + canvas_height - canvas_timebars_vsize;
- if (trackview_by_y_position(bottom_track_pos) != 0) {
- trackview_by_y_position(bottom_track_pos)->clip_to_viewport ();
+ std::pair<TimeAxisView*, int> const p = trackview_by_y_position (bottom_track_pos);
+ if (p.first) {
+ p.first->clip_to_viewport ();
}
ruler_label_vbox.set_size_request (-1, (int)(timebar_height * visible_rulers));
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index 6166360542..5035814fa2 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -2171,8 +2171,22 @@ RouteTimeAxisView::update_rec_display ()
void
RouteTimeAxisView::set_layer_display (LayerDisplay d)
{
- _view->set_layer_display (d);
+ if (_view) {
+ _view->set_layer_display (d);
+ }
}
+
+LayerDisplay
+RouteTimeAxisView::layer_display () const
+{
+ if (_view) {
+ return _view->layer_display ();
+ }
+
+ /* we don't know, since we don't have a _view, so just return something */
+ return Overlaid;
+}
+
boost::shared_ptr<AutomationTimeAxisView>
diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h
index 35c4b48a16..9e40c511a6 100644
--- a/gtk2_ardour/route_time_axis.h
+++ b/gtk2_ardour/route_time_axis.h
@@ -85,6 +85,7 @@ public:
void get_inverted_selectables (Selection&, list<Selectable*>&);
bool show_automation(Evoral::Parameter param);
void set_layer_display (LayerDisplay d);
+ LayerDisplay layer_display () const;
boost::shared_ptr<ARDOUR::Region> find_next_region (nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
nframes64_t find_next_region_boundary (nframes64_t pos, int32_t dir);
diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc
index 9831bf742f..d8abf0f834 100644
--- a/gtk2_ardour/streamview.cc
+++ b/gtk2_ardour/streamview.cc
@@ -56,9 +56,9 @@ StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Group* group)
, use_rec_regions (tv.editor().show_waveforms_recording ())
, region_color(_trackview.color())
, stream_base_color(0xFFFFFFFF)
- , layers(1)
+ , _layers (1)
, height(tv.height)
- , layer_display(Overlaid)
+ , _layer_display (Overlaid)
, last_rec_data_frame(0)
{
/* set_position() will position the group */
@@ -233,7 +233,7 @@ StreamView::playlist_modified (boost::shared_ptr<Diskstream> ds)
/* update layers count and the y positions and heights of our regions */
if (ds->playlist()) {
- layers = ds->playlist()->top_layer() + 1;
+ _layers = ds->playlist()->top_layer() + 1;
update_contents_height ();
update_coverage_frames ();
redisplay_diskstream ();
@@ -256,7 +256,7 @@ StreamView::playlist_changed (boost::shared_ptr<Diskstream> ds)
undisplay_diskstream ();
/* update layers count and the y positions and heights of our regions */
- layers = ds->playlist()->top_layer() + 1;
+ _layers = ds->playlist()->top_layer() + 1;
update_contents_height ();
update_coverage_frames ();
@@ -430,8 +430,8 @@ StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results
double
StreamView::child_height () const
{
- if (layer_display == Stacked) {
- return height / layers;
+ if (_layer_display == Stacked) {
+ return height / _layers;
}
return height;
@@ -445,7 +445,7 @@ StreamView::update_contents_height ()
const double h = child_height ();
for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
- switch (layer_display) {
+ switch (_layer_display) {
case Overlaid:
(*i)->set_y (0);
break;
@@ -465,7 +465,7 @@ StreamView::update_contents_height ()
void
StreamView::set_layer_display (LayerDisplay d)
{
- layer_display = d;
+ _layer_display = d;
update_contents_height ();
update_coverage_frames ();
}
@@ -474,6 +474,6 @@ void
StreamView::update_coverage_frames ()
{
for (RegionViewList::iterator i = region_views.begin (); i != region_views.end (); ++i) {
- (*i)->update_coverage_frames (layer_display);
+ (*i)->update_coverage_frames (_layer_display);
}
}
diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h
index 47c6277578..68498f30eb 100644
--- a/gtk2_ardour/streamview.h
+++ b/gtk2_ardour/streamview.h
@@ -73,6 +73,7 @@ public:
gdouble get_samples_per_unit () { return _samples_per_unit; }
void set_layer_display (LayerDisplay);
+ LayerDisplay layer_display () const { return _layer_display; }
ArdourCanvas::Group* background_group() { return _background_group; }
ArdourCanvas::Group* canvas_item() { return canvas_group; }
@@ -97,6 +98,8 @@ public:
virtual void update_contents_height ();
virtual void redisplay_diskstream () = 0;
+ double child_height () const;
+ ARDOUR::layer_t layers () const { return _layers; }
sigc::signal<void,RegionView*> RegionViewAdded;
@@ -126,7 +129,6 @@ protected:
virtual void playlist_modified (boost::shared_ptr<ARDOUR::Diskstream>);
virtual void color_handler () = 0;
- double child_height () const;
RouteTimeAxisView& _trackview;
bool owns_canvas_group;
@@ -152,9 +154,9 @@ protected:
vector<sigc::connection> playlist_connections;
sigc::connection playlist_change_connection;
- int layers;
+ ARDOUR::layer_t _layers;
double height;
- LayerDisplay layer_display;
+ LayerDisplay _layer_display;
list<sigc::connection> rec_data_ready_connections;
jack_nframes_t last_rec_data_frame;
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index 2eac4c53ee..8c56fb6585 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -50,6 +50,7 @@
#include "keyboard.h"
#include "rgb_macros.h"
#include "utils.h"
+ #include "streamview.h"
#include "i18n.h"
@@ -70,6 +71,7 @@
uint32_t TimeAxisView::hSmaller = 0;
uint32_t TimeAxisView::hSmall = 0;
bool TimeAxisView::need_size_info = true;
+ int const TimeAxisView::_max_order = 512;
TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* rent, Canvas& canvas)
: AxisView (sess),
@@ -1191,30 +1193,46 @@ TimeAxisView::color_handler ()
}
}
-/** Returns a TimeAxisView* if this object covers y, or one of its children does.
+/** @return Pair: TimeAxisView, layer index.
+ * TimeAxisView is non-0 if this object covers y, or one of its children does.
* If the covering object is a child axis, then the child is returned.
- * Returns 0 otherwise.
+ * TimeAxisView is 0 otherwise.
+ * Layer index is the layer number if the TimeAxisView is valid and is in stacked
+ * region display mode, otherwise 0.
*/
-TimeAxisView*
+std::pair<TimeAxisView*, layer_t>
TimeAxisView::covers_y_position (double y)
{
if (hidden()) {
- return 0;
+ return std::make_pair ( (TimeAxisView *) 0, 0);
}
if (_y_position <= y && y < (_y_position + height)) {
- return this;
+
+ /* work out the layer index if appropriate */
+ layer_t l = 0;
+ if (layer_display () == Stacked && view ()) {
+ /* compute layer */
+ l = layer_t ((_y_position + height - y) / (view()->child_height ()));
+ /* clamp to max layers to be on the safe side; sometimes the above calculation
+ returns a too-high value */
+ if (l >= view()->layers ()) {
+ l = view()->layers() - 1;
+ }
+ }
+
+ return std::make_pair (this, l);
}
- for (Children::iterator i = children.begin(); i != children.end(); ++i) {
- TimeAxisView* tv;
+ for (Children::const_iterator i = children.begin(); i != children.end(); ++i) {
- if ((tv = (*i)->covers_y_position (y)) != 0) {
- return tv;
+ std::pair<TimeAxisView*, int> const r = (*i)->covers_y_position (y);
+ if (r.first) {
+ return r;
}
}
- return 0;
+ return std::make_pair ( (TimeAxisView *) 0, 0);
}
void
diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h
index e3fbc88514..980ff2cdd8 100644
--- a/gtk2_ardour/time_axis_view.h
+++ b/gtk2_ardour/time_axis_view.h
@@ -66,6 +66,7 @@ class Selection;
class Selectable;
class RegionView;
class GhostRegion;
+class StreamView;
/** Abstract base class for time-axis views (horizontal editor 'strips')
*
@@ -97,6 +98,9 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful
/** @return index of this TimeAxisView within its parent */
int order () const { return _order; }
+ /** @return maximum allowable value of order */
+ static int max_order () { return _max_order; }
+
ArdourCanvas::Group* canvas_display () { return _canvas_display; }
ArdourCanvas::Group* canvas_background () { return _canvas_background; }
ArdourCanvas::Group* ghost_group () { return _ghost_group; }
@@ -149,7 +153,7 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful
virtual void set_height (uint32_t h);
void reset_height();
- TimeAxisView* covers_y_position (double y);
+ std::pair<TimeAxisView*, ARDOUR::layer_t> covers_y_position (double);
/**
* Steps through the defined heights for this TrackView.
@@ -207,6 +211,9 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful
/* call this on the parent */
virtual XMLNode* get_automation_child_xml_node (Evoral::Parameter param) { return 0; }
+
+ virtual LayerDisplay layer_display () const { return Overlaid; }
+ virtual StreamView* view () const { return 0; }
typedef std::vector<boost::shared_ptr<TimeAxisView> > Children;
@@ -342,6 +349,8 @@ private:
double _resize_drag_start;
int32_t _resize_idle_target;
ArdourCanvas::Group* _ghost_group;
+
+ static int const _max_order;
}; /* class TimeAxisView */