#include "mouse_cursors.h"
#include "note_base.h"
#include "patch_change.h"
+#include "ui_config.h"
#include "verbose_cursor.h"
using namespace std;
DragManager::DragManager (Editor* e)
: _editor (e)
, _ending (false)
+ , _current_pointer_x (0.0)
+ , _current_pointer_y (0.0)
, _current_pointer_frame (0)
+ , _old_follow_playhead (false)
{
}
{
_ending = true;
- cerr << "Aborting drag\n";
-
for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
(*i)->abort ();
delete *i;
Drag::Drag (Editor* e, ArdourCanvas::Item* i, bool trackview_only)
: _editor (e)
+ , _drags (0)
, _item (i)
, _pointer_frame_offset (0)
+ , _x_constrained (false)
+ , _y_constrained (false)
+ , _was_rolling (false)
, _trackview_only (trackview_only)
, _move_threshold_passed (false)
, _starting_point_passed (false)
, _initially_vertical (false)
, _was_double_click (false)
+ , _grab_x (0.0)
+ , _grab_y (0.0)
+ , _last_pointer_x (0.0)
+ , _last_pointer_y (0.0)
, _raw_grab_frame (0)
, _grab_frame (0)
, _last_pointer_frame (0)
+ , _snap_delta (0)
{
}
void
Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
{
- // if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained
- if (Keyboard::is_button2_event (&event->button)) {
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::SecondaryModifier)) {
- _y_constrained = true;
- _x_constrained = false;
- } else {
- _y_constrained = false;
- _x_constrained = true;
- }
- } else {
- _x_constrained = false;
- _y_constrained = false;
- }
+ /* we set up x/y dragging constraints on first move */
_raw_grab_frame = _editor->canvas_event_sample (event, &_grab_x, &_grab_y);
return adjusted_frame (_drags->current_pointer_frame (), event, snap);
}
+frameoffset_t
+Drag::snap_delta (guint state) const
+{
+ if (ArdourKeyboard::indicates_snap_delta (state)) {
+ return _snap_delta;
+ }
+
+ return 0;
+}
+
double
Drag::current_pointer_x() const
{
return _drags->current_pointer_y () - _editor->get_trackview_group()->canvas_origin().y;
}
+void
+Drag::setup_snap_delta (framepos_t pos)
+{
+ framepos_t temp = pos;
+ _editor->snap_to (temp, ARDOUR::RoundNearest, false, true);
+ _snap_delta = temp - pos;
+}
+
bool
Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
{
} else {
_initially_vertical = false;
}
+ /** check constraints for this drag.
+ * Note that the current convention is to use "contains" for
+ * key modifiers during motion and "equals" when initiating a drag.
+ * In this case we haven't moved yet, so "equals" applies here.
+ */
+ if (Config->get_edit_mode() != Lock) {
+ if (event->motion.state & Gdk::BUTTON2_MASK) {
+ // if dragging with button2, the motion is x constrained, with constraint modifier it is y constrained
+ if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::constraint_modifier ())) {
+ _x_constrained = false;
+ _y_constrained = true;
+ } else {
+ _x_constrained = true;
+ _y_constrained = false;
+ }
+ } else if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::constraint_modifier ())) {
+ // if dragging normally, the motion is constrained to the first direction of movement.
+ if (_initially_vertical) {
+ _x_constrained = true;
+ _y_constrained = false;
+ } else {
+ _x_constrained = false;
+ _y_constrained = true;
+ }
+ }
+ } else {
+ if (event->button.state & Gdk::BUTTON2_MASK) {
+ _x_constrained = false;
+ } else {
+ _x_constrained = true;
+ }
+ _y_constrained = false;
+ }
}
if (!from_autoscroll) {
_last_pointer_x = _drags->current_pointer_x ();
_last_pointer_y = current_pointer_y ();
- _last_pointer_frame = adjusted_current_frame (event);
+ _last_pointer_frame = adjusted_current_frame (event, false);
}
return true;
}
boost::shared_ptr<Region>
-Drag::add_midi_region (MidiTimeAxisView* view)
+Drag::add_midi_region (MidiTimeAxisView* view, bool commit)
{
if (_editor->session()) {
const TempoMap& map (_editor->session()->tempo_map());
framecnt_t pos = grab_frame();
- const Meter& m = map.meter_at (pos);
/* not that the frame rate used here can be affected by pull up/down which
might be wrong.
*/
- framecnt_t len = m.frames_per_bar (map.tempo_at (pos), _editor->session()->frame_rate());
- return view->add_region (grab_frame(), len, true);
+ framecnt_t len = map.frame_at_beat (map.beat_at_frame (pos) + 1.0) - pos;
+ return view->add_region (grab_frame(), len, commit);
}
return boost::shared_ptr<Region>();
RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b)
: RegionDrag (e, i, p, v)
, _brushing (b)
+ , _ignore_video_lock (false)
, _total_x_delta (0)
, _last_pointer_time_axis_view (0)
, _last_pointer_layer (0)
- , _single_axis (false)
, _ndropzone (0)
, _pdropzone (0)
, _ddropzone (0)
- , _snap_delta (0)
{
DEBUG_TRACE (DEBUG::Drags, "New RegionMotionDrag\n");
}
RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{
Drag::start_grab (event, cursor);
-
- if (_editor->snap_delta () == SnapRelative) {
- framepos_t temp = _last_frame_position;
- _editor->snap_to_with_modifier (temp, event, RoundUpMaybe);
- _snap_delta = temp - _last_frame_position;
- }
-
- if (Keyboard::modifier_state_contains (event->button.state, Keyboard::TertiaryModifier)) {
- _single_axis = true;
- }
+ setup_snap_delta (_last_frame_position);
show_verbose_cursor_time (_last_frame_position);
assert(_last_pointer_time_axis_view >= 0);
_last_pointer_layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
}
+
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier))) {
+ _ignore_video_lock = true;
+ }
+
+ if (_brushing) {
+ /* cross track dragging seems broken here. disabled for now. */
+ _y_constrained = true;
+ }
}
double
/* compute the amount of pointer motion in frames, and where
the region would be if we moved it by that much.
*/
- *pending_region_position = adjusted_frame (_drags->current_pointer_frame () + _snap_delta, event, true);
+ *pending_region_position = adjusted_frame (_drags->current_pointer_frame (), event, false);
framepos_t sync_frame;
framecnt_t sync_offset;
*/
if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
- sync_frame = *pending_region_position + (sync_dir * sync_offset);
+ framecnt_t const sd = snap_delta (event->button.state);
+ sync_frame = *pending_region_position + (sync_dir * sync_offset) + sd;
_editor->snap_to_with_modifier (sync_frame, event);
- *pending_region_position = _primary->region()->adjust_to_sync (sync_frame) - _snap_delta;
+ *pending_region_position = _primary->region()->adjust_to_sync (sync_frame) - sd;
} else {
*pending_region_position = _last_frame_position;
double dx = 0;
- /* in locked edit mode, reverse the usual meaning of _x_constrained */
- bool const x_move_allowed = Config->get_edit_mode() == Lock ? _x_constrained : !_x_constrained;
+ bool const x_move_allowed = !_x_constrained;
if ((*pending_region_position != _last_frame_position) && x_move_allowed) {
assert (!_views.empty ());
- if (first_move) {
- if (_single_axis) {
- if (initially_vertical()) {
- _y_constrained = false;
- _x_constrained = true;
- } else {
- _y_constrained = true;
- _x_constrained = false;
- }
- }
- }
-
/* Note: time axis views in this method are often expressed as an index into the _time_axis_views vector */
/* Find the TimeAxisView that the pointer is now over */
}
/* for automation lanes, there is a TimeAxisView but no ->view()
- * if (!tv) -> dropzone
+ * if (!tv) -> dropzone
*/
else if (!tv && cur_y >= 0 && _last_pointer_time_axis_view >= 0) {
/* Moving into the drop-zone.. */
y_delta = 0;
- if (rv->region()->locked() || rv->region()->video_locked()) {
+ if (rv->region()->locked() || (rv->region()->video_locked() && !_ignore_video_lock)) {
continue;
}
* We do not use negative _last_pointer_time_axis_view because
* the dropzone is "packed" (the actual track offset is ignored)
*
- * As opposed to the actual number
+ * As opposed to the actual number
* of elements in the dropzone (_ndropzone)
* _pdropzone is not constrained. This is necessary
* to allow moving multiple regions with y-distance
RegionMoveDrag::motion (GdkEvent* event, bool first_move)
{
if (_copy && first_move) {
-
- if (_x_constrained) {
+ if (_x_constrained && !_brushing) {
_editor->begin_reversible_command (Operations::fixed_time_region_copy);
- } else {
+ } else if (!_brushing) {
_editor->begin_reversible_command (Operations::region_copy);
+ } else if (_brushing) {
+ _editor->begin_reversible_command (Operations::drag_region_brush);
}
-
/* duplicate the regionview(s) and region(s) */
list<DraggingView> new_regionviews;
}
} else if (!_copy && first_move) {
-
- if (_x_constrained) {
+ if (_x_constrained && !_brushing) {
_editor->begin_reversible_command (_("fixed time region drag"));
- } else {
+ } else if (!_brushing) {
_editor->begin_reversible_command (Operations::region_drag);
+ } else if (_brushing) {
+ _editor->begin_reversible_command (Operations::drag_region_brush);
}
}
-
RegionMotionDrag::motion (event, first_move);
}
return;
}
- /* reverse this here so that we have the correct logic to finalize
- the drag.
- */
-
- if (Config->get_edit_mode() == Lock) {
- _x_constrained = !_x_constrained;
- }
-
assert (!_views.empty ());
/* We might have hidden region views so that they weren't visible during the drag
RouteTimeAxisView* dest_rtv = 0;
- if (i->view->region()->locked() || i->view->region()->video_locked()) {
+ if (i->view->region()->locked() || (i->view->region()->video_locked() && !_ignore_video_lock)) {
continue;
}
set<RouteTimeAxisView*> views_to_update;
RouteTimeAxisView* new_time_axis_view = 0;
- if (_brushing) {
- /* all changes were made during motion event handlers */
- _editor->commit_reversible_command ();
- return;
- }
-
typedef map<boost::shared_ptr<Playlist>, RouteTimeAxisView*> PlaylistMapping;
PlaylistMapping playlist_mapping;
RegionView* rv = i->view;
RouteTimeAxisView* dest_rtv = 0;
- if (rv->region()->locked() || rv->region()->video_locked()) {
+ if (rv->region()->locked() || (rv->region()->video_locked() && !_ignore_video_lock)) {
++i;
continue;
}
}
rv->region()->set_position (where);
-
_editor->session()->add_command (new StatefulDiffCommand (rv->region()));
}
/* write commands for the accumulated diffs for all our modified playlists */
add_stateful_diff_commands_for_playlists (modified_playlists);
-
+ /* applies to _brushing */
_editor->commit_reversible_command ();
/* We have futzed with the layering of canvas items on our streamviews.
RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b, bool c)
: RegionMotionDrag (e, i, p, v, b)
, _copy (c)
+ , _new_region_view (0)
{
DEBUG_TRACE (DEBUG::Drags, "New RegionMoveDrag\n");
RegionCreateDrag::motion (GdkEvent* event, bool first_move)
{
if (first_move) {
- _region = add_midi_region (_view);
+ _editor->begin_reversible_command (_("create region"));
+ _region = add_midi_region (_view, false);
_view->playlist()->freeze ();
} else {
if (_region) {
framepos_t const f = adjusted_current_frame (event);
if (f < grab_frame()) {
- _region->set_position (f);
+ _region->set_initial_position (f);
}
/* Don't use a zero-length region, and subtract 1 frame from the snapped length
RegionCreateDrag::finished (GdkEvent*, bool movement_occurred)
{
if (!movement_occurred) {
- add_midi_region (_view);
+ add_midi_region (_view, true);
} else {
_view->playlist()->thaw ();
+ _editor->commit_reversible_command();
}
}
NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
, region (0)
+ , relative (false)
+ , at_front (true)
+ , _was_selected (false)
, _snap_delta (0)
{
DEBUG_TRACE (DEBUG::Drags, "New NoteResizeDrag\n");
region = &cnote->region_view();
- if (_editor->snap_delta () == SnapRelative) {
- double temp;
- temp = region->snap_to_pixel(cnote->x0 ());
- _snap_delta = temp - cnote->x0 ();
- /*
- if (at_front) {
- temp = region->snap_to_pixel(cnote->x0 ());
- _snap_delta = temp - cnote->x0 ();
- } else {
- temp = region->snap_to_pixel(cnote->x1 ());
- _snap_delta = temp - cnote->x1 ();
- }
- */
- }
+ double temp;
+ temp = region->snap_to_pixel (cnote->x0 (), true);
+ _snap_delta = temp - cnote->x0 ();
_item->grab ();
- if (event->motion.state & Keyboard::PrimaryModifier) {
+ if (event->motion.state & ArdourKeyboard::note_size_relative_modifier ()) {
relative = false;
} else {
relative = true;
}
-
MidiRegionSelection& ms (_editor->get_selection().midi_regions);
-
if (ms.size() > 1) {
/* has to be relative, may make no sense otherwise */
relative = true;
}
- /* select this note; if it is already selected, preserve the existing selection,
- otherwise make this note the only one selected.
- */
- region->note_selected (cnote, cnote->selected ());
+ if (!(_was_selected = cnote->selected())) {
+
+ /* tertiary-click means extend selection - we'll do that on button release,
+ so don't add it here, because otherwise we make it hard to figure
+ out the "extend-to" range.
+ */
- _editor->begin_reversible_command (_("resize notes"));
+ bool extend = Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier);
- for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ) {
- MidiRegionSelection::iterator next;
- next = r;
- ++next;
- MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
- if (mrv) {
- mrv->begin_resizing (at_front);
+ if (!extend) {
+ bool add = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+
+ if (add) {
+ region->note_selected (cnote, true);
+ } else {
+ _editor->get_selection().clear_points();
+ region->unique_select (cnote);
+ }
}
- r = next;
}
}
void
-NoteResizeDrag::motion (GdkEvent* /*event*/, bool /*first_move*/)
+NoteResizeDrag::motion (GdkEvent* event, bool first_move)
{
MidiRegionSelection& ms (_editor->get_selection().midi_regions);
+ if (first_move) {
+ _editor->begin_reversible_command (_("resize notes"));
+
+ for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ) {
+ MidiRegionSelection::iterator next;
+ next = r;
+ ++next;
+ MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
+ if (mrv) {
+ mrv->begin_resizing (at_front);
+ }
+ r = next;
+ }
+ }
+
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
NoteBase* nb = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
assert (nb);
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
if (mrv) {
- mrv->update_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, _snap_delta);
+ double sd = 0.0;
+ bool snap = true;
+ bool apply_snap_delta = ArdourKeyboard::indicates_snap_delta (event->button.state);
+
+ if (ArdourKeyboard::indicates_snap (event->button.state)) {
+ if (_editor->snap_mode () != SnapOff) {
+ snap = false;
+ }
+ } else {
+ if (_editor->snap_mode () == SnapOff) {
+ snap = false;
+ /* inverted logic here - we;re in snapoff but we've pressed the snap delta modifier */
+ if (apply_snap_delta) {
+ snap = true;
+ }
+ }
+ }
+
+ if (apply_snap_delta) {
+ sd = _snap_delta;
+ }
+
+ mrv->update_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, sd, snap);
}
}
}
void
-NoteResizeDrag::finished (GdkEvent*, bool /*movement_occurred*/)
+NoteResizeDrag::finished (GdkEvent* event, bool movement_occurred)
{
+ if (!movement_occurred) {
+ /* no motion - select note */
+ NoteBase* cnote = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
+ if (_editor->current_mouse_mode() == Editing::MouseContent ||
+ _editor->current_mouse_mode() == Editing::MouseDraw) {
+
+ bool changed = false;
+
+ if (_was_selected) {
+ bool add = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+ if (add) {
+ region->note_deselected (cnote);
+ changed = true;
+ } else {
+ _editor->get_selection().clear_points();
+ region->unique_select (cnote);
+ changed = true;
+ }
+ } else {
+ bool extend = Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier);
+ bool add = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
+
+ if (!extend && !add && region->selection_size() > 1) {
+ _editor->get_selection().clear_points();
+ region->unique_select (cnote);
+ changed = true;
+ } else if (extend) {
+ region->note_selected (cnote, true, true);
+ changed = true;
+ } else {
+ /* it was added during button press */
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ _editor->begin_reversible_selection_op(X_("Resize Select Note Release"));
+ _editor->commit_reversible_selection_op();
+ }
+ }
+
+ return;
+ }
+
MidiRegionSelection& ms (_editor->get_selection().midi_regions);
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
NoteBase* nb = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
assert (nb);
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
+ double sd = 0.0;
+ bool snap = true;
+ bool apply_snap_delta = ArdourKeyboard::indicates_snap_delta (event->button.state);
if (mrv) {
- mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, _snap_delta);
+ if (ArdourKeyboard::indicates_snap (event->button.state)) {
+ if (_editor->snap_mode () != SnapOff) {
+ snap = false;
+ }
+ } else {
+ if (_editor->snap_mode () == SnapOff) {
+ snap = false;
+ /* inverted logic here - we;re in snapoff but we've pressed the snap delta modifier */
+ if (apply_snap_delta) {
+ snap = true;
+ }
+ }
+ }
+
+ if (apply_snap_delta) {
+ sd = _snap_delta;
+ }
+
+ mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, sd, snap);
}
}
_editor->get_regions_after(rs, (framepos_t) 0, empty);
std::list<RegionView*> views = rs.by_layer();
+ _stuck = false;
for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
RegionView* rv = (*i);
if (!rv->region()->video_locked()) {
continue;
}
+ if (rv->region()->locked()) {
+ _stuck = true;
+ }
_views.push_back (AVDraggingView (rv));
}
}
return;
}
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier))) {
+ _stuck = false;
+ _views.clear();
+ }
+
+ if (_stuck) {
+ show_verbose_cursor_text (_("One or more Audio Regions\nare both Locked and\nLocked to Video.\nThe video cannot me moved."));
+ return;
+ }
+
_startdrag_video_offset=ARDOUR_UI::instance()->video_timeline->get_offset();
_max_backwards_drag = (
ARDOUR_UI::instance()->video_timeline->get_duration()
if (ARDOUR_UI::instance()->video_timeline->is_offset_locked()) {
return;
}
+ if (_stuck) {
+ show_verbose_cursor_text (_("One or more Audio Regions\nare both Locked and\nLocked to Video.\nThe video cannot me moved."));
+ return;
+ }
framecnt_t dt = adjusted_current_frame (event) - raw_grab_frame() + _pointer_frame_offset;
dt = ARDOUR_UI::instance()->video_timeline->quantify_frames_to_apv(_startdrag_video_offset+dt) - _startdrag_video_offset;
if (ARDOUR_UI::instance()->video_timeline->is_offset_locked()) {
return;
}
+ if (_stuck) {
+ return;
+ }
if (!movement_occurred || ! _editor->session()) {
return;
TrimDrag::TrimDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool preserve_fade_anchor)
: RegionDrag (e, i, p, v)
+ , _operation (StartTrim)
, _preserve_fade_anchor (preserve_fade_anchor)
, _jump_position_when_done (false)
- , _snap_delta (0)
{
DEBUG_TRACE (DEBUG::Drags, "New TrimDrag\n");
}
framecnt_t const region_length = (framecnt_t) (_primary->region()->length() / speed);
framepos_t const pf = adjusted_current_frame (event);
+ setup_snap_delta (region_start);
- if (_editor->snap_delta () == SnapRelative) {
- framepos_t temp = region_start;
- _editor->snap_to_with_modifier (temp, event, RoundUpMaybe);
- _snap_delta = temp - region_start;
- }
-
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
+ if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::trim_contents_modifier ())) {
/* Move the contents of the region around without changing the region bounds */
_operation = ContentsTrim;
Drag::start_grab (event, _editor->cursors()->trimmer);
if (pf < (region_start + region_length/2)) {
/* closer to front */
_operation = StartTrim;
-
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+ if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::trim_anchored_modifier ())) {
Drag::start_grab (event, _editor->cursors()->anchored_left_side_trim);
} else {
Drag::start_grab (event, _editor->cursors()->left_side_trim);
} else {
/* closer to end */
_operation = EndTrim;
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+ if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::trim_anchored_modifier ())) {
Drag::start_grab (event, _editor->cursors()->anchored_right_side_trim);
} else {
Drag::start_grab (event, _editor->cursors()->right_side_trim);
}
}
}
-
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+ /* jump trim disabled for now
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::trim_jump_modifier ())) {
_jump_position_when_done = true;
}
+ */
switch (_operation) {
case StartTrim:
show_verbose_cursor_time (region_start);
- for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
- i->view->trim_front_starting ();
- }
break;
case EndTrim:
show_verbose_cursor_duration (region_start, region_end);
if (tv && tv->is_track()) {
speed = tv->track()->speed();
}
- framecnt_t adj_frame = adjusted_frame (_drags->current_pointer_frame () + _snap_delta, event, true);
- framecnt_t dt = adj_frame - raw_grab_frame () + _pointer_frame_offset - _snap_delta;
+ framecnt_t adj_frame = adjusted_frame (_drags->current_pointer_frame () + snap_delta (event->button.state), event, true);
+ framecnt_t dt = adj_frame - raw_grab_frame () + _pointer_frame_offset - snap_delta (event->button.state);
if (first_move) {
rv->enable_display (false);
rv->region()->playlist()->clear_owned_changes ();
+ if (_operation == StartTrim) {
+ rv->trim_front_starting ();
+ }
+
AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (rv);
if (arv) {
bool non_overlap_trim = false;
- if (event && Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+ if (event && Keyboard::modifier_state_contains (event->button.state, ArdourKeyboard::trim_overlap_modifier ())) {
non_overlap_trim = true;
}
}
}
-
void
TrimDrag::finished (GdkEvent* event, bool movement_occurred)
{
} else {
/* no mouse movement */
- _editor->point_trim (event, adjusted_current_frame (event));
+ if (adjusted_current_frame (event) != adjusted_frame (_drags->current_pointer_frame(), event, false)) {
+ _editor->point_trim (event, adjusted_current_frame (event));
+ }
}
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- if (_operation == StartTrim) {
- i->view->trim_front_ending ();
- }
-
i->view->region()->resume_property_changes ();
}
}
MeterMarkerDrag::MeterMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
: Drag (e, i),
_copy (c)
+ , before_state (0)
{
DEBUG_TRACE (DEBUG::Drags, "New MeterMarkerDrag\n");
_marker = reinterpret_cast<MeterMarker*> (_item->get_data ("marker"));
assert (_marker);
+ _real_section = &_marker->meter();
+
}
void
// leave or lose the original marker (leave if its a copy; lose if its
// not, because we'll remove it from the map).
+ char name[64];
+ snprintf (name, sizeof(name), "%g/%g", _marker->meter().divisions_per_bar(), _marker->meter().note_divisor ());
+
MeterSection section (_marker->meter());
if (!section.movable()) {
return;
}
- char name[64];
- snprintf (name, sizeof(name), "%g/%g", _marker->meter().divisions_per_bar(), _marker->meter().note_divisor ());
-
_marker = new MeterMarker (
*_editor,
*_editor->meter_group,
- ARDOUR_UI::config()->color ("meter marker"),
+ UIConfiguration::instance().color ("meter marker"),
name,
*new MeterSection (_marker->meter())
);
swap_grab (&_marker->the_item(), 0, GDK_CURRENT_TIME);
if (!_copy) {
+ _editor->begin_reversible_command (_("move meter mark"));
TempoMap& map (_editor->session()->tempo_map());
/* get current state */
before_state = &map.get_state();
/* remove the section while we drag it */
- map.remove_meter (section, true);
+ //map.remove_meter (section, true);
}
+ _marker->hide();
}
framepos_t const pf = adjusted_current_frame (event);
_marker->set_position (pf);
+ _editor->session()->tempo_map().gui_move_meter (_real_section, _marker->meter(), pf);
+
show_verbose_cursor_time (pf);
}
Timecode::BBT_Time when;
TempoMap& map (_editor->session()->tempo_map());
- map.bbt_time (last_pointer_frame(), when);
+ map.bbt_time (_marker->position(), when);
if (_copy == true) {
_editor->begin_reversible_command (_("copy meter mark"));
XMLNode &before = map.get_state();
- map.add_meter (_marker->meter(), when);
+
+ if (_marker->meter().position_lock_style() == AudioTime) {
+ map.add_meter (_marker->meter(), _marker->position());
+ } else {
+ map.add_meter (_marker->meter(), map.bbt_to_beats (when), when);
+ }
+
XMLNode &after = map.get_state();
_editor->session()->add_command(new MementoCommand<TempoMap>(map, &before, &after));
_editor->commit_reversible_command ();
} else {
- _editor->begin_reversible_command (_("move meter mark"));
-
/* we removed it before, so add it back now */
+ if (_marker->meter().position_lock_style() == AudioTime) {
+ map.add_meter (_marker->meter(), _marker->position());
+ } else {
+ map.add_meter (_marker->meter(), map.beat_at_frame (_marker->position()), when);
+ }
- map.add_meter (_marker->meter(), when);
XMLNode &after = map.get_state();
_editor->session()->add_command(new MementoCommand<TempoMap>(map, before_state, &after));
_editor->commit_reversible_command ();
if (moved) {
TempoMap& map (_editor->session()->tempo_map());
/* we removed it before, so add it back now */
- map.add_meter (_marker->meter(), _marker->meter().frame());
+ map.add_meter (_marker->meter(), map.beat_at_frame (_marker->meter().frame()), _marker->meter().bbt());
// delete the dummy marker we used for visual representation while moving.
// a new visual marker will show up automatically.
delete _marker;
}
TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
- : Drag (e, i),
- _copy (c)
+ : Drag (e, i)
+ , _copy (c)
+ , before_state (0)
{
DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n");
_marker = reinterpret_cast<TempoMarker*> (_item->get_data ("marker"));
+ _real_section = &_marker->tempo();
assert (_marker);
}
_marker = new TempoMarker (
*_editor,
*_editor->tempo_group,
- ARDOUR_UI::config()->color ("tempo marker"),
+ UIConfiguration::instance().color ("tempo marker"),
name,
*new TempoSection (_marker->tempo())
);
swap_grab (&_marker->the_item(), 0, GDK_CURRENT_TIME);
if (!_copy) {
+ _editor->begin_reversible_command (_("move tempo mark"));
TempoMap& map (_editor->session()->tempo_map());
/* get current state */
before_state = &map.get_state();
- /* remove the section while we drag it */
- map.remove_tempo (section, true);
}
+ _marker->hide();
}
- framepos_t const pf = adjusted_current_frame (event);
+ framepos_t const pf = adjusted_current_frame (event, false);
+ Tempo const tp = _marker->tempo();
_marker->set_position (pf);
+ _editor->session()->tempo_map().gui_move_tempo (_real_section, tp, pf);
+
show_verbose_cursor_time (pf);
}
return;
}
- motion (event, false);
+ //motion (event, false);
TempoMap& map (_editor->session()->tempo_map());
- framepos_t beat_time = map.round_to_beat (last_pointer_frame(), RoundNearest);
- Timecode::BBT_Time when;
-
- map.bbt_time (beat_time, when);
if (_copy == true) {
_editor->begin_reversible_command (_("copy tempo mark"));
XMLNode &before = map.get_state();
- map.add_tempo (_marker->tempo(), when);
+
+ if (_marker->tempo().position_lock_style() == MusicTime) {
+ map.add_tempo (_marker->tempo(), _real_section->beat(), _marker->tempo().type());
+ } else {
+ map.add_tempo (_marker->tempo(), _real_section->frame(), _marker->tempo().type());
+ }
+
XMLNode &after = map.get_state();
_editor->session()->add_command (new MementoCommand<TempoMap>(map, &before, &after));
_editor->commit_reversible_command ();
} else {
- _editor->begin_reversible_command (_("move tempo mark"));
/* we removed it before, so add it back now */
- map.add_tempo (_marker->tempo(), when);
+ if (_marker->tempo().position_lock_style() == MusicTime) {
+ map.replace_tempo (*_real_section, _marker->tempo().beats_per_minute() , _real_section->beat(), _marker->tempo().type());
+ } else {
+ map.replace_tempo (*_real_section, _marker->tempo().beats_per_minute() , _real_section->frame(), _marker->tempo().type());
+ }
+
XMLNode &after = map.get_state();
_editor->session()->add_command (new MementoCommand<TempoMap>(map, before_state, &after));
_editor->commit_reversible_command ();
if (moved) {
TempoMap& map (_editor->session()->tempo_map());
/* we removed it before, so add it back now */
- map.add_tempo (_marker->tempo(), _marker->tempo().start());
+ if (_marker->tempo().position_lock_style() == MusicTime) {
+ map.add_tempo (_marker->tempo(), _marker->tempo().beat(), _marker->tempo().type());
+ } else {
+ map.add_tempo (_marker->tempo(), _marker->tempo().frame(), _marker->tempo().type());
+ }
// delete the dummy marker we used for visual representation while moving.
// a new visual marker will show up automatically.
delete _marker;
: Drag (e, &c.track_canvas_item(), false)
, _cursor (c)
, _stop (s)
- , _snap_delta (0)
+ , _grab_zoom (0.0)
{
DEBUG_TRACE (DEBUG::Drags, "New CursorDrag\n");
}
void
CursorDrag::fake_locate (framepos_t t)
{
+ if (_editor->session () == 0) {
+ return;
+ }
+
_editor->playhead_cursor->set_position (t);
Session* s = _editor->session ();
CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
{
Drag::start_grab (event, c);
-
- if (_editor->snap_delta () == SnapRelative) {
- framepos_t temp = _editor->playhead_cursor->current_frame ();
- _editor->snap_to_with_modifier (temp, event);
- _snap_delta = temp - _editor->playhead_cursor->current_frame ();
- }
+ setup_snap_delta (_editor->playhead_cursor->current_frame ());
_grab_zoom = _editor->samples_per_pixel;
- framepos_t where = _editor->canvas_event_sample (event) + _snap_delta;
+ framepos_t where = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (where, event);
}
}
- fake_locate (where - _snap_delta);
+ fake_locate (where - snap_delta (event->button.state));
}
void
CursorDrag::motion (GdkEvent* event, bool)
{
- framepos_t where = _editor->canvas_event_sample (event) + _snap_delta;
+ framepos_t where = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (where, event);
if (where != last_pointer_frame()) {
- fake_locate (where - _snap_delta);
+ fake_locate (where - snap_delta (event->button.state));
}
}
FadeInDrag::FadeInDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionDrag (e, i, p, v)
- , _snap_delta (0)
{
DEBUG_TRACE (DEBUG::Drags, "New FadeInDrag\n");
}
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> const r = arv->audio_region ();
-
- if (_editor->snap_delta () == SnapRelative) {
- framepos_t temp = r->position();
- _editor->snap_to_with_modifier (temp, event);
- _snap_delta = temp - r->position();
- }
+ setup_snap_delta (r->position ());
show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32);
}
{
framecnt_t fade_length;
- framepos_t pos = _editor->canvas_event_sample (event) + _snap_delta;
+ framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pos, event);
- pos -= _snap_delta;
+ pos -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
}
framecnt_t fade_length;
- framepos_t pos = _editor->canvas_event_sample (event) + _snap_delta;
+ framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pos, event);
- pos -= _snap_delta;
+ pos -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
fade_length = pos - region->position();
}
- _editor->begin_reversible_command (_("change fade in length"));
+ bool in_command = false;
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
tmp->audio_region()->set_fade_in_length (fade_length);
tmp->audio_region()->set_fade_in_active (true);
+ if (!in_command) {
+ _editor->begin_reversible_command (_("change fade in length"));
+ in_command = true;
+ }
XMLNode &after = alist->get_state();
_editor->session()->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
}
- _editor->commit_reversible_command ();
+ if (in_command) {
+ _editor->commit_reversible_command ();
+ }
}
void
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> r = arv->audio_region ();
-
- if (_editor->snap_delta () == SnapRelative) {
- framepos_t temp = r->last_frame ();
- _editor->snap_to_with_modifier (temp, event);
- _snap_delta = temp - r->last_frame();
- }
+ setup_snap_delta (r->last_frame ());
show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame());
}
{
framecnt_t fade_length;
- framepos_t pos = _editor->canvas_event_sample (event) + _snap_delta;
+ framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pos, event);
- pos -= _snap_delta;
+ pos -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
framecnt_t fade_length;
- framepos_t pos = _editor->canvas_event_sample (event) + _snap_delta;
+ framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pos, event);
- pos -= _snap_delta;
+ pos -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
fade_length = region->last_frame() - pos;
}
- _editor->begin_reversible_command (_("change fade out length"));
+ bool in_command = false;
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
tmp->audio_region()->set_fade_out_length (fade_length);
tmp->audio_region()->set_fade_out_active (true);
+ if (!in_command) {
+ _editor->begin_reversible_command (_("change fade out length"));
+ in_command = true;
+ }
XMLNode &after = alist->get_state();
_editor->session()->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
}
- _editor->commit_reversible_command ();
+ if (in_command) {
+ _editor->commit_reversible_command ();
+ }
}
void
MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
+ , _selection_changed (false)
{
DEBUG_TRACE (DEBUG::Drags, "New MarkerDrag\n");
+ Gtk::Window* toplevel = _editor->current_toplevel();
+ _marker = reinterpret_cast<ArdourMarker*> (_item->get_data ("marker"));
- _marker = reinterpret_cast<Marker*> (_item->get_data ("marker"));
assert (_marker);
_points.push_back (ArdourCanvas::Duple (0, 0));
- _points.push_back (ArdourCanvas::Duple (0, physical_screen_height (_editor->get_window())));
+
+ _points.push_back (ArdourCanvas::Duple (0, toplevel ? physical_screen_height (toplevel->get_window()) : 900));
}
MarkerDrag::~MarkerDrag ()
}
}
-MarkerDrag::CopiedLocationMarkerInfo::CopiedLocationMarkerInfo (Location* l, Marker* m)
+MarkerDrag::CopiedLocationMarkerInfo::CopiedLocationMarkerInfo (Location* l, ArdourMarker* m)
{
location = new Location (*l);
markers.push_back (m);
} else {
show_verbose_cursor_time (location->end());
}
+ setup_snap_delta (is_start ? location->start() : location->end());
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
case Selection::Set:
if (!_editor->selection->selected (_marker)) {
_editor->selection->set (_marker);
+ _selection_changed = true;
}
break;
case Selection::Extend:
{
Locations::LocationList ll;
- list<Marker*> to_add;
+ list<ArdourMarker*> to_add;
framepos_t s, e;
_editor->selection->markers.range (s, e);
s = min (_marker->position(), s);
}
if (!to_add.empty()) {
_editor->selection->add (to_add);
+ _selection_changed = true;
}
break;
}
case Selection::Add:
_editor->selection->add (_marker);
+ _selection_changed = true;
+
break;
}
bool move_both = false;
Location *real_location;
Location *copy_location = 0;
+ framecnt_t const sd = snap_delta (event->button.state);
- framepos_t const newframe = adjusted_current_frame (event);
+ framecnt_t const newframe = adjusted_frame (_drags->current_pointer_frame () + sd, event, true) - sd;
framepos_t next = newframe;
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
+ if (Keyboard::modifier_state_contains (event->button.state, ArdourKeyboard::push_points_modifier ())) {
move_both = true;
}
switch (_marker->type()) {
- case Marker::SessionStart:
- case Marker::RangeStart:
- case Marker::LoopStart:
- case Marker::PunchIn:
+ case ArdourMarker::SessionStart:
+ case ArdourMarker::RangeStart:
+ case ArdourMarker::LoopStart:
+ case ArdourMarker::PunchIn:
f_delta = newframe - copy_location->start();
break;
- case Marker::SessionEnd:
- case Marker::RangeEnd:
- case Marker::LoopEnd:
- case Marker::PunchOut:
+ case ArdourMarker::SessionEnd:
+ case ArdourMarker::RangeEnd:
+ case ArdourMarker::LoopEnd:
+ case ArdourMarker::PunchOut:
f_delta = newframe - copy_location->end();
break;
default:
if (move_both || (*x).move_both) {
copy_location->set_start (new_start);
copy_location->set_end (new_end);
- } else if (new_start < copy_location->end()) {
+ } else if (new_start < copy_location->end()) {
copy_location->set_start (new_start);
} else if (newframe > 0) {
- _editor->snap_to (next, RoundUpAlways, true);
+ //_editor->snap_to (next, RoundUpAlways, true);
copy_location->set_end (next);
copy_location->set_start (newframe);
}
} else if (new_end > copy_location->start()) {
copy_location->set_end (new_end);
} else if (newframe > 0) {
- _editor->snap_to (next, RoundDownAlways, true);
+ //_editor->snap_to (next, RoundDownAlways, true);
copy_location->set_start (next);
copy_location->set_end (newframe);
}
*/
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
-
switch (op) {
case Selection::Set:
if (_editor->selection->selected (_marker) && _editor->selection->markers.size() > 1) {
_editor->selection->set (_marker);
+ _selection_changed = true;
}
break;
case Selection::Toggle:
/* we toggle on the button release, click only */
_editor->selection->toggle (_marker);
+ _selection_changed = true;
+
break;
case Selection::Extend:
break;
}
+ if (_selection_changed) {
+ _editor->begin_reversible_selection_op(X_("Select Marker Release"));
+ _editor->commit_reversible_selection_op();
+ }
+
return;
}
_editor->_dragging_edit_point = false;
- _editor->begin_reversible_command ( _("move marker") );
XMLNode &before = _editor->session()->locations()->get_state();
+ bool in_command = false;
MarkerSelection::iterator i;
CopiedLocationInfo::iterator x;
if (location) {
if (location->locked()) {
- return;
+ continue;
+ }
+ if (!in_command) {
+ _editor->begin_reversible_command ( _("move marker") );
+ in_command = true;
}
-
if (location->is_mark()) {
location->set_start (((*x).location)->start());
} else {
}
}
- XMLNode &after = _editor->session()->locations()->get_state();
- _editor->session()->add_command(new MementoCommand<Locations>(*(_editor->session()->locations()), &before, &after));
- _editor->commit_reversible_command ();
+ if (in_command) {
+ XMLNode &after = _editor->session()->locations()->get_state();
+ _editor->session()->add_command(new MementoCommand<Locations>(*(_editor->session()->locations()), &before, &after));
+ _editor->commit_reversible_command ();
+ }
}
void
-MarkerDrag::aborted (bool movement_occured)
+MarkerDrag::aborted (bool movement_occurred)
{
- if (!movement_occured) {
+ if (!movement_occurred) {
return;
}
/* move all markers to their original location */
- for (vector<Marker*>::iterator m = x->markers.begin(); m != x->markers.end(); ++m) {
+ for (vector<ArdourMarker*>::iterator m = x->markers.begin(); m != x->markers.end(); ++m) {
bool is_start;
Location * location = _editor->find_location_from_marker (*m, is_start);
}
ControlPointDrag::ControlPointDrag (Editor* e, ArdourCanvas::Item* i)
- : Drag (e, i),
- _cumulative_x_drag (0),
- _cumulative_y_drag (0)
+ : Drag (e, i)
+ , _fixed_grab_x (0.0)
+ , _fixed_grab_y (0.0)
+ , _cumulative_x_drag (0.0)
+ , _cumulative_y_drag (0.0)
+ , _pushing (false)
+ , _final_index (0)
{
if (_zero_gain_fraction < 0.0) {
_zero_gain_fraction = gain_to_slider_position_with_max (dB_to_coefficient (0.0), Config->get_max_gain());
_fixed_grab_y = _point->get_y();
framepos_t pos = _editor->pixel_to_sample (_fixed_grab_x);
-
- if (_editor->snap_delta () == SnapRelative) {
- framepos_t temp = pos;
- if (!_x_constrained) {
- _editor->snap_to_with_modifier (temp, event);
- }
- _snap_delta = temp - pos;
- }
+ setup_snap_delta (pos);
float const fraction = 1 - (_point->get_y() / _point->line().height());
-
- _point->line().start_drag_single (_point, _fixed_grab_x, fraction);
-
show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction));
- _pushing = Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier);
+ _pushing = Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::push_points_modifier ());
if (!_point->can_slide ()) {
_x_constrained = true;
}
void
-ControlPointDrag::motion (GdkEvent* event, bool)
+ControlPointDrag::motion (GdkEvent* event, bool first_motion)
{
double dx = _drags->current_pointer_x() - last_pointer_x();
double dy = current_pointer_y() - last_pointer_y();
+ bool need_snap = true;
- if (event->button.state & Keyboard::SecondaryModifier) {
+ if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::fine_adjust_modifier ())) {
dx *= 0.1;
dy *= 0.1;
+ need_snap = false;
}
/* coordinate in pixels relative to the start of the region (for region-based automation)
// positive side of zero
double const zero_gain_y = (1.0 - _zero_gain_fraction) * _point->line().height() - .01;
- // make sure we hit zero when passing through
- if ((cy < zero_gain_y && (cy - dy) > zero_gain_y) || (cy > zero_gain_y && (cy - dy) < zero_gain_y)) {
- cy = zero_gain_y;
- }
-
if (_x_constrained) {
cx = _fixed_grab_x;
}
cy = max (0.0, cy);
cy = min ((double) _point->line().height(), cy);
- framepos_t cx_frames = _editor->pixel_to_sample (cx) + _snap_delta;
+ // make sure we hit zero when passing through
+ if ((cy < zero_gain_y && (cy - dy) > zero_gain_y) || (cy > zero_gain_y && (cy - dy) < zero_gain_y)) {
+ cy = zero_gain_y;
+ }
- if (!_x_constrained) {
+ framepos_t cx_frames = _editor->pixel_to_sample (cx) + snap_delta (event->button.state);
+
+ if (!_x_constrained && need_snap) {
_editor->snap_to_with_modifier (cx_frames, event);
}
- cx_frames -= _snap_delta;
+ cx_frames -= snap_delta (event->button.state);
cx_frames = min (cx_frames, _point->line().maximum_time());
float const fraction = 1.0 - (cy / _point->line().height());
- _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index);
+ if (first_motion) {
+ float const initial_fraction = 1.0 - (_fixed_grab_y / _point->line().height());
+ _editor->begin_reversible_command (_("automation event move"));
+ _point->line().start_drag_single (_point, _fixed_grab_x, initial_fraction);
+ }
+ pair<double, float> result;
+ result = _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index);
- show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction));
+ show_verbose_cursor_text (_point->line().get_verbose_cursor_string (result.second));
}
void
if (!movement_occurred) {
/* just a click */
-
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier))) {
_editor->reset_point_selection ();
}
} else {
- motion (event, false);
+ _point->line().end_drag (_pushing, _final_index);
+ _editor->commit_reversible_command ();
}
-
- _point->line().end_drag (_pushing, _final_index);
- _editor->commit_reversible_command ();
}
void
LineDrag::LineDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
, _line (0)
+ , _fixed_grab_x (0.0)
+ , _fixed_grab_y (0.0)
, _cumulative_y_drag (0)
+ , _before (0)
+ , _after (0)
{
DEBUG_TRACE (DEBUG::Drags, "New LineDrag\n");
}
origin, and ditto for y.
*/
- double cx = event->button.x;
- double cy = event->button.y;
-
- _line->parent_group().canvas_to_item (cx, cy);
+ double mx = event->button.x;
+ double my = event->button.y;
- framecnt_t const frame_within_region = (framecnt_t) floor (cx * _editor->samples_per_pixel);
+ _line->grab_item().canvas_to_item (mx, my);
- uint32_t before;
- uint32_t after;
+ framecnt_t const frame_within_region = (framecnt_t) floor (mx * _editor->samples_per_pixel);
- if (!_line->control_points_adjacent (frame_within_region, before, after)) {
+ if (!_line->control_points_adjacent (frame_within_region, _before, _after)) {
/* no adjacent points */
return;
}
Drag::start_grab (event, _editor->cursors()->fader);
- /* store grab start in parent frame */
+ /* store grab start in item frame */
+ double const bx = _line->nth (_before)->get_x();
+ double const ax = _line->nth (_after)->get_x();
+ double const click_ratio = (ax - mx) / (ax - bx);
+
+ double const cy = ((_line->nth (_before)->get_y() * click_ratio) + (_line->nth (_after)->get_y() * (1 - click_ratio)));
- _fixed_grab_x = cx;
+ _fixed_grab_x = mx;
_fixed_grab_y = cy;
double fraction = 1.0 - (cy / _line->height());
- _line->start_drag_line (before, after, fraction);
-
show_verbose_cursor_text (_line->get_verbose_cursor_string (fraction));
}
void
-LineDrag::motion (GdkEvent* event, bool)
+LineDrag::motion (GdkEvent* event, bool first_move)
{
double dy = current_pointer_y() - last_pointer_y();
- if (event->button.state & Keyboard::SecondaryModifier) {
+ if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::fine_adjust_modifier ())) {
dy *= 0.1;
}
double const fraction = 1.0 - (cy / _line->height());
uint32_t ignored;
+ if (first_move) {
+ float const initial_fraction = 1.0 - (_fixed_grab_y / _line->height());
+
+ _editor->begin_reversible_command (_("automation range move"));
+ _line->start_drag_line (_before, _after, initial_fraction);
+ }
+
/* we are ignoring x position for this drag, so we can just pass in anything */
- _line->drag_motion (0, fraction, true, false, ignored);
+ pair<double, float> result;
- show_verbose_cursor_text (_line->get_verbose_cursor_string (fraction));
+ result = _line->drag_motion (0, fraction, true, false, ignored);
+ show_verbose_cursor_text (_line->get_verbose_cursor_string (result.second));
}
void
-LineDrag::finished (GdkEvent* event, bool movement_occured)
+LineDrag::finished (GdkEvent* event, bool movement_occurred)
{
- if (movement_occured) {
+ if (movement_occurred) {
motion (event, false);
_line->end_drag (false, 0);
+ _editor->commit_reversible_command ();
} else {
/* add a new control point on the line */
AutomationTimeAxisView* atv;
- _line->end_drag (false, 0);
-
if ((atv = dynamic_cast<AutomationTimeAxisView*>(_editor->clicked_axisview)) != 0) {
- framepos_t where = _editor->window_event_sample (event, 0, 0);
- atv->add_automation_event (event, where, event->button.y, false);
+ framepos_t where = grab_frame ();
+
+ double cx = 0;
+ double cy = _fixed_grab_y;
+
+ _line->grab_item().item_to_canvas (cx, cy);
+
+ atv->add_automation_event (event, where, cy, false);
+ } else if (dynamic_cast<AudioTimeAxisView*>(_editor->clicked_axisview) != 0) {
+ AudioRegionView* arv;
+
+ if ((arv = dynamic_cast<AudioRegionView*>(_editor->clicked_regionview)) != 0) {
+ arv->add_gain_point_event (&arv->get_gain_line()->grab_item(), event, false);
+ }
}
}
-
- _editor->commit_reversible_command ();
}
void
FeatureLineDrag::FeatureLineDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i),
_line (0),
- _cumulative_x_drag (0)
+ _arv (0),
+ _region_view_grab_x (0.0),
+ _cumulative_x_drag (0),
+ _before (0.0),
+ _max_x (0)
{
DEBUG_TRACE (DEBUG::Drags, "New FeatureLineDrag\n");
}
RubberbandSelectDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
Drag::start_grab (event);
- show_verbose_cursor_time (adjusted_current_frame (event, ARDOUR_UI::config()->get_rubberbanding_snaps_to_grid()));
+ show_verbose_cursor_time (adjusted_current_frame (event, UIConfiguration::instance().get_rubberbanding_snaps_to_grid()));
}
void
double y1;
double y2;
- framepos_t const pf = adjusted_current_frame (event, ARDOUR_UI::config()->get_rubberbanding_snaps_to_grid());
+ framepos_t const pf = adjusted_current_frame (event, UIConfiguration::instance().get_rubberbanding_snaps_to_grid());
framepos_t grab = grab_frame ();
- if (ARDOUR_UI::config()->get_rubberbanding_snaps_to_grid ()) {
+ if (UIConfiguration::instance().get_rubberbanding_snaps_to_grid ()) {
_editor->snap_to_with_modifier (grab, event);
} else {
grab = raw_grab_frame ();
framepos_t grab = grab_frame ();
framepos_t lpf = last_pointer_frame ();
- if (!ARDOUR_UI::config()->get_rubberbanding_snaps_to_grid ()) {
+ if (!UIConfiguration::instance().get_rubberbanding_snaps_to_grid ()) {
grab = raw_grab_frame ();
lpf = _editor->pixel_to_sample_from_event (last_pointer_x());
}
/* MIDI track */
if (_editor->selection->empty() && _editor->mouse_mode == MouseDraw) {
/* nothing selected */
- add_midi_region (mtv);
+ add_midi_region (mtv, true);
do_deselect = false;
}
}
TimeFXDrag::TimeFXDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, std::list<RegionView*> const & v)
: RegionDrag (e, i, p, v)
- , _snap_delta (0)
{
DEBUG_TRACE (DEBUG::Drags, "New TimeFXDrag\n");
}
_editor->get_selection().add (_primary);
framepos_t where = _primary->region()->position();
- if (_editor->snap_delta () == SnapRelative) {
- framepos_t temp = where;
- _editor->snap_to_with_modifier (temp, event);
- _snap_delta = temp - where;
- }
+ setup_snap_delta (where);
show_verbose_cursor_duration (where, adjusted_current_frame (event), 0);
}
pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (grab_y());
int layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
int layers = tv.first->layer_display() == Overlaid ? 1 : cv->layers();
- framepos_t pf = _editor->canvas_event_sample (event) + _snap_delta;
+ framepos_t pf = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pf, event);
- pf -= _snap_delta;
+ pf -= snap_delta (event->button.state);
if (pf > rv->region()->position()) {
rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf, layers, layer);
}
void
-TimeFXDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
+TimeFXDrag::finished (GdkEvent* event, bool movement_occurred)
{
- _primary->get_time_axis_view().hide_timestretch ();
+ /* this may have been a single click, no drag. We still want the dialog
+ to show up in that case, so that the user can manually edit the
+ parameters for the timestretch.
+ */
- if (!movement_occurred) {
- return;
- }
+ float fraction = 1.0;
- if (last_pointer_frame() < _primary->region()->position()) {
- /* backwards drag of the left edge - not usable */
- return;
- }
+ if (movement_occurred) {
+
+ motion (event, false);
- framecnt_t newlen = last_pointer_frame() - _primary->region()->position();
+ _primary->get_time_axis_view().hide_timestretch ();
- float percentage = (double) newlen / (double) _primary->region()->length();
+ framepos_t adjusted_frame_pos = adjusted_current_frame (event);
+
+ if (adjusted_frame_pos < _primary->region()->position()) {
+ /* backwards drag of the left edge - not usable */
+ return;
+ }
+
+ framecnt_t newlen = adjusted_frame_pos - _primary->region()->position();
+
+ fraction = (double) newlen / (double) _primary->region()->length();
#ifndef USE_RUBBERBAND
- // Soundtouch uses percentage / 100 instead of normal (/ 1)
- if (_primary->region()->data_type() == DataType::AUDIO) {
- percentage = (float) ((double) newlen - (double) _primary->region()->length()) / ((double) newlen) * 100.0f;
- }
+ // Soundtouch uses fraction / 100 instead of normal (/ 1)
+ if (_primary->region()->data_type() == DataType::AUDIO) {
+ fraction = (float) ((double) newlen - (double) _primary->region()->length()) / ((double) newlen) * 100.0f;
+ }
#endif
+ }
if (!_editor->get_selection().regions.empty()) {
/* primary will already be included in the selection, and edit
selection.
*/
- if (_editor->time_stretch (_editor->get_selection().regions, percentage) == -1) {
+ if (_editor->time_stretch (_editor->get_selection().regions, fraction) == -1) {
error << _("An error occurred while executing time stretch operation") << endmsg;
}
}
case SelectionStartTrim:
- start = _editor->selection->time[_editor->clicked_selection].start;
end = _editor->selection->time[_editor->clicked_selection].end;
if (pending_position > end) {
case SelectionEndTrim:
start = _editor->selection->time[_editor->clicked_selection].start;
- end = _editor->selection->time[_editor->clicked_selection].end;
if (pending_position < start) {
end = start;
/* XXX what if its a music time selection? */
if (s) {
- if ( s->get_play_range() && s->transport_rolling() ) {
+ if (s->get_play_range() && s->transport_rolling()) {
s->request_play_range (&_editor->selection->time, true);
- } else {
- if (ARDOUR_UI::config()->get_follow_edits() && !s->transport_rolling()) {
+ } else if (!s->config.get_external_sync()) {
+ if (UIConfiguration::instance().get_follow_edits() && !s->transport_rolling()) {
if (_operation == SelectionEndTrim)
_editor->maybe_locate_with_edit_preroll( _editor->get_selection().time.end_frame());
else
s->request_locate (_editor->get_selection().time.start());
}
}
+
+ if (_editor->get_selection().time.length() != 0) {
+ s->set_range_selection (_editor->get_selection().time.start(), _editor->get_selection().time.end_frame());
+ } else {
+ s->clear_range_selection ();
+ }
}
} else {
_drag_rect = new ArdourCanvas::Rectangle (_editor->time_line_group,
ArdourCanvas::Rect (0.0, 0.0, 0.0,
- physical_screen_height (_editor->get_window())));
+ physical_screen_height (_editor->current_toplevel()->get_window())));
_drag_rect->hide ();
- _drag_rect->set_fill_color (ARDOUR_UI::config()->color ("range drag rect"));
- _drag_rect->set_outline_color (ARDOUR_UI::config()->color ("range drag rect"));
+ _drag_rect->set_fill_color (UIConfiguration::instance().color ("range drag rect"));
+ _drag_rect->set_outline_color (UIConfiguration::instance().color ("range drag rect"));
}
RangeMarkerBarDrag::~RangeMarkerBarDrag()
case CreateTransportMarker:
case CreateCDMarker:
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::CopyModifier)) {
_copy = true;
} else {
_copy = false;
}
void
-RangeMarkerBarDrag::aborted (bool movement_occured)
+RangeMarkerBarDrag::aborted (bool movement_occurred)
{
- if (movement_occured) {
+ if (movement_occurred) {
_drag_rect->hide ();
}
}
: Drag (e, i)
, _cumulative_dx (0)
, _cumulative_dy (0)
- , _snap_delta (0)
+ , _was_selected (false)
{
DEBUG_TRACE (DEBUG::Drags, "New NoteDrag\n");
NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
Drag::start_grab (event);
-
- if (_editor->snap_delta () == SnapRelative) {
- framepos_t where = _region->source_beats_to_absolute_frames (_primary->note()->time ());
- framepos_t temp = where;
- _editor->snap_to_with_modifier (temp, event);
- _snap_delta = temp - where;
- }
+ setup_snap_delta (_region->source_beats_to_absolute_frames (_primary->note()->time ()));
if (!(_was_selected = _primary->selected())) {
if (add) {
_region->note_selected (_primary, true);
} else {
+ _editor->get_selection().clear_points();
_region->unique_select (_primary);
}
-
- _editor->begin_reversible_selection_op(X_("Select Note Press"));
- _editor->commit_reversible_selection_op();
}
}
}
/** @return Current total drag x change in frames */
frameoffset_t
-NoteDrag::total_dx () const
+NoteDrag::total_dx (const guint state) const
{
/* dx in frames */
frameoffset_t const dx = _editor->pixel_to_sample (_drags->current_pointer_x() - grab_x());
frameoffset_t const n = _region->source_beats_to_absolute_frames (_primary->note()->time ());
/* new time of the primary note in session frames */
- frameoffset_t st = n + dx + _snap_delta;
+ frameoffset_t st = n + dx + snap_delta (state);
framepos_t const rp = _region->region()->position ();
/* prevent the note being dragged earlier than the region's position */
st = max (st, rp);
- /* snap and return corresponding delta */
- return _region->snap_frame_to_frame (st - rp) + rp - n - _snap_delta;
+ /* possibly snap and return corresponding delta */
+
+ bool snap = true;
+
+ if (ArdourKeyboard::indicates_snap (state)) {
+ if (_editor->snap_mode () != SnapOff) {
+ snap = false;
+ }
+ } else {
+ if (_editor->snap_mode () == SnapOff) {
+ snap = false;
+ /* inverted logic here - we;re in snapoff but we've pressed the snap delta modifier */
+ if (ArdourKeyboard::indicates_snap_delta (state)) {
+ snap = true;
+ }
+ }
+ }
+
+ frameoffset_t ret;
+ if (snap) {
+ bool const ensure_snap = _editor->snap_mode () != SnapMagnetic;
+ ret = _region->snap_frame_to_frame (st - rp, ensure_snap) + rp - n - snap_delta (state);
+ } else {
+ ret = st - n - snap_delta (state);
+ }
+ return ret;
}
/** @return Current total drag y change in note number */
}
void
-NoteDrag::motion (GdkEvent *, bool)
+NoteDrag::motion (GdkEvent * event, bool)
{
/* Total change in x and y since the start of the drag */
- frameoffset_t const dx = total_dx ();
+ frameoffset_t const dx = total_dx (event->button.state);
int8_t const dy = total_dy ();
/* Now work out what we have to do to the note canvas items to set this new drag delta */
* odd with them. so show the note value anyway, always.
*/
- char buf[12];
uint8_t new_note = min (max (_primary->note()->note() + note_delta, 0), 127);
- snprintf (buf, sizeof (buf), "%s (%d)", Evoral::midi_note_name (new_note).c_str(),
- (int) floor ((double)new_note));
-
- show_verbose_cursor_text (buf);
+ _region->show_verbose_cursor_for_new_note_value (_primary->note(), new_note);
}
}
if (!moved) {
/* no motion - select note */
- if (_editor->current_mouse_mode() == Editing::MouseObject ||
+ if (_editor->current_mouse_mode() == Editing::MouseContent ||
_editor->current_mouse_mode() == Editing::MouseDraw) {
bool changed = false;
if (add) {
_region->note_deselected (_primary);
changed = true;
+ } else {
+ _editor->get_selection().clear_points();
+ _region->unique_select (_primary);
+ changed = true;
}
} else {
bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
if (!extend && !add && _region->selection_size() > 1) {
+ _editor->get_selection().clear_points();
_region->unique_select (_primary);
changed = true;
} else if (extend) {
changed = true;
} else {
/* it was added during button press */
+ changed = true;
+
}
}
}
}
} else {
- _region->note_dropped (_primary, total_dx(), total_dy());
+ _region->note_dropped (_primary, total_dx (ev->button.state), total_dy());
}
}
}
}
- } else {
+ }
+
+ if (_nothing_to_drag) {
+ return;
+ }
+}
+
+void
+AutomationRangeDrag::motion (GdkEvent*, bool first_move)
+{
+ if (_nothing_to_drag && !first_move) {
+ return;
+ }
+
+ if (first_move) {
+ _editor->begin_reversible_command (_("automation range move"));
- for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
+ if (!_ranges.empty()) {
- framecnt_t const half = (i->start + i->end) / 2;
+ for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
- /* find the line that this audio range starts in */
- list<Line>::iterator j = _lines.begin();
- while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
- ++j;
- }
+ framecnt_t const half = (i->start + i->end) / 2;
+
+ /* find the line that this audio range starts in */
+ list<Line>::iterator j = _lines.begin();
+ while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
+ ++j;
+ }
- if (j != _lines.end()) {
- boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
+ if (j != _lines.end()) {
+ boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
/* j is the line that this audio range starts in; fade into it;
64 samples length plucked out of thin air.
*/
- framepos_t a = i->start + 64;
- if (a > half) {
- a = half;
- }
+ framepos_t a = i->start + 64;
+ if (a > half) {
+ a = half;
+ }
- double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ());
- double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ());
+ double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ());
+ double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ());
- the_list->editor_add (p, value (the_list, p));
- the_list->editor_add (q, value (the_list, q));
- }
+ XMLNode &before = the_list->get_state();
+ bool const add_p = the_list->editor_add (p, value (the_list, p), false);
+ bool const add_q = the_list->editor_add (q, value (the_list, q), false);
+
+ if (add_p || add_q) {
+ _editor->session()->add_command (
+ new MementoCommand<AutomationList>(*the_list.get (), &before, &the_list->get_state()));
+ }
+ }
- /* same thing for the end */
+ /* same thing for the end */
- j = _lines.begin();
- while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
- ++j;
- }
+ j = _lines.begin();
+ while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
+ ++j;
+ }
- if (j != _lines.end()) {
- boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
+ if (j != _lines.end()) {
+ boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
- /* j is the line that this audio range starts in; fade out of it;
- 64 samples length plucked out of thin air.
- */
+ /* j is the line that this audio range starts in; fade out of it;
+ 64 samples length plucked out of thin air.
+ */
- framepos_t b = i->end - 64;
- if (b < half) {
- b = half;
- }
+ framepos_t b = i->end - 64;
+ if (b < half) {
+ b = half;
+ }
+
+ double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ());
+ double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ());
- double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ());
- double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ());
+ XMLNode &before = the_list->get_state();
+ bool const add_p = the_list->editor_add (p, value (the_list, p), false);
+ bool const add_q = the_list->editor_add (q, value (the_list, q), false);
- the_list->editor_add (p, value (the_list, p));
- the_list->editor_add (q, value (the_list, q));
+ if (add_p || add_q) {
+ _editor->session()->add_command (
+ new MementoCommand<AutomationList>(*the_list.get (), &before, &the_list->get_state()));
+ }
+ }
}
- }
- _nothing_to_drag = true;
+ _nothing_to_drag = true;
- /* Find all the points that should be dragged and put them in the relevant
- points lists in the Line structs.
- */
+ /* Find all the points that should be dragged and put them in the relevant
+ points lists in the Line structs.
+ */
- for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
+ for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
- uint32_t const N = i->line->npoints ();
- for (uint32_t j = 0; j < N; ++j) {
+ uint32_t const N = i->line->npoints ();
+ for (uint32_t j = 0; j < N; ++j) {
- /* here's a control point on this line */
- ControlPoint* p = i->line->nth (j);
- double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b ();
+ /* here's a control point on this line */
+ ControlPoint* p = i->line->nth (j);
+ double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b ();
- /* see if it's inside a range */
- list<AudioRange>::const_iterator k = _ranges.begin ();
- while (k != _ranges.end() && (k->start >= w || k->end <= w)) {
- ++k;
- }
+ /* see if it's inside a range */
+ list<AudioRange>::const_iterator k = _ranges.begin ();
+ while (k != _ranges.end() && (k->start >= w || k->end <= w)) {
+ ++k;
+ }
- if (k != _ranges.end()) {
- /* dragging this point */
- _nothing_to_drag = false;
- i->points.push_back (p);
+ if (k != _ranges.end()) {
+ /* dragging this point */
+ _nothing_to_drag = false;
+ i->points.push_back (p);
+ }
}
}
}
- }
-
- if (_nothing_to_drag) {
- return;
- }
-
- for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
- i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state);
- }
-}
-void
-AutomationRangeDrag::motion (GdkEvent*, bool /*first_move*/)
-{
- if (_nothing_to_drag) {
- return;
+ for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
+ i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state);
+ }
}
for (list<Line>::iterator l = _lines.begin(); l != _lines.end(); ++l) {
float const f = y_fraction (l->line, current_pointer_y());
/* we are ignoring x position for this drag, so we can just pass in anything */
+ pair<double, float> result;
uint32_t ignored;
- l->line->drag_motion (0, f, true, false, ignored);
- show_verbose_cursor_text (l->line->get_verbose_cursor_relative_string (l->original_fraction, f));
+ result = l->line->drag_motion (0, f, true, false, ignored);
+ show_verbose_cursor_text (l->line->get_verbose_cursor_relative_string (l->original_fraction, result.second));
}
}
void
-AutomationRangeDrag::finished (GdkEvent* event, bool)
+AutomationRangeDrag::finished (GdkEvent* event, bool motion_occurred)
{
- if (_nothing_to_drag) {
+ if (_nothing_to_drag || !motion_occurred) {
return;
}
, line (new EditorCursor (*e))
{
line->set_position (pos);
- line->how ();
+ line->show ();
}
RegionCutDrag::~RegionCutDrag ()