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
This commit is contained in:
Carl Hetherington 2009-01-06 03:18:09 +00:00
parent 780b753639
commit f2058a3f87
15 changed files with 375 additions and 220 deletions

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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__ */

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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;
}
@ -3639,76 +3646,207 @@ 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 */
/* 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 (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*/
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;
if (pointer_y_span != 0 && !clamp_y_axis) {
/* 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;
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--;
}
while (j != height_list.end () && x != canvas_rtv->order ()) {
++x;
++j;
}
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 */
y_delta = 0;
int32_t temp_pointer_y_span = pointer_y_span;
tvp2 = trackview_by_y_position (iy1 + y_delta);
temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
rv->set_height (temp_rtv->current_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.
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--;
}
x++;
while (temp_pointer_y_span < 0) {
y_delta += (*j);
if (j != height_list.end()) {
j++;
}
temp_pointer_y_span++;
}
/* 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;

View File

@ -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;
}

View File

@ -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));

View File

@ -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>

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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

View File

@ -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 */