Allow multiple simulataneous Drags to be active, and hence set up and drag time ranges when moving regions in PT-edit mode.

git-svn-id: svn://localhost/ardour2/branches/3.0@6478 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2010-01-12 16:14:49 +00:00
parent 642f41b82f
commit 11bd4eed89
14 changed files with 414 additions and 350 deletions

View File

@ -281,7 +281,7 @@ Editor::Editor ()
clicked_crossfadeview = 0;
clicked_control_point = 0;
last_update_frame = 0;
_drag = 0;
_drags = new DragManager (this);
current_mixer_strip = 0;
current_bbt_points = 0;
tempo_lines = 0;
@ -714,7 +714,7 @@ Editor::~Editor()
delete _routes;
delete _route_groups;
delete track_canvas;
delete _drag;
delete _drags;
}
void
@ -731,10 +731,8 @@ Editor::catch_vanishing_regionview (RegionView *rv)
audioregionview by itself.
*/
if (_drag && rv->get_canvas_group() == _drag->item() && !_drag->ending()) {
_drag->end_grab (0);
delete _drag;
_drag = 0;
if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
_drags->abort ();
}
if (clicked_regionview == rv) {

View File

@ -107,7 +107,7 @@ class AutomationTimeAxisView;
class BundleManager;
class ControlPoint;
class CrossfadeView;
class Drag;
class DragManager;
class GlobalPortMatrixWindow;
class GroupedButtons;
class Marker;
@ -607,7 +607,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void collect_new_region_view (RegionView *);
void collect_and_select_new_region_view (RegionView *);
void select_range_around_region (RegionView *);
long select_range_around_region (RegionView *);
Gtk::Menu track_context_menu;
Gtk::Menu track_region_context_menu;
@ -1260,7 +1260,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
int scrubbing_direction;
int scrub_reversals;
int scrub_reverse_distance;
void scrub ();
void scrub (nframes64_t, double);
void keyboard_selection_begin ();
void keyboard_selection_finish (bool add);
@ -1279,9 +1279,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
bool ignore_gui_changes;
Drag* _drag;
DragManager* _drags;
void break_drag ();
void escape ();
Gtk::Menu fade_context_menu;
@ -1305,10 +1304,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
gint mouse_rename_region (ArdourCanvas::Item*, GdkEvent*);
void start_region_grab (ArdourCanvas::Item*, GdkEvent*, RegionView*);
void add_region_drag (ArdourCanvas::Item*, GdkEvent*, RegionView*);
void start_create_region_grab (ArdourCanvas::Item*, GdkEvent*);
void start_region_copy_grab (ArdourCanvas::Item*, GdkEvent*, RegionView*);
void start_region_brush_grab (ArdourCanvas::Item*, GdkEvent*, RegionView*);
void add_region_copy_drag (ArdourCanvas::Item*, GdkEvent*, RegionView*);
void add_region_brush_drag (ArdourCanvas::Item*, GdkEvent*, RegionView*);
void start_selection_grab (ArdourCanvas::Item*, GdkEvent*);
void region_view_item_click (AudioRegionView&, GdkEventButton*);
@ -1676,7 +1675,7 @@ public:
bool allow_vertical_scroll;
/* trimming */
void point_trim (GdkEvent*);
void point_trim (GdkEvent *, nframes64_t);
void single_contents_trim (RegionView&, nframes64_t, bool, bool, bool);
void single_start_trim (RegionView&, nframes64_t, bool, bool, bool);
void single_end_trim (RegionView&, nframes64_t, bool, bool, bool);

View File

@ -541,17 +541,14 @@ Editor::drop_regions (const RefPtr<Gdk::DragContext>& /*context*/,
const SelectionData& /*data*/,
guint /*info*/, guint /*time*/)
{
assert (_drag);
_drag->end_grab (0);
delete _drag;
_drag = 0;
_drags->end_grab (0);
}
void
Editor::maybe_autoscroll (GdkEventMotion* event, bool allow_vert)
{
nframes64_t rightmost_frame = leftmost_frame + current_page_frames();
pair<nframes64_t, nframes64_t> frames = _drag->extent ();
pair<nframes64_t, nframes64_t> frames = _drags->extent ();
bool startit = false;
autoscroll_y = 0;
@ -610,11 +607,9 @@ Editor::autoscroll_canvas ()
double new_pixel;
double target_pixel;
assert (_drag);
if (autoscroll_x_distance != 0) {
pair<nframes64_t, nframes64_t> const e = _drag->extent ();
pair<nframes64_t, nframes64_t> const e = _drags->extent ();
if (autoscroll_x > 0) {
autoscroll_x_distance = (e.second - (leftmost_frame + current_page_frames())) / 3;
@ -626,10 +621,10 @@ Editor::autoscroll_canvas ()
if (autoscroll_y_distance != 0) {
if (autoscroll_y > 0) {
autoscroll_y_distance = (_drag->current_pointer_y() - (get_trackview_group_vertical_offset() + _canvas_height)) / 3;
autoscroll_y_distance = (_drags->current_pointer_y() - (get_trackview_group_vertical_offset() + _canvas_height)) / 3;
} else if (autoscroll_y < 0) {
autoscroll_y_distance = (vertical_adjustment.get_value () - _drag->current_pointer_y()) / 3;
autoscroll_y_distance = (vertical_adjustment.get_value () - _drags->current_pointer_y()) / 3;
}
}
@ -659,7 +654,7 @@ Editor::autoscroll_canvas ()
new_pixel = vertical_pos - autoscroll_y_distance;
}
target_pixel = _drag->current_pointer_y() - autoscroll_y_distance;
target_pixel = _drags->current_pointer_y() - autoscroll_y_distance;
target_pixel = max (target_pixel, 0.0);
} else if (autoscroll_y > 0) {
@ -674,7 +669,7 @@ Editor::autoscroll_canvas ()
new_pixel = min (top_of_bottom_of_canvas, new_pixel);
target_pixel = _drag->current_pointer_y() + autoscroll_y_distance;
target_pixel = _drags->current_pointer_y() + autoscroll_y_distance;
/* don't move to the full canvas height because the item will be invisible
(its top edge will line up with the bottom of the visible canvas.
@ -683,7 +678,7 @@ Editor::autoscroll_canvas ()
target_pixel = min (target_pixel, full_canvas_height - 10);
} else {
target_pixel = _drag->current_pointer_y();
target_pixel = _drags->current_pointer_y();
new_pixel = vertical_pos;
}
@ -709,7 +704,7 @@ Editor::autoscroll_canvas ()
ev.x = x;
ev.y = y;
motion_handler (_drag->item(), (GdkEvent*) &ev, true);
motion_handler (0, (GdkEvent*) &ev, true);
autoscroll_cnt++;

View File

@ -196,10 +196,8 @@ Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
bool
Editor::track_canvas_button_release_event (GdkEventButton *event)
{
if (_drag) {
_drag->end_grab ((GdkEvent*) event);
delete _drag;
_drag = 0;
if (_drags->active ()) {
_drags->end_grab ((GdkEvent*) event);
}
return false;
}
@ -1008,7 +1006,7 @@ Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/,
/* assume we're dragging with button 1 */
event.motion.state = Gdk::BUTTON1_MASK;
if (_drag == 0) {
if (!_drags->active ()) {
double px;
double py;
@ -1042,11 +1040,10 @@ Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const & /*c*/,
return true;
}
_drag = new RegionInsertDrag (this, region_copy, rtav, pos);
_drag->start_grab (&event);
_drags->set (new RegionInsertDrag (this, region_copy, rtav, pos), &event);
}
_drag->motion_handler (&event, false);
_drags->motion_handler (&event, false);
return true;
}

View File

@ -53,15 +53,149 @@ using Gtkmm2ext::Keyboard;
double const ControlPointDrag::_zero_gain_fraction = gain_to_slider_position (dB_to_coefficient (0.0));
DragManager::DragManager (Editor* e)
: _editor (e)
, _ending (false)
, _current_pointer_frame (0)
{
}
DragManager::~DragManager ()
{
abort ();
}
void
DragManager::abort ()
{
for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
(*i)->end_grab (0);
delete *i;
}
_drags.clear ();
}
void
DragManager::break_drag ()
{
_ending = true;
for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
(*i)->break_drag ();
delete *i;
}
_drags.clear ();
_ending = false;
}
void
DragManager::add (Drag* d)
{
d->set_manager (this);
_drags.push_back (d);
}
void
DragManager::set (Drag* d, GdkEvent* e, Gdk::Cursor* c)
{
assert (_drags.empty ());
d->set_manager (this);
_drags.push_back (d);
start_grab (e);
}
void
DragManager::start_grab (GdkEvent* e)
{
_current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y);
for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
(*i)->start_grab (e);
}
}
bool
DragManager::end_grab (GdkEvent* e)
{
_ending = true;
bool r = false;
for (list<Drag*>::iterator i = _drags.begin(); i != _drags.end(); ++i) {
bool const t = (*i)->end_grab (e);
if (t) {
r = true;
}
delete *i;
}
_drags.clear ();
_ending = false;
return r;
}
bool
DragManager::motion_handler (GdkEvent* e, bool from_autoscroll)
{
bool r = false;
_current_pointer_frame = _editor->event_frame (e, &_current_pointer_x, &_current_pointer_y);
for (list<Drag*>::iterator i = _drags.begin(); i != _drags.end(); ++i) {
bool const t = (*i)->motion_handler (e, from_autoscroll);
if (t) {
r = true;
}
}
return r;
}
bool
DragManager::have_item (ArdourCanvas::Item* i) const
{
list<Drag*>::const_iterator j = _drags.begin ();
while (j != _drags.end() && (*j)->item () != i) {
++j;
}
return j != _drags.end ();
}
pair<nframes64_t, nframes64_t>
DragManager::extent () const
{
if (_drags.empty()) {
return make_pair (0, 0);
}
list<Drag*>::const_iterator i = _drags.begin ();
pair<nframes64_t, nframes64_t> e = (*i)->extent ();
++i;
while (i != _drags.end()) {
pair<nframes64_t, nframes64_t> const t = (*i)->extent ();
e.first = min (e.first, t.first);
e.second = max (e.second, t.second);
++i;
}
return e;
}
Drag::Drag (Editor* e, ArdourCanvas::Item* i)
: _editor (e)
, _item (i)
, _pointer_frame_offset (0)
, _ending (false)
, _move_threshold_passed (false)
, _grab_frame (0)
, _last_pointer_frame (0)
, _current_pointer_frame (0)
{
}
@ -104,11 +238,8 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
_grab_frame = _editor->event_frame (event, &_grab_x, &_grab_y);
_grab_frame = adjusted_frame (_grab_frame, event);
_last_pointer_frame = _grab_frame;
_current_pointer_frame = _grab_frame;
_current_pointer_x = _grab_x;
_current_pointer_y = _grab_y;
_last_pointer_x = _current_pointer_x;
_last_pointer_y = _current_pointer_y;
_last_pointer_x = _grab_x;
_last_pointer_y = _grab_y;
_item->grab (Gdk::POINTER_MOTION_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK,
*cursor,
@ -138,20 +269,14 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
bool
Drag::end_grab (GdkEvent* event)
{
_ending = true;
_editor->stop_canvas_autoscroll ();
_item->ungrab (event ? event->button.time : 0);
_last_pointer_x = _current_pointer_x;
_last_pointer_y = _current_pointer_y;
finished (event, _move_threshold_passed);
_editor->hide_verbose_canvas_cursor();
_ending = false;
return _move_threshold_passed;
}
@ -174,17 +299,15 @@ Drag::adjusted_frame (nframes64_t f, GdkEvent const * event, bool snap) const
nframes64_t
Drag::adjusted_current_frame (GdkEvent const * event, bool snap) const
{
return adjusted_frame (_current_pointer_frame, event, snap);
return adjusted_frame (_drags->current_pointer_frame (), event, snap);
}
bool
Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
{
_current_pointer_frame = _editor->event_frame (event, &_current_pointer_x, &_current_pointer_y);
/* check to see if we have moved in any way that matters since the last motion event */
if ( (!x_movement_matters() || _last_pointer_frame == adjusted_current_frame (event)) &&
(!y_movement_matters() || _last_pointer_y == _current_pointer_y) ) {
(!y_movement_matters() || _last_pointer_y == _drags->current_pointer_y ()) ) {
return false;
}
@ -195,7 +318,7 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
if (!from_autoscroll && !_move_threshold_passed) {
bool const xp = (::llabs (adjusted_current_frame (event) - _grab_frame) >= threshold.first);
bool const yp = (::fabs ((_current_pointer_y - _grab_y)) >= threshold.second);
bool const yp = (::fabs ((_drags->current_pointer_y () - _grab_y)) >= threshold.second);
_move_threshold_passed = ((xp && x_movement_matters()) || (yp && y_movement_matters()));
}
@ -209,8 +332,8 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
motion (event, _move_threshold_passed != old_move_threshold_passed);
_last_pointer_x = _current_pointer_x;
_last_pointer_y = _current_pointer_y;
_last_pointer_x = _drags->current_pointer_x ();
_last_pointer_y = _drags->current_pointer_y ();
_last_pointer_frame = adjusted_current_frame (event);
return true;
@ -223,8 +346,6 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
void
Drag::break_drag ()
{
_ending = true;
if (_item) {
_item->ungrab (0);
}
@ -233,8 +354,6 @@ Drag::break_drag ()
_editor->stop_canvas_autoscroll ();
_editor->hide_verbose_canvas_cursor ();
_ending = false;
}
pair<nframes64_t, nframes64_t>
@ -255,7 +374,7 @@ RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<Re
void
RegionDrag::region_going_away (RegionView* v)
{
if (!ending ()) {
if (!_drags->ending ()) {
_views.remove (v);
}
}
@ -1102,7 +1221,7 @@ RegionMotionDrag::check_possible (RouteTimeAxisView** tv, layer_t* layer)
{
/* Which trackview is this ? */
pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (current_pointer_y ());
pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (_drags->current_pointer_y ());
(*tv) = dynamic_cast<RouteTimeAxisView*> (tvp.first);
(*layer) = tvp.second;
@ -1335,7 +1454,7 @@ RegionSpliceDrag::motion (GdkEvent* event, bool)
int dir;
if ((current_pointer_x() - last_pointer_x()) > 0) {
if ((_drags->current_pointer_x() - last_pointer_x()) > 0) {
dir = 1;
} else {
dir = -1;
@ -1501,7 +1620,7 @@ NoteResizeDrag::motion (GdkEvent* /*event*/, bool /*first_move*/)
{
MidiRegionSelection& ms (_editor->get_selection().midi_regions);
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
(*r)->update_resizing (at_front, current_pointer_x() - grab_x(), relative);
(*r)->update_resizing (at_front, _drags->current_pointer_x() - grab_x(), relative);
}
}
@ -1510,7 +1629,7 @@ NoteResizeDrag::finished (GdkEvent*, bool /*movement_occurred*/)
{
MidiRegionSelection& ms (_editor->get_selection().midi_regions);
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
(*r)->commit_resizing (at_front, current_pointer_x() - grab_x(), relative);
(*r)->commit_resizing (at_front, _drags->current_pointer_x() - grab_x(), relative);
}
}
@ -1754,7 +1873,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
} else {
/* no mouse movement */
_editor->point_trim (event);
_editor->point_trim (event, adjusted_current_frame (event));
}
}
@ -2614,8 +2733,8 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
void
ControlPointDrag::motion (GdkEvent* event, bool)
{
double dx = current_pointer_x() - last_pointer_x();
double dy = current_pointer_y() - last_pointer_y();
double dx = _drags->current_pointer_x() - last_pointer_x();
double dy = _drags->current_pointer_y() - last_pointer_y();
if (event->button.state & Keyboard::SecondaryModifier) {
dx *= 0.1;
@ -2753,7 +2872,7 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
void
LineDrag::motion (GdkEvent* event, bool)
{
double dy = current_pointer_y() - last_pointer_y();
double dy = _drags->current_pointer_y() - last_pointer_y();
if (event->button.state & Keyboard::SecondaryModifier) {
dy *= 0.1;
@ -2827,11 +2946,11 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool)
start = grab;
}
if (current_pointer_y() < grab_y()) {
y1 = current_pointer_y();
if (_drags->current_pointer_y() < grab_y()) {
y1 = _drags->current_pointer_y();
y2 = grab_y();
} else {
y2 = current_pointer_y();
y2 = _drags->current_pointer_y();
y1 = grab_y();
}
@ -2861,11 +2980,11 @@ RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred)
motion (event, false);
double y1,y2;
if (current_pointer_y() < grab_y()) {
y1 = current_pointer_y();
if (_drags->current_pointer_y() < grab_y()) {
y1 = _drags->current_pointer_y();
y2 = grab_y();
} else {
y2 = current_pointer_y();
y2 = _drags->current_pointer_y();
y1 = grab_y();
}
@ -2978,7 +3097,7 @@ ScrubDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
void
ScrubDrag::motion (GdkEvent* /*event*/, bool)
{
_editor->scrub ();
_editor->scrub (adjusted_current_frame (0, false), _drags->current_pointer_x ());
}
void
@ -3060,7 +3179,7 @@ SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
_editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
_original_pointer_time_axis = _editor->trackview_by_y_position (current_pointer_y ()).first->order ();
_original_pointer_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()).first->order ();
}
void
@ -3070,7 +3189,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
nframes64_t end = 0;
nframes64_t length;
pair<TimeAxisView*, int> const pending_time_axis = _editor->trackview_by_y_position (current_pointer_y ());
pair<TimeAxisView*, int> const pending_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ());
if (pending_time_axis.first == 0) {
return;
}
@ -3547,8 +3666,8 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
double event_x;
double event_y;
event_x = current_pointer_x();
event_y = current_pointer_y();
event_x = _drags->current_pointer_x();
event_y = _drags->current_pointer_y();
_item->property_parent().get_value()->w2i(event_x, event_y);
@ -3585,8 +3704,8 @@ NoteDrag::motion (GdkEvent*, bool)
double event_x;
double event_y;
event_x = current_pointer_x();
event_y = current_pointer_y();
event_x = _drags->current_pointer_x();
event_y = _drags->current_pointer_y();
_item->property_parent().get_value()->w2i(event_x, event_y);
@ -3738,7 +3857,7 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
return;
}
_line->start_drag_multiple (points, 1 - (current_pointer_y() / _line->height ()), state);
_line->start_drag_multiple (points, 1 - (_drags->current_pointer_y() / _line->height ()), state);
}
void
@ -3748,7 +3867,7 @@ AutomationRangeDrag::motion (GdkEvent* event, bool first_move)
return;
}
float const f = 1 - (current_pointer_y() / _line->height());
float const f = 1 - (_drags->current_pointer_y() / _line->height());
/* we are ignoring x position for this drag, so we can just pass in anything */
_line->drag_motion (0, f, true, false);

View File

@ -37,29 +37,36 @@ namespace ARDOUR {
class Editor;
class EditorCursor;
class TimeAxisView;
class Drag;
/** Abstract base class for dragging of things within the editor */
class Drag
/** Class to manage current drags */
class DragManager
{
public:
Drag (Editor *, ArdourCanvas::Item *);
virtual ~Drag () {}
/** @return the canvas item being dragged */
ArdourCanvas::Item* item () const {
return _item;
}
DragManager (Editor* e);
~DragManager ();
void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
bool motion_handler (GdkEvent*, bool);
bool motion_handler (GdkEvent *, bool);
void abort ();
void break_drag ();
void add (Drag *);
void set (Drag *, GdkEvent *, Gdk::Cursor* c = 0);
void start_grab (GdkEvent *);
bool end_grab (GdkEvent *);
bool have_item (ArdourCanvas::Item *) const;
std::pair<nframes64_t, nframes64_t> extent () const;
/** @return true if an end drag is in progress */
/** @return true if an end drag or break_drag is in progress */
bool ending () const {
return _ending;
}
bool active () const {
return !_drags.empty ();
}
/** @return current pointer x position in trackview coordinates */
double current_pointer_x () const {
return _current_pointer_x;
@ -70,6 +77,40 @@ public:
return _current_pointer_y;
}
/** @return current pointer frame */
nframes64_t current_pointer_frame () const {
return _current_pointer_frame;
}
private:
Editor* _editor;
std::list<Drag*> _drags;
bool _ending; ///< true if end_grab or break_drag is in progress, otherwise false
double _current_pointer_x; ///< trackview x of the current pointer
double _current_pointer_y; ///< trackview y of the current pointer
nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
};
/** Abstract base class for dragging of things within the editor */
class Drag
{
public:
Drag (Editor *, ArdourCanvas::Item *);
virtual ~Drag () {}
void set_manager (DragManager* m) {
_drags = m;
}
/** @return the canvas item being dragged */
ArdourCanvas::Item* item () const {
return _item;
}
void swap_grab (ArdourCanvas::Item *, Gdk::Cursor *, uint32_t);
bool motion_handler (GdkEvent*, bool);
void break_drag ();
nframes64_t adjusted_frame (nframes64_t, GdkEvent const *, bool snap = true) const;
nframes64_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
@ -156,6 +197,7 @@ protected:
}
Editor* _editor; ///< our editor
DragManager* _drags;
ArdourCanvas::Item* _item; ///< our item
/** Offset from the mouse's position for the drag to the start of the thing that is being dragged */
nframes64_t _pointer_frame_offset;
@ -165,17 +207,13 @@ protected:
private:
bool _ending; ///< true if end_grab or break_drag is in progress, otherwise false
bool _move_threshold_passed; ///< true if the move threshold has been passed, otherwise false
double _grab_x; ///< trackview x of the grab start position
double _grab_y; ///< trackview y of the grab start position
double _current_pointer_x; ///< trackview x of the current pointer
double _current_pointer_y; ///< trackview y of the current pointer
double _last_pointer_x; ///< trackview x of the pointer last time a motion occurred
double _last_pointer_y; ///< trackview y of the pointer last time a motion occurred
nframes64_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
nframes64_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
nframes64_t _current_pointer_frame; ///< frame that the pointer is now at
};

View File

@ -53,10 +53,8 @@ Editor::kbd_driver (sigc::slot<void,GdkEvent*> theslot, bool use_track_canvas, b
/* any use of "keyboard mouse buttons" invalidates an existing grab
*/
if (_drag) {
_drag->item()->ungrab (GDK_CURRENT_TIME);
delete _drag;
_drag = 0;
if (_drags->active ()) {
_drags->abort ();
}
if (doit) {

View File

@ -37,6 +37,7 @@
#include "simplerect.h"
#include "actions.h"
#include "prompter.h"
#include "editor_drag.h"
#include "i18n.h"
@ -1088,7 +1089,7 @@ Editor::new_transport_marker_menu_popdown ()
// hide rects
transport_bar_drag_rect->hide();
break_drag ();
_drags->break_drag ();
}
void

View File

@ -36,6 +36,7 @@
#include "editor_route_groups.h"
#include "editor_regions.h"
#include "gui_thread.h"
#include "editor_drag.h"
#include "i18n.h"
@ -342,7 +343,7 @@ Editor::session_going_away ()
entered_regionview = 0;
entered_track = 0;
last_update_frame = 0;
_drag = 0;
_drags->abort ();
playhead_cursor->canvas_item.hide ();

View File

@ -271,7 +271,7 @@ Editor::set_canvas_cursor ()
void
Editor::set_mouse_mode (MouseMode m, bool force)
{
if (_drag) {
if (_drags->active ()) {
return;
}
@ -462,7 +462,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
set_selected_track_as_side_effect (true);
}
if (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT && !selection->regions.empty()) {
select_range_around_region (selection->regions.front());
clicked_selection = select_range_around_region (selection->regions.front());
}
break;
@ -514,10 +514,8 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
bool
Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
if (_drag) {
_drag->item()->ungrab (event->button.time);
delete _drag;
_drag = 0;
if (_drags->active ()) {
_drags->abort ();
}
/* single mouse clicks on any of these item types operate
@ -528,83 +526,73 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
switch (item_type) {
case PlayheadCursorItem:
assert (_drag == 0);
_drag = new CursorDrag (this, item, true);
_drag->start_grab (event);
_drags->set (new CursorDrag (this, item, true), event);
return true;
case MarkerItem:
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
hide_marker (item, event);
} else {
assert (_drag == 0);
_drag = new MarkerDrag (this, item);
_drag->start_grab (event);
_drags->set (new MarkerDrag (this, item), event);
}
return true;
case TempoMarkerItem:
assert (_drag == 0);
_drag = new TempoMarkerDrag (
this,
item,
Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
_drags->set (
new TempoMarkerDrag (
this,
item,
Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
),
event
);
_drag->start_grab (event);
return true;
case MeterMarkerItem:
assert (_drag == 0);
_drag = new MeterMarkerDrag (
this,
item,
Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
_drags->set (
new MeterMarkerDrag (
this,
item,
Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
),
event
);
_drag->start_grab (event);
return true;
case MarkerBarItem:
case TempoBarItem:
case MeterBarItem:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
assert (_drag == 0);
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
_drag->start_grab (event);
_drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event);
}
return true;
break;
case RangeMarkerBarItem:
assert (_drag == 0);
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
_drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event);
} else {
_drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateRangeMarker);
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateRangeMarker), event);
}
_drag->start_grab (event);
return true;
break;
case CdMarkerBarItem:
assert (_drag == 0);
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
_drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event);
} else {
_drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateCDMarker);
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateCDMarker), event);
}
_drag->start_grab (event);
return true;
break;
case TransportMarkerBarItem:
assert (_drag == 0);
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
_drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), event);
} else {
_drag = new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateTransportMarker);
_drags->set (new RangeMarkerBarDrag (this, item, RangeMarkerBarDrag::CreateTransportMarker), event);
}
_drag->start_grab (event);
return true;
break;
@ -620,13 +608,9 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
over a region.
*/
if (item_type == StartSelectionTrimItem) {
assert (_drag == 0);
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim);
_drag->start_grab (event);
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim), event);
} else if (item_type == EndSelectionTrimItem) {
assert (_drag == 0);
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim);
_drag->start_grab (event);
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim), event);
}
}
@ -636,15 +620,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MouseRange:
switch (item_type) {
case StartSelectionTrimItem:
assert (_drag == 0);
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim);
_drag->start_grab (event);
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionStartTrim), event);
break;
case EndSelectionTrimItem:
assert (_drag == 0);
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim);
_drag->start_grab (event);
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionEndTrim), event);
break;
case SelectionItem:
@ -654,32 +634,26 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
start_selection_grab (item, event);
} else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
/* grab selection for moving */
assert (_drag == 0);
_drag = new SelectionDrag (this, item, SelectionDrag::SelectionMove);
_drag->start_grab (event);
_drags->set (new SelectionDrag (this, item, SelectionDrag::SelectionMove), event);
} else {
double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize;
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
if (tvp.first) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
assert (_drag == 0);
if (join_object_range_button.get_active() && atv) {
/* smart "join" mode: drag automation */
_drag = new AutomationRangeDrag (this, atv->base_item(), selection->time);
_drags->set (new AutomationRangeDrag (this, atv->base_item(), selection->time), event);
} else {
/* this was debated, but decided the more common action was to
make a new selection */
_drag = new SelectionDrag (this, item, SelectionDrag::CreateSelection);
_drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event);
}
_drag->start_grab (event);
}
}
break;
default:
assert (_drag == 0);
_drag = new SelectionDrag (this, item, SelectionDrag::CreateSelection);
_drag->start_grab (event);
_drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event);
}
return true;
break;
@ -689,9 +663,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case NoteItem:
if (internal_editing()) {
/* Note: we don't get here if not in internal_editing() mode */
assert (_drag == 0);
_drag = new NoteDrag (this, item);
_drag->start_grab (event);
_drags->set (new NoteDrag (this, item), event);
return true;
}
break;
@ -703,47 +675,45 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) &&
event->type == GDK_BUTTON_PRESS) {
assert (_drag == 0);
_drag = new RubberbandSelectDrag (this, item);
_drag->start_grab (event);
_drags->set (new RubberbandSelectDrag (this, item), event);
} else if (event->type == GDK_BUTTON_PRESS) {
switch (item_type) {
case FadeInHandleItem:
{
assert (_drag == 0);
RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit);
_drag = new FadeInDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), s);
_drag->start_grab (event);
_drags->set (new FadeInDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), s), event);
return true;
}
case FadeOutHandleItem:
{
assert (_drag == 0);
RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit);
_drag = new FadeOutDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), s);
_drag->start_grab (event);
_drags->set (new FadeOutDrag (this, item, reinterpret_cast<RegionView*> (item->get_data("regionview")), s), event);
return true;
}
case RegionItem:
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
start_region_copy_grab (item, event, clicked_regionview);
add_region_copy_drag (item, event, clicked_regionview);
} else if (Keyboard::the_keyboard().key_is_down (GDK_b)) {
start_region_brush_grab (item, event, clicked_regionview);
add_region_brush_drag (item, event, clicked_regionview);
} else {
start_region_grab (item, event, clicked_regionview);
add_region_drag (item, event, clicked_regionview);
}
if (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT && !selection->regions.empty()) {
_drags->add (new SelectionDrag (this, clicked_axisview->get_selection_rect (clicked_selection)->rect, SelectionDrag::SelectionMove));
}
_drags->start_grab (event);
break;
case RegionViewNameHighlight:
{
assert (_drag == 0);
RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit);
_drag = new TrimDrag (this, item, clicked_regionview, s.by_layer());
_drag->start_grab (event);
_drags->set (new TrimDrag (this, item, clicked_regionview, s.by_layer()), event);
return true;
break;
}
@ -751,61 +721,68 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case RegionViewName:
{
/* rename happens on edit clicks */
assert (_drag == 0);
RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit);
_drag = new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, s.by_layer());
_drag->start_grab (event);
_drags->set (new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, s.by_layer()), event);
return true;
break;
}
case ControlPointItem:
assert (_drag == 0);
_drag = new ControlPointDrag (this, item);
_drag->start_grab (event);
_drags->set (new ControlPointDrag (this, item), event);
return true;
break;
case AutomationLineItem:
assert (_drag == 0);
_drag = new LineDrag (this, item);
_drag->start_grab (event);
_drags->set (new LineDrag (this, item), event);
return true;
break;
case StreamItem:
if (internal_editing()) {
assert (_drag == 0);
_drag = new RegionCreateDrag (this, item, clicked_axisview);
_drag->start_grab (event);
_drags->set (new RegionCreateDrag (this, item, clicked_axisview), event);
return true;
} else {
assert (_drag == 0);
_drag = new RubberbandSelectDrag (this, item);
_drag->start_grab (event);
_drags->set (new RubberbandSelectDrag (this, item), event);
}
break;
case AutomationTrackItem:
assert (_drag == 0);
/* rubberband drag to select automation points */
_drag = new RubberbandSelectDrag (this, item);
_drag->start_grab (event);
_drags->set (new RubberbandSelectDrag (this, item), event);
break;
case SelectionItem:
{
if (join_object_range_button.get_active()) {
/* we're in "smart" joined mode, and we've clicked on a Selection; if we're
* over an automation track, start a drag of its data */
/* we're in "smart" joined mode, and we've clicked on a Selection */
double const y = event->button.y + vertical_adjustment.get_value() - canvas_timebars_vsize;
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y);
if (tvp.first) {
/* if we're over an automation track, start a drag of its data */
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
if (atv) {
assert (_drag == 0);
_drag = new AutomationRangeDrag (this, atv->base_item(), selection->time);
_drag->start_grab (event);
_drags->set (new AutomationRangeDrag (this, atv->base_item(), selection->time), event);
}
/* if we're over a track and a region, and in the `object' part of a region,
put a selection around the region and drag both
*/
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
if (rtv && _join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) {
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (rtv->route ());
if (t) {
boost::shared_ptr<Playlist> pl = t->diskstream()->playlist ();
if (pl) {
boost::shared_ptr<Region> r = pl->top_region_at (unit_to_frame (event->button.x));
RegionView* rv = rtv->view()->find_view (r);
clicked_selection = select_range_around_region (rv);
_drags->add (new SelectionDrag (this, item, SelectionDrag::SelectionMove));
list<RegionView*> rvs;
rvs.push_back (rv);
_drags->add (new RegionMoveDrag (this, item, rv, rvs, false, false));
_drags->start_grab (event);
}
}
}
}
}
@ -854,21 +831,15 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
/* start a grab so that if we finish after moving
we can tell what happened.
*/
assert (_drag == 0);
_drag = new RegionGainDrag (this, item);
_drag->start_grab (event, current_canvas_cursor);
_drags->set (new RegionGainDrag (this, item), event, current_canvas_cursor);
break;
case GainLineItem:
assert (_drag == 0);
_drag = new LineDrag (this, item);
_drag->start_grab (event);
_drags->set (new LineDrag (this, item), event);
return true;
case ControlPointItem:
assert (_drag == 0);
_drag = new ControlPointDrag (this, item);
_drag->start_grab (event);
_drags->set (new ControlPointDrag (this, item), event);
return true;
break;
@ -880,15 +851,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
switch (item_type) {
case ControlPointItem:
assert (_drag == 0);
_drag = new ControlPointDrag (this, item);
_drag->start_grab (event);
_drags->set (new ControlPointDrag (this, item), event);
break;
case AutomationLineItem:
assert (_drag == 0);
_drag = new LineDrag (this, item);
_drag->start_grab (event);
_drags->set (new LineDrag (this, item), event);
break;
case RegionItem:
@ -905,9 +872,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MouseZoom:
if (event->type == GDK_BUTTON_PRESS) {
assert (_drag == 0);
_drag = new MouseZoomDrag (this, item);
_drag->start_grab (event);
_drags->set (new MouseZoomDrag (this, item), event);
}
return true;
@ -915,21 +880,16 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MouseTimeFX:
if (internal_editing() && item_type == NoteItem) {
assert (_drag == 0);
_drag = new NoteResizeDrag (this, item);
_drag->start_grab (event);
_drags->set (new NoteResizeDrag (this, item), event);
return true;
} else if (!internal_editing() && item_type == RegionItem) {
assert (_drag == 0);
_drag = new TimeFXDrag (this, item, clicked_regionview, selection->regions.by_layer());
_drag->start_grab (event);
_drags->set (new TimeFXDrag (this, item, clicked_regionview, selection->regions.by_layer()), event);
return true;
}
break;
case MouseAudition:
_drag = new ScrubDrag (this, item);
_drag->start_grab (event);
_drags->set (new ScrubDrag (this, item), event);
scrub_reversals = 0;
scrub_reverse_distance = 0;
last_scrub_x = event->button.x;
@ -954,16 +914,15 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
switch (item_type) {
case RegionItem:
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
start_region_copy_grab (item, event, clicked_regionview);
add_region_copy_drag (item, event, clicked_regionview);
} else {
start_region_grab (item, event, clicked_regionview);
add_region_drag (item, event, clicked_regionview);
}
_drags->start_grab (event);
return true;
break;
case ControlPointItem:
assert (_drag == 0);
_drag = new ControlPointDrag (this, item);
_drag->start_grab (event);
_drags->set (new ControlPointDrag (this, item), event);
return true;
break;
@ -973,16 +932,12 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
switch (item_type) {
case RegionViewNameHighlight:
assert (_drag == 0);
_drag = new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer());
_drag->start_grab (event);
_drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer()), event);
return true;
break;
case RegionViewName:
assert (_drag == 0);
_drag = new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer());
_drag->start_grab (event);
_drags->set (new TrimDrag (this, clicked_regionview->get_name_highlight(), clicked_regionview, selection->regions.by_layer()), event);
return true;
break;
@ -1047,7 +1002,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
button_selection (item, event, item_type);
if (_drag == 0 &&
if (!_drags->active () &&
(Keyboard::is_delete_event (&event->button) ||
Keyboard::is_context_menu_event (&event->button) ||
Keyboard::is_edit_event (&event->button))) {
@ -1091,10 +1046,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
/* first, see if we're finishing a drag ... */
bool were_dragging = false;
if (_drag) {
bool const r = _drag->end_grab (event);
delete _drag;
_drag = 0;
if (_drags->active ()) {
bool const r = _drags->end_grab (event);
if (r) {
/* grab dragged, so do nothing else */
return true;
@ -1107,7 +1060,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
/* edit events get handled here */
if (_drag == 0 && Keyboard::is_edit_event (&event->button)) {
if (!_drags->active () && Keyboard::is_edit_event (&event->button)) {
switch (item_type) {
case RegionItem:
edit_region ();
@ -1141,7 +1094,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
if (Keyboard::is_context_menu_event (&event->button)) {
if (_drag == 0) {
if (!_drags->active ()) {
/* no matter which button pops up the context menu, tell the menu
widget to use button 1 to drive menu selection.
@ -1225,7 +1178,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
Editing::MouseMode const eff = effective_mouse_mode ();
if (_drag == 0 && Keyboard::is_delete_event (&event->button)) {
if (!_drags->active () && Keyboard::is_delete_event (&event->button)) {
switch (item_type) {
case TempoMarkerItem:
@ -1447,7 +1400,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
fraction = 1.0 - (cp->get_y() / cp->line().height());
if (is_drawable() && dynamic_cast<ScrubDrag*> (_drag) == 0) {
if (is_drawable() && !_drags->active ()) {
track_canvas->get_window()->set_cursor (*fader_cursor);
}
@ -1734,10 +1687,6 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
break;
}
if (item_type == RegionItem) {
update_join_object_range_location (event->crossing.x, event->crossing.y);
}
return false;
}
@ -1752,19 +1701,19 @@ Editor::left_automation_track ()
}
void
Editor::scrub ()
Editor::scrub (nframes64_t frame, double current_x)
{
double delta;
if (scrubbing_direction == 0) {
/* first move */
_session->request_locate (_drag->adjusted_current_frame (0), false);
_session->request_locate (frame, false);
_session->request_transport_speed (0.1);
scrubbing_direction = 1;
} else {
if (last_scrub_x > _drag->current_pointer_x()) {
if (last_scrub_x > current_x) {
/* pointer moved to the left */
@ -1773,7 +1722,7 @@ Editor::scrub ()
/* we reversed direction to go backwards */
scrub_reversals++;
scrub_reverse_distance += (int) (last_scrub_x - _drag->current_pointer_x());
scrub_reverse_distance += (int) (last_scrub_x - current_x);
} else {
@ -1782,7 +1731,7 @@ Editor::scrub ()
scrub_reversals = 0;
scrub_reverse_distance = 0;
delta = 0.01 * (last_scrub_x - _drag->current_pointer_x());
delta = 0.01 * (last_scrub_x - current_x);
_session->request_transport_speed (_session->transport_speed() - delta);
}
@ -1793,7 +1742,7 @@ Editor::scrub ()
/* we reversed direction to go forward */
scrub_reversals++;
scrub_reverse_distance += (int) (_drag->current_pointer_x() - last_scrub_x);
scrub_reverse_distance += (int) (current_x - last_scrub_x);
} else {
/* still moving to the right */
@ -1801,7 +1750,7 @@ Editor::scrub ()
scrub_reversals = 0;
scrub_reverse_distance = 0;
delta = 0.01 * (_drag->current_pointer_x() - last_scrub_x);
delta = 0.01 * (current_x - last_scrub_x);
_session->request_transport_speed (_session->transport_speed() + delta);
}
}
@ -1827,7 +1776,7 @@ Editor::scrub ()
}
}
last_scrub_x = _drag->current_pointer_x();
last_scrub_x = current_x;
}
bool
@ -1866,8 +1815,8 @@ Editor::motion_handler (ArdourCanvas::Item* /*item*/, GdkEvent* event, bool from
}
bool handled = false;
if (_drag) {
handled = _drag->motion_handler (event, from_autoscroll);
if (_drags->active ()) {
handled = _drags->motion_handler (event, from_autoscroll);
}
if (!handled) {
@ -2042,7 +1991,7 @@ Editor::show_verbose_time_cursor (nframes64_t frame, double offset, double xpos,
if (xpos >= 0 && ypos >=0) {
set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset);
} else {
set_verbose_canvas_cursor (buf, _drag->current_pointer_x() + offset - horizontal_adjustment.get_value(), _drag->current_pointer_y() + offset - vertical_adjustment.get_value() + canvas_timebars_vsize);
set_verbose_canvas_cursor (buf, _drags->current_pointer_x() + offset - horizontal_adjustment.get_value(), _drags->current_pointer_y() + offset - vertical_adjustment.get_value() + canvas_timebars_vsize);
}
show_verbose_canvas_cursor ();
}
@ -2124,7 +2073,7 @@ Editor::show_verbose_duration_cursor (nframes64_t start, nframes64_t end, double
set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset);
}
else {
set_verbose_canvas_cursor (buf, _drag->current_pointer_x() + offset, _drag->current_pointer_y() + offset);
set_verbose_canvas_cursor (buf, _drags->current_pointer_x() + offset, _drags->current_pointer_y() + offset);
}
show_verbose_canvas_cursor ();
@ -2310,14 +2259,10 @@ Editor::single_end_trim (RegionView& rv, nframes64_t frame_delta, bool left_dire
void
Editor::point_trim (GdkEvent* event)
Editor::point_trim (GdkEvent* event, nframes64_t new_bound)
{
RegionView* rv = clicked_regionview;
nframes64_t new_bound = _drag->adjusted_current_frame (event);
snap_to_with_modifier (new_bound, event);
/* Choose action dependant on which button was pressed */
switch (event->button.button) {
case 1:
@ -2519,23 +2464,19 @@ Editor::track_height_step_timeout ()
}
void
Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
Editor::add_region_drag (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
{
assert (region_view);
_region_motion_group->raise_to_top ();
assert (_drag == 0);
if (Config->get_edit_mode() == Splice) {
_drag = new RegionSpliceDrag (this, item, region_view, selection->regions.by_layer());
_drags->add (new RegionSpliceDrag (this, item, region_view, selection->regions.by_layer()));
} else {
RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit);
_drag = new RegionMoveDrag (this, item, region_view, s.by_layer(), false, false);
_drags->add (new RegionMoveDrag (this, item, region_view, s.by_layer(), false, false));
}
_drag->start_grab (event);
begin_reversible_command (_("move region(s)"));
/* sync the canvas to what we think is its current state */
@ -2543,31 +2484,27 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView
}
void
Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
Editor::add_region_copy_drag (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
{
assert (region_view);
assert (_drag == 0);
_region_motion_group->raise_to_top ();
RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit);
_drag = new RegionMoveDrag (this, item, region_view, s.by_layer(), false, true);
_drag->start_grab(event);
_drags->add (new RegionMoveDrag (this, item, region_view, s.by_layer(), false, true));
}
void
Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
Editor::add_region_brush_drag (ArdourCanvas::Item* item, GdkEvent* event, RegionView* region_view)
{
assert (region_view);
assert (_drag == 0);
if (Config->get_edit_mode() == Splice) {
return;
}
RegionSelection s = get_equivalent_regions (selection->regions, RouteGroup::Edit);
_drag = new RegionMoveDrag (this, item, region_view, s.by_layer(), true, false);
_drag->start_grab (event);
_drags->add (new RegionMoveDrag (this, item, region_view, s.by_layer(), true, false));
begin_reversible_command (_("Drag region brush"));
}
@ -2633,31 +2570,19 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event)
*/
selection->set (latest_regionviews);
assert (_drag == 0);
_drag = new RegionMoveDrag (this, latest_regionviews.front()->get_canvas_group(), latest_regionviews.front(), latest_regionviews, false, false);
_drag->start_grab (event);
_drags->set (new RegionMoveDrag (this, latest_regionviews.front()->get_canvas_group(), latest_regionviews.front(), latest_regionviews, false, false), event);
}
void
Editor::escape ()
{
if (_drag) {
break_drag ();
if (_drags->active ()) {
_drags->break_drag ();
} else {
selection->clear ();
}
}
void
Editor::break_drag ()
{
if (_drag) {
_drag->break_drag ();
delete _drag;
_drag = 0;
}
}
void
Editor::set_internal_edit (bool yn)
{
@ -2700,33 +2625,37 @@ Editor::set_internal_edit (bool yn)
void
Editor::update_join_object_range_location (double x, double y)
{
/* XXX: actually, this decides based on whether the mouse is in the top or bottom half of a RouteTimeAxisView;
entered_{track,regionview} is not always setup (e.g. if the mouse is over a TimeSelection), and to get a Region
that we're over requires searching the playlist.
*/
if (join_object_range_button.get_active() == false || (mouse_mode != MouseRange && mouse_mode != MouseObject)) {
_join_object_range_state = JOIN_OBJECT_RANGE_NONE;
return;
}
if (mouse_mode == MouseObject) {
_join_object_range_state = JOIN_OBJECT_RANGE_OBJECT;
} else if (mouse_mode == MouseRange) {
_join_object_range_state = JOIN_OBJECT_RANGE_RANGE;
}
if (entered_regionview) {
/* XXX: maybe we should make entered_track work in all cases, rather than resorting to this */
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y + vertical_adjustment.get_value() - canvas_timebars_vsize);
if (tvp.first) {
double cx = x;
double cy = y;
entered_regionview->get_canvas_group()->w2i (cx, cy);
double x1;
double y1;
double x2;
double y2;
entered_regionview->get_canvas_group()->get_bounds (x1, y1, x2, y2);
bool const top_half = cy < (y2 - y1) / 2;
_join_object_range_state = top_half ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT;
} else {
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
if (rtv) {
if (mouse_mode == MouseObject) {
_join_object_range_state = JOIN_OBJECT_RANGE_OBJECT;
} else if (mouse_mode == MouseRange) {
_join_object_range_state = JOIN_OBJECT_RANGE_RANGE;
double cx = 0;
double cy = y;
rtv->canvas_display()->w2i (cx, cy);
bool const top_half = cy < rtv->current_height () / 2;
_join_object_range_state = top_half ? JOIN_OBJECT_RANGE_RANGE : JOIN_OBJECT_RANGE_OBJECT;
}
}
}

View File

@ -3826,10 +3826,8 @@ Editor::cut_copy (CutCopyOp op)
*/
if (op == Cut || op == Clear) {
if (_drag) {
_drag->item()->ungrab (0);
delete _drag;
_drag = 0;
if (_drags->active ()) {
_drags->abort ();
}
}
@ -3846,10 +3844,7 @@ Editor::cut_copy (CutCopyOp op)
Glib::signal_idle().connect (sigc::bind (sigc::mem_fun(*this, &Editor::really_remove_marker), loc));
}
break_drag ();
delete _drag;
_drag = 0;
_drags->break_drag ();
return;
}
@ -3930,9 +3925,7 @@ Editor::cut_copy (CutCopyOp op)
}
if (op == Cut || op == Clear) {
break_drag ();
delete _drag;
_drag = 0;
_drags->break_drag ();
}
}

View File

@ -246,9 +246,7 @@ Editor::ruler_button_press (GdkEventButton* ev)
}
/* playhead cursor */
assert (_drag == 0);
_drag = new CursorDrag (this, &playhead_cursor->canvas_item, false);
_drag->start_grab (reinterpret_cast<GdkEvent *> (ev));
_drags->set (new CursorDrag (this, &playhead_cursor->canvas_item, false), reinterpret_cast<GdkEvent *> (ev));
_dragging_playhead = true;
}
@ -265,10 +263,8 @@ Editor::ruler_button_release (GdkEventButton* ev)
gint x,y;
Gdk::ModifierType state;
if (_drag) {
_drag->end_grab (reinterpret_cast<GdkEvent*> (ev));
delete _drag;
_drag = 0;
if (_drags->active ()) {
_drags->end_grab (reinterpret_cast<GdkEvent*> (ev));
_dragging_playhead = false;
}
@ -312,8 +308,8 @@ Editor::ruler_mouse_motion (GdkEventMotion* ev)
return FALSE;
}
if (_drag) {
_drag->motion_handler (reinterpret_cast<GdkEvent*> (ev), false);
if (_drags->active ()) {
_drags->motion_handler (reinterpret_cast<GdkEvent*> (ev), false);
}
return TRUE;

View File

@ -1418,12 +1418,12 @@ Editor::deselect_all ()
selection->clear ();
}
void
long
Editor::select_range_around_region (RegionView* rv)
{
selection->set (&rv->get_time_axis_view());
selection->time.clear ();
boost::shared_ptr<Region> r = rv->region ();
selection->set (r->position(), r->position() + r->length());
return selection->set (r->position(), r->position() + r->length());
}

View File

@ -221,6 +221,8 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful
typedef std::vector<boost::shared_ptr<TimeAxisView> > Children;
SelectionRect* get_selection_rect(uint32_t id);
protected:
/* The Standard LHS Controls */
Gtk::HBox controls_hbox;
@ -317,8 +319,6 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful
std::list<SelectionRect*> free_selection_rects;
std::list<SelectionRect*> used_selection_rects;
SelectionRect* get_selection_rect(uint32_t id);
virtual void selection_click (GdkEventButton*);
bool _hidden;