*/
+#define __STDC_LIMIT_MACROS 1
+#include <stdint.h>
#include "pbd/memento_command.h"
#include "pbd/basename.h"
+#include "pbd/stateful_diff_command.h"
#include "ardour/diskstream.h"
#include "ardour/session.h"
#include "ardour/dB.h"
#include "audio_region_view.h"
#include "midi_region_view.h"
#include "ardour_ui.h"
+#include "gui_thread.h"
#include "control_point.h"
#include "utils.h"
#include "region_gain_line.h"
#include "canvas-note.h"
#include "selection.h"
#include "midi_selection.h"
+#include "automation_time_axis.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
-using namespace sigc;
using namespace Gtk;
using namespace Editing;
using namespace ArdourCanvas;
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 ();
+}
+
Drag::Drag (Editor* e, ArdourCanvas::Item* i)
: _editor (e)
, _item (i)
, _pointer_frame_offset (0)
+ , _move_threshold_passed (false)
, _grab_frame (0)
, _last_pointer_frame (0)
- , _current_pointer_frame (0)
- , _have_transaction (false)
- , _had_movement (false)
- , _move_threshold_passed (false)
{
}
}
_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;
-
- _original_x = 0;
- _original_y = 0;
- _item->i2w (_original_x, _original_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,
event->button.time);
- if (_editor->session && _editor->session->transport_rolling()) {
+ if (_editor->session() && _editor->session()->transport_rolling()) {
_was_rolling = true;
} else {
_was_rolling = false;
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, _had_movement);
+ finished (event, _move_threshold_passed);
_editor->hide_verbose_canvas_cursor();
- _ending = false;
-
- return _had_movement;
+ return _move_threshold_passed;
}
nframes64_t
-Drag::adjusted_current_frame (GdkEvent* event) const
+Drag::adjusted_frame (nframes64_t f, GdkEvent const * event, bool snap) const
{
nframes64_t pos = 0;
- if (_current_pointer_frame > _pointer_frame_offset) {
- pos = _current_pointer_frame - _pointer_frame_offset;
+ if (f > _pointer_frame_offset) {
+ pos = f - _pointer_frame_offset;
}
- _editor->snap_to_with_modifier (pos, event);
+ if (snap) {
+ _editor->snap_to_with_modifier (pos, event);
+ }
return pos;
}
+nframes64_t
+Drag::adjusted_current_frame (GdkEvent const * event, bool snap) const
+{
+ return adjusted_frame (_drags->current_pointer_frame (), event, snap);
+}
+
bool
Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
{
- _last_pointer_x = _current_pointer_x;
- _last_pointer_y = _current_pointer_y;
- _current_pointer_frame = _editor->event_frame (event, &_current_pointer_x, &_current_pointer_y);
-
- if (!from_autoscroll && !_move_threshold_passed) {
+ /* 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 == _drags->current_pointer_y ()) ) {
+ return false;
+ }
- bool const xp = (::llabs ((nframes64_t) (_current_pointer_x - _grab_x)) > 4LL);
- bool const yp = (::llabs ((nframes64_t) (_current_pointer_y - _grab_y)) > 4LL);
+ pair<nframes64_t, int> const threshold = move_threshold ();
- _move_threshold_passed = (xp || yp);
- }
+ bool const old_move_threshold_passed = _move_threshold_passed;
- bool old_had_movement = _had_movement;
+ if (!from_autoscroll && !_move_threshold_passed) {
- /* a motion event has happened, so we've had movement... */
- _had_movement = true;
+ bool const xp = (::llabs (adjusted_current_frame (event) - _grab_frame) >= threshold.first);
+ bool const yp = (::fabs ((_drags->current_pointer_y () - _grab_y)) >= threshold.second);
- /* ... unless we're using a move threshold and we've not yet passed it */
- if (apply_move_threshold() && !_move_threshold_passed) {
- _had_movement = false;
+ _move_threshold_passed = ((xp && x_movement_matters()) || (yp && y_movement_matters()));
}
- if (active (_editor->mouse_mode) && _had_movement) {
+ if (active (_editor->mouse_mode) && _move_threshold_passed) {
if (event->motion.state & Gdk::BUTTON1_MASK || event->motion.state & Gdk::BUTTON2_MASK) {
if (!from_autoscroll) {
_editor->maybe_autoscroll (&event->motion, allow_vertical_autoscroll ());
}
- motion (event, _had_movement != old_had_movement);
+ motion (event, _move_threshold_passed != old_move_threshold_passed);
+
+ _last_pointer_x = _drags->current_pointer_x ();
+ _last_pointer_y = _drags->current_pointer_y ();
+ _last_pointer_frame = adjusted_current_frame (event);
+
return true;
}
}
return false;
}
-
void
Drag::break_drag ()
{
- _editor->stop_canvas_autoscroll ();
- _editor->hide_verbose_canvas_cursor ();
-
if (_item) {
_item->ungrab (0);
+ }
- /* put it back where it came from */
+ aborted ();
- double cxw, cyw;
- cxw = 0;
- cyw = 0;
- _item->i2w (cxw, cyw);
- _item->move (_original_x - cxw, _original_y - cyw);
- }
+ _editor->stop_canvas_autoscroll ();
+ _editor->hide_verbose_canvas_cursor ();
}
-
RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: Drag (e, i),
_primary (p),
_views (v)
{
- RegionView::RegionViewGoingAway.connect (sigc::mem_fun (*this, &RegionDrag::region_going_away));
+ RegionView::RegionViewGoingAway.connect (death_connection, ui_bind (&RegionDrag::region_going_away, this, _1), gui_context());
}
void
: RegionDrag (e, i, p, v),
_dest_trackview (0),
_dest_layer (0),
- _brushing (b)
+ _brushing (b),
+ _total_x_delta (0)
{
}
/* get a bitmask representing the visible tracks */
- for (Editor::TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
+ for (TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
TimeAxisView::Children children_list;
double
RegionMotionDrag::compute_x_delta (GdkEvent const * event, nframes64_t* pending_region_position)
{
- *pending_region_position = 0;
-
/* compute the amount of pointer motion in frames, and where
the region would be if we moved it by that much.
*/
- if (_current_pointer_frame >= _pointer_frame_offset) {
-
- nframes64_t sync_frame;
- nframes64_t sync_offset;
- int32_t sync_dir;
-
- *pending_region_position = _current_pointer_frame - _pointer_frame_offset;
-
- sync_offset = _primary->region()->sync_offset (sync_dir);
-
- /* we don't handle a sync point that lies before zero.
- */
- if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
-
- sync_frame = *pending_region_position + (sync_dir*sync_offset);
-
- _editor->snap_to_with_modifier (sync_frame, event);
-
- *pending_region_position = _primary->region()->adjust_to_sync (sync_frame);
-
- } else {
- *pending_region_position = _last_frame_position;
- }
-
+ *pending_region_position = adjusted_current_frame (event);
+
+ nframes64_t sync_frame;
+ nframes64_t sync_offset;
+ int32_t sync_dir;
+
+ sync_offset = _primary->region()->sync_offset (sync_dir);
+
+ /* we don't handle a sync point that lies before zero.
+ */
+ if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
+
+ sync_frame = *pending_region_position + (sync_dir*sync_offset);
+
+ _editor->snap_to_with_modifier (sync_frame, event);
+
+ *pending_region_position = _primary->region()->adjust_to_sync (sync_frame);
+
+ } else {
+ *pending_region_position = _last_frame_position;
}
if (*pending_region_position > max_frames - _primary->region()->length()) {
} /* foreach region */
+ _total_x_delta += x_delta;
+
if (first_move) {
_editor->cursor_group->raise_to_top();
}
vector<RegionView*> copies;
boost::shared_ptr<Diskstream> ds;
boost::shared_ptr<Playlist> from_playlist;
+ boost::shared_ptr<Playlist> to_playlist;
RegionSelection new_views;
typedef set<boost::shared_ptr<Playlist> > PlaylistSet;
PlaylistSet modified_playlists;
bool changed_tracks, changed_position;
map<RegionView*, pair<RouteTimeAxisView*, int> > final;
RouteTimeAxisView* source_tv;
+ vector<StatefulDiffCommand*> sdc;
if (!movement_occurred) {
/* just a click */
}
}
- _have_transaction = true;
-
changed_position = (_last_frame_position != (nframes64_t) (_primary->region()->position()));
changed_tracks = (_dest_trackview != &_primary->get_time_axis_view());
/* make a list of where each region ended up */
final = find_time_axis_views_and_layers ();
+ cerr << "Iterate over " << _views.size() << " views\n";
+
for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ) {
RegionView* rv = (*i);
nframes64_t where;
+ from_playlist.reset ();
+ to_playlist.reset ();
+
if (rv->region()->locked()) {
++i;
continue;
if (changed_tracks || _copy) {
- boost::shared_ptr<Playlist> to_playlist = dest_rtv->playlist();
+ to_playlist = dest_rtv->playlist();
if (!to_playlist) {
++i;
insert_result = modified_playlists.insert (to_playlist);
if (insert_result.second) {
- _editor->session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
+ to_playlist->clear_history ();
}
+ cerr << "To playlist " << to_playlist->name() << " region history contains "
+ << to_playlist->region_list().change().added.size() << " adds and "
+ << to_playlist->region_list().change().removed.size() << " removes\n";
+
+ cerr << "Adding new region " << new_region->id() << " based on "
+ << rv->region()->id() << endl;
+
to_playlist->add_region (new_region, where);
+
if (dest_rtv->view()->layer_display() == Stacked) {
new_region->set_layer (dest_layer);
new_region->set_pending_explicit_relayer (true);
}
} else {
+ rv->region()->clear_history ();
+
/*
motion on the same track. plonk the previously reparented region
back to its original canvas group (its streamview).
rv->get_canvas_group()->reparent (*dest_rtv->view()->canvas_item());
rv->get_canvas_group()->property_y() = 0;
+ rv->get_time_axis_view().reveal_dependent_views (*rv);
/* just change the model */
boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
-
+
if (dest_rtv->view()->layer_display() == Stacked) {
rv->region()->set_layer (dest_layer);
rv->region()->set_pending_explicit_relayer (true);
}
+
+ /* freeze playlist to avoid lots of relayering in the case of a multi-region drag */
- insert_result = modified_playlists.insert (playlist);
-
- if (insert_result.second) {
- _editor->session->add_command (new MementoCommand<Playlist>(*playlist, &playlist->get_state(), 0));
- }
- /* freeze to avoid lots of relayering in the case of a multi-region drag */
frozen_insert_result = frozen_playlists.insert(playlist);
if (frozen_insert_result.second) {
playlist->freeze();
}
+ cerr << "Moving region " << rv->region()->id() << endl;
+
rv->region()->set_position (where, (void*) this);
+
+ sdc.push_back (new StatefulDiffCommand (rv->region()));
}
if (changed_tracks && !_copy) {
insert_result = modified_playlists.insert (from_playlist);
if (insert_result.second) {
- _editor->session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
+ from_playlist->clear_history ();
}
+
+ cerr << "From playlist " << from_playlist->name() << " region history contains "
+ << from_playlist->region_list().change().added.size() << " adds and "
+ << from_playlist->region_list().change().removed.size() << " removes\n";
+ cerr << "removing region " << rv->region() << endl;
+
from_playlist->remove_region (rv->region());
/* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
*/
if (_views.empty()) {
- break;
+ if (to_playlist) {
+ sdc.push_back (new StatefulDiffCommand (to_playlist));
+ cerr << "Saved diff for to:" << to_playlist->name() << endl;
+ }
+
+ if (from_playlist && (from_playlist != to_playlist)) {
+ sdc.push_back (new StatefulDiffCommand (from_playlist));
+ cerr << "Saved diff for from:" << from_playlist->name() << endl;
+ }
+ break;
} else {
i = _views.begin();
}
if (_copy) {
copies.push_back (rv);
}
+
+ cerr << "Done with TV, top = " << to_playlist << " from = " << from_playlist << endl;
+
+ if (to_playlist) {
+ sdc.push_back (new StatefulDiffCommand (to_playlist));
+ cerr << "Saved diff for to:" << to_playlist->name() << endl;
+ }
+
+ if (from_playlist && (from_playlist != to_playlist)) {
+ sdc.push_back (new StatefulDiffCommand (from_playlist));
+ cerr << "Saved diff for from:" << from_playlist->name() << endl;
+ }
}
+
/*
if we've created new regions either by copying or moving
to a new track, we want to replace the old selection with the new ones
*/
+
if (new_views.size() > 0) {
_editor->selection->set (new_views);
}
}
out:
- for (set<boost::shared_ptr<Playlist> >::iterator p = modified_playlists.begin(); p != modified_playlists.end(); ++p) {
- _editor->session->add_command (new MementoCommand<Playlist>(*(*p), 0, &(*p)->get_state()));
- }
+ for (vector<StatefulDiffCommand*>::iterator i = sdc.begin(); i != sdc.end(); ++i) {
+ _editor->session()->add_command (*i);
+ }
_editor->commit_reversible_command ();
}
}
+void
+RegionMoveDrag::aborted ()
+{
+ if (_copy) {
+
+ for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ delete *i;
+ }
+
+ _views.clear ();
+
+ } else {
+ RegionMotionDrag::aborted ();
+ }
+}
+
+void
+RegionMotionDrag::aborted ()
+{
+ for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ TimeAxisView* tv = &(*i)->get_time_axis_view ();
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
+ assert (rtv);
+ (*i)->get_canvas_group()->reparent (*rtv->view()->canvas_item());
+ (*i)->get_canvas_group()->property_y() = 0;
+ (*i)->get_time_axis_view().reveal_dependent_views (**i);
+ (*i)->fake_set_opaque (false);
+ (*i)->move (-_total_x_delta, 0);
+ (*i)->set_height (rtv->view()->child_height ());
+ }
+
+ _editor->update_canvas_now ();
+}
+
bool
RegionMotionDrag::x_move_allowed () const
const boost::shared_ptr<const Region> original = rv->region();
boost::shared_ptr<Region> region_copy = RegionFactory::create (original);
+ region_copy->set_position (original->position(), this);
RegionView* nrv;
if (arv) {
boost::shared_ptr<AudioRegion> audioregion_copy
= boost::dynamic_pointer_cast<AudioRegion>(region_copy);
+
nrv = new AudioRegionView (*arv, audioregion_copy);
} else if (mrv) {
boost::shared_ptr<MidiRegion> midiregion_copy
without it, the canvas seems to
"forget" to update properly after the upcoming reparent()
..only if the mouse is in rapid motion at the time of the grab.
- something to do with regionview creation raking so long?
+ something to do with regionview creation taking so long?
*/
_editor->update_canvas_now();
}
{
/* 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;
{
RegionMotionDrag::start_grab (event, c);
- _pointer_frame_offset = _grab_frame - _last_frame_position;
+ _pointer_frame_offset = grab_frame() - _last_frame_position;
}
RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr<Region> r, RouteTimeAxisView* v, nframes64_t pos)
boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
_editor->begin_reversible_command (_("insert region"));
- XMLNode& before = playlist->get_state ();
+ playlist->clear_history ();
playlist->add_region (_primary->region (), _last_frame_position);
- _editor->session->add_command (new MementoCommand<Playlist> (*playlist, &before, &playlist->get_state()));
+ _editor->session()->add_command (new StatefulDiffCommand (playlist));
_editor->commit_reversible_command ();
delete _primary;
_views.clear ();
}
+void
+RegionInsertDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
RegionSpliceDrag::RegionSpliceDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionMoveDrag (e, i, p, v, false, false)
{
};
void
-RegionSpliceDrag::motion (GdkEvent* /*event*/, bool)
+RegionSpliceDrag::motion (GdkEvent* event, bool)
{
RouteTimeAxisView* tv;
layer_t layer;
int dir;
- if (_current_pointer_x - _grab_x > 0) {
+ if ((_drags->current_pointer_x() - last_pointer_x()) > 0) {
dir = 1;
} else {
dir = -1;
RegionSelectionByPosition cmp;
copy.sort (cmp);
+ nframes64_t const pf = adjusted_current_frame (event);
+
for (RegionSelection::iterator i = copy.begin(); i != copy.end(); ++i) {
RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*> (&(*i)->get_time_axis_view());
}
if (dir > 0) {
- if (_current_pointer_frame < (*i)->region()->last_frame() + 1) {
+ if (pf < (*i)->region()->last_frame() + 1) {
continue;
}
} else {
- if (_current_pointer_frame > (*i)->region()->first_frame()) {
+ if (pf > (*i)->region()->first_frame()) {
continue;
}
}
playlist->shuffle ((*i)->region(), dir);
-
- _grab_x = _current_pointer_x;
}
}
}
+void
+RegionSpliceDrag::aborted ()
+{
+ /* XXX: TODO */
+}
RegionCreateDrag::RegionCreateDrag (Editor* e, ArdourCanvas::Item* i, TimeAxisView* v)
: Drag (e, i),
}
if (!movement_occurred) {
- mtv->add_region (_grab_frame);
+ mtv->add_region (grab_frame ());
} else {
motion (event, false);
// TODO: create region-create-drag region here
}
}
+void
+RegionCreateDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
, region (0)
double region_start = region->get_position_pixels();
double middle_point = region_start + cnote->x1() + (cnote->x2() - cnote->x1()) / 2.0L;
- if (_grab_x <= middle_point) {
+ if (grab_x() <= middle_point) {
cursor = Gdk::Cursor(Gdk::LEFT_SIDE);
at_front = true;
} else {
{
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);
}
}
{
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);
}
}
+void
+NoteResizeDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
void
RegionGainDrag::motion (GdkEvent* /*event*/, bool)
{
}
+void
+RegionGainDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
TrimDrag::TrimDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionDrag (e, i, p, v)
+ , _have_transaction (false)
{
}
Drag::start_grab (event, _editor->trimmer_cursor);
+ nframes64_t const pf = adjusted_current_frame (event);
+
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_operation = ContentsTrim;
} else {
/* These will get overridden for a point trim.*/
- if (_current_pointer_frame < (region_start + region_length/2)) {
+ if (pf < (region_start + region_length/2)) {
/* closer to start */
_operation = StartTrim;
- } else if (_current_pointer_frame > (region_end - region_length/2)) {
+ } else if (pf > (region_end - region_length/2)) {
/* closer to end */
_operation = EndTrim;
}
_editor->show_verbose_time_cursor (region_end, 10);
break;
case ContentsTrim:
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (pf, 10);
break;
}
}
nframes64_t frame_delta = 0;
bool left_direction;
- bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier());
+ bool obey_snap = event ? !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) : false;
/* snap modifier works differently here..
- its' current state has to be passed to the
+ its current state has to be passed to the
various trim functions in order to work properly
*/
speed = tv->get_diskstream()->speed();
}
- if (_last_pointer_frame > _current_pointer_frame) {
+ nframes64_t const pf = adjusted_current_frame (event);
+
+ if (last_pointer_frame() > pf) {
left_direction = true;
} else {
left_direction = false;
}
- _editor->snap_to_with_modifier (_current_pointer_frame, event);
-
if (first_move) {
string trim_type;
for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
(*i)->fake_set_opaque(false);
- (*i)->region()->freeze ();
+ (*i)->region()->clear_history ();
+ (*i)->region()->suspend_property_changes ();
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
insert_result = _editor->motion_frozen_playlists.insert (pl);
if (insert_result.second) {
- _editor->session->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
pl->freeze();
}
}
}
- if (_current_pointer_frame == _last_pointer_frame) {
- return;
- }
-
- /* XXX i hope to god that we can really conclude this ... */
- _have_transaction = true;
-
if (left_direction) {
- frame_delta = (_last_pointer_frame - _current_pointer_frame);
+ frame_delta = (last_pointer_frame() - pf);
} else {
- frame_delta = (_current_pointer_frame - _last_pointer_frame);
+ frame_delta = (pf - last_pointer_frame());
}
bool non_overlap_trim = false;
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+ if (event && Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
non_overlap_trim = true;
}
switch (_operation) {
case StartTrim:
- if ((left_direction == false) && (_current_pointer_frame <= rv->region()->first_frame()/speed)) {
+ if ((left_direction == false) && (pf <= rv->region()->first_frame()/speed)) {
break;
} else {
}
case EndTrim:
- if ((left_direction == true) && (_current_pointer_frame > (nframes64_t) (rv->region()->last_frame()/speed))) {
+ if ((left_direction == true) && (pf > (nframes64_t) (rv->region()->last_frame()/speed))) {
break;
} else {
{
bool swap_direction = false;
- if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
+ if (event && Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
swap_direction = true;
}
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i)
- {
+ for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
_editor->single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap);
}
}
_editor->show_verbose_time_cursor((nframes64_t) (rv->region()->last_frame()/speed), 10);
break;
case ContentsTrim:
- _editor->show_verbose_time_cursor(_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (pf, 10);
break;
}
-
- _last_pointer_frame = _current_pointer_frame;
}
for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
_editor->thaw_region_after_trim (**i);
(*i)->fake_set_opaque (true);
+ if (_have_transaction) {
+ _editor->session()->add_command (new StatefulDiffCommand ((*i)->region()));
+ }
}
}
for (set<boost::shared_ptr<Playlist> >::iterator p = _editor->motion_frozen_playlists.begin(); p != _editor->motion_frozen_playlists.end(); ++p) {
(*p)->thaw ();
- if (_have_transaction) {
- _editor->session->add_command (new MementoCommand<Playlist>(*(*p).get(), 0, &(*p)->get_state()));
- }
}
_editor->motion_frozen_playlists.clear ();
} else {
/* no mouse movement */
- _editor->point_trim (event);
+ _editor->point_trim (event, adjusted_current_frame (event));
+ }
+}
+
+void
+TrimDrag::aborted ()
+{
+ /* Our motion method is changing model state, so use the Undo system
+ to cancel. Perhaps not ideal, as this will leave an Undo point
+ behind which may be slightly odd from the user's point of view.
+ */
+
+ finished (0, true);
+
+ if (_have_transaction) {
+ _editor->undo ();
}
}
Drag::start_grab (event, cursor);
- _pointer_frame_offset = _grab_frame - _marker->meter().frame();
+ _pointer_frame_offset = grab_frame() - _marker->meter().frame();
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (adjusted_current_frame(event), 10);
}
void
MeterMarkerDrag::motion (GdkEvent* event, bool)
{
- nframes64_t const adjusted_frame = adjusted_current_frame (event);
-
- if (adjusted_frame == _last_pointer_frame) {
- return;
- }
-
- _marker->set_position (adjusted_frame);
-
- _last_pointer_frame = adjusted_frame;
+ nframes64_t const pf = adjusted_current_frame (event);
- _editor->show_verbose_time_cursor (adjusted_frame, 10);
+ _marker->set_position (pf);
+
+ _editor->show_verbose_time_cursor (pf, 10);
}
void
BBT_Time when;
- TempoMap& map (_editor->session->tempo_map());
- map.bbt_time (_last_pointer_frame, when);
+ TempoMap& map (_editor->session()->tempo_map());
+ map.bbt_time (last_pointer_frame(), when);
if (_copy == true) {
_editor->begin_reversible_command (_("copy meter mark"));
XMLNode &before = map.get_state();
map.add_meter (_marker->meter(), when);
XMLNode &after = map.get_state();
- _editor->session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
+ _editor->session()->add_command(new MementoCommand<TempoMap>(map, &before, &after));
_editor->commit_reversible_command ();
// delete the dummy marker we used for visual representation of copying.
XMLNode &before = map.get_state();
map.move_meter (_marker->meter(), when);
XMLNode &after = map.get_state();
- _editor->session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
+ _editor->session()->add_command(new MementoCommand<TempoMap>(map, &before, &after));
_editor->commit_reversible_command ();
}
}
+void
+MeterMarkerDrag::aborted ()
+{
+ _marker->set_position (_marker->meter().frame ());
+}
+
TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
: Drag (e, i),
_copy (c)
Drag::start_grab (event, cursor);
- _pointer_frame_offset = _grab_frame - _marker->tempo().frame();
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _pointer_frame_offset = grab_frame() - _marker->tempo().frame();
+ _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
void
TempoMarkerDrag::motion (GdkEvent* event, bool)
{
- nframes64_t const adjusted_frame = adjusted_current_frame (event);
-
- if (adjusted_frame == _last_pointer_frame) {
- return;
- }
-
- /* OK, we've moved far enough to make it worth actually move the thing. */
-
- _marker->set_position (adjusted_frame);
-
- _editor->show_verbose_time_cursor (adjusted_frame, 10);
-
- _last_pointer_frame = adjusted_frame;
+ nframes64_t const pf = adjusted_current_frame (event);
+ _marker->set_position (pf);
+ _editor->show_verbose_time_cursor (pf, 10);
}
void
BBT_Time when;
- TempoMap& map (_editor->session->tempo_map());
- map.bbt_time (_last_pointer_frame, when);
+ TempoMap& map (_editor->session()->tempo_map());
+ map.bbt_time (last_pointer_frame(), when);
if (_copy == true) {
_editor->begin_reversible_command (_("copy tempo mark"));
XMLNode &before = map.get_state();
map.add_tempo (_marker->tempo(), when);
XMLNode &after = map.get_state();
- _editor->session->add_command (new MementoCommand<TempoMap>(map, &before, &after));
+ _editor->session()->add_command (new MementoCommand<TempoMap>(map, &before, &after));
_editor->commit_reversible_command ();
// delete the dummy marker we used for visual representation of copying.
XMLNode &before = map.get_state();
map.move_tempo (_marker->tempo(), when);
XMLNode &after = map.get_state();
- _editor->session->add_command (new MementoCommand<TempoMap>(map, &before, &after));
+ _editor->session()->add_command (new MementoCommand<TempoMap>(map, &before, &after));
_editor->commit_reversible_command ();
}
}
+void
+TempoMarkerDrag::aborted ()
+{
+ _marker->set_position (_marker->tempo().frame());
+}
CursorDrag::CursorDrag (Editor* e, ArdourCanvas::Item* i, bool s)
: Drag (e, i),
if (_cursor == _editor->playhead_cursor) {
_editor->_dragging_playhead = true;
- if (_editor->session && _was_rolling && _stop) {
- _editor->session->request_stop ();
+ if (_editor->session() && _was_rolling && _stop) {
+ _editor->session()->request_stop ();
}
- if (_editor->session && _editor->session->is_auditioning()) {
- _editor->session->cancel_audition ();
+ if (_editor->session() && _editor->session()->is_auditioning()) {
+ _editor->session()->cancel_audition ();
}
}
+ _pointer_frame_offset = grab_frame() - _cursor->current_frame;
+
_editor->show_verbose_time_cursor (_cursor->current_frame, 10);
}
{
nframes64_t const adjusted_frame = adjusted_current_frame (event);
- if (adjusted_frame == _last_pointer_frame) {
+ if (adjusted_frame == last_pointer_frame()) {
return;
}
_editor->update_canvas_now ();
#endif
_editor->UpdateAllTransportClocks (_cursor->current_frame);
-
- _last_pointer_frame = adjusted_frame;
}
void
motion (event, false);
if (_item == &_editor->playhead_cursor->canvas_item) {
- if (_editor->session) {
- _editor->session->request_locate (_editor->playhead_cursor->current_frame, _was_rolling);
+ if (_editor->session()) {
+ _editor->session()->request_locate (_editor->playhead_cursor->current_frame, _was_rolling);
_editor->_pending_locate_request = true;
}
}
}
+void
+CursorDrag::aborted ()
+{
+ _editor->_dragging_playhead = false;
+ _cursor->set_position (adjusted_frame (grab_frame (), 0, false));
+}
+
FadeInDrag::FadeInDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionDrag (e, i, p, v)
{
AudioRegionView* a = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> const r = a->audio_region ();
- _pointer_frame_offset = _grab_frame - ((nframes64_t) r->fade_in()->back()->when + r->position());
+ _pointer_frame_offset = grab_frame() - ((nframes64_t) r->fade_in()->back()->when + r->position());
_editor->show_verbose_duration_cursor (r->position(), r->position() + r->fade_in()->back()->when, 10);
}
tmp->audio_region()->set_fade_in_active (true);
XMLNode &after = alist->get_state();
- _editor->session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
+ _editor->session()->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
}
_editor->commit_reversible_command ();
}
+void
+FadeInDrag::aborted ()
+{
+ for (RegionSelection::iterator i = _views.begin(); i != _views.end(); ++i) {
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
+
+ if (!tmp) {
+ continue;
+ }
+
+ tmp->reset_fade_in_shape_width (tmp->audio_region()->fade_in()->back()->when);
+ }
+}
+
FadeOutDrag::FadeOutDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionDrag (e, i, p, v)
{
AudioRegionView* a = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> r = a->audio_region ();
- _pointer_frame_offset = _grab_frame - (r->length() - (nframes64_t) r->fade_out()->back()->when + r->position());
+ _pointer_frame_offset = grab_frame() - (r->length() - (nframes64_t) r->fade_out()->back()->when + r->position());
_editor->show_verbose_duration_cursor (r->last_frame() - r->fade_out()->back()->when, r->last_frame(), 10);
}
tmp->audio_region()->set_fade_out_active (true);
XMLNode &after = alist->get_state();
- _editor->session->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
+ _editor->session()->add_command(new MementoCommand<AutomationList>(*alist.get(), &before, &after));
}
_editor->commit_reversible_command ();
}
+void
+FadeOutDrag::aborted ()
+{
+ for (RegionSelection::iterator i = _views.begin(); i != _views.end(); ++i) {
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
+
+ if (!tmp) {
+ continue;
+ }
+
+ tmp->reset_fade_out_shape_width (tmp->audio_region()->fade_out()->back()->when);
+ }
+}
+
MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
{
Location *location = _editor->find_location_from_marker (_marker, is_start);
_editor->_dragging_edit_point = true;
- _pointer_frame_offset = _grab_frame - (is_start ? location->start() : location->end());
+ _pointer_frame_offset = grab_frame() - (is_start ? location->start() : location->end());
update_item (location);
if (e < max_frames) {
++e;
}
- _editor->session->locations()->find_all_between (s, e, ll, Location::Flags (0));
+ _editor->session()->locations()->find_all_between (s, e, ll, Location::Flags (0));
for (Locations::LocationList::iterator i = ll.begin(); i != ll.end(); ++i) {
Editor::LocationMarkers* lm = _editor->find_location_markers (*i);
if (lm) {
nframes64_t next = newframe;
- if (_current_pointer_frame == _last_pointer_frame) {
+ if (newframe == last_pointer_frame()) {
return;
}
}
}
- _last_pointer_frame = _current_pointer_frame;
-
assert (!_copied_locations.empty());
_editor->show_verbose_time_cursor (newframe, 10);
_editor->_dragging_edit_point = false;
_editor->begin_reversible_command ( _("move marker") );
- XMLNode &before = _editor->session->locations()->get_state();
+ XMLNode &before = _editor->session()->locations()->get_state();
MarkerSelection::iterator i;
list<Location*>::iterator x;
}
}
- XMLNode &after = _editor->session->locations()->get_state();
- _editor->session->add_command(new MementoCommand<Locations>(*(_editor->session->locations()), &before, &after));
+ XMLNode &after = _editor->session()->locations()->get_state();
+ _editor->session()->add_command(new MementoCommand<Locations>(*(_editor->session()->locations()), &before, &after));
_editor->commit_reversible_command ();
_line->hide();
}
+void
+MarkerDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
void
MarkerDrag::update_item (Location* location)
{
// start the grab at the center of the control point so
// the point doesn't 'jump' to the mouse after the first drag
- _grab_x = _point->get_x();
- _grab_y = _point->get_y();
-
- _point->line().parent_group().i2w (_grab_x, _grab_y);
- _editor->track_canvas->w2c (_grab_x, _grab_y, _grab_x, _grab_y);
+ _time_axis_view_grab_x = _point->get_x();
+ _time_axis_view_grab_y = _point->get_y();
- _grab_frame = _editor->pixel_to_frame (_grab_x);
+ float const fraction = 1 - (_point->get_y() / _point->line().height());
- _point->line().start_drag (_point, _grab_frame, 0);
+ _point->line().start_drag_single (_point, _time_axis_view_grab_x, fraction);
- float fraction = 1.0 - (_point->get_y() / _point->line().height());
_editor->set_verbose_canvas_cursor (_point->line().get_verbose_cursor_string (fraction),
- _current_pointer_x + 10, _current_pointer_y + 10);
+ event->button.x + 10, event->button.y + 10);
_editor->show_verbose_canvas_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;
dy *= 0.1;
}
- double cx = _grab_x + _cumulative_x_drag + dx;
- double cy = _grab_y + _cumulative_y_drag + dy;
+ /* coordinate in TimeAxisView's space */
+ double cx = _time_axis_view_grab_x + _cumulative_x_drag + dx;
+ double cy = _time_axis_view_grab_y + _cumulative_y_drag + dy;
// calculate zero crossing point. back off by .01 to stay on the
// positive side of zero
- double _unused = 0;
- double zero_gain_y = (1.0 - _zero_gain_fraction) * _point->line().height() - .01;
- _point->line().parent_group().i2w(_unused, zero_gain_y);
+ 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 and (cy - dy) > zero_gain_y)
- or (cy > zero_gain_y and (cy - dy) < zero_gain_y)) {
+ 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 = _grab_x;
+ cx = _time_axis_view_grab_x;
}
if (_y_constrained) {
- cy = _grab_y;
+ cy = _time_axis_view_grab_y;
}
- _cumulative_x_drag = cx - _grab_x;
- _cumulative_y_drag = cy - _grab_y;
-
- _point->line().parent_group().w2i (cx, cy);
+ _cumulative_x_drag = cx - _time_axis_view_grab_x;
+ _cumulative_y_drag = cy - _time_axis_view_grab_y;
cx = max (0.0, cx);
cy = max (0.0, cy);
cy = min ((double) _point->line().height(), cy);
- //translate cx to frames
nframes64_t cx_frames = _editor->unit_to_frame (cx);
if (!_x_constrained) {
bool const push = Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier);
- _point->line().point_drag (*_point, cx_frames, fraction, push);
+ _point->line().drag_motion (_editor->frame_to_unit (cx_frames), fraction, false, push);
_editor->set_verbose_canvas_cursor_text (_point->line().get_verbose_cursor_string (fraction));
}
} else {
motion (event, false);
}
- _point->line().end_drag (_point);
+ _point->line().end_drag ();
+}
+
+void
+ControlPointDrag::aborted ()
+{
+ _point->line().reset ();
}
bool
nframes64_t const frame_within_region = (nframes64_t) floor (cx * _editor->frames_per_unit);
- if (!_line->control_points_adjacent (frame_within_region, _before, _after)) {
+ uint32_t before;
+ uint32_t after;
+
+ if (!_line->control_points_adjacent (frame_within_region, before, after)) {
/* no adjacent points */
return;
}
/* store grab start in parent frame */
- _grab_x = cx;
- _grab_y = cy;
+ _time_axis_view_grab_x = cx;
+ _time_axis_view_grab_y = cy;
double fraction = 1.0 - (cy / _line->height());
- _line->start_drag (0, _grab_frame, fraction);
+ _line->start_drag_line (before, after, fraction);
_editor->set_verbose_canvas_cursor (_line->get_verbose_cursor_string (fraction),
- _current_pointer_x + 10, _current_pointer_y + 10);
+ event->button.x + 10, event->button.y + 10);
_editor->show_verbose_canvas_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;
}
- double cy = _grab_y + _cumulative_y_drag + dy;
+ double cy = _time_axis_view_grab_y + _cumulative_y_drag + dy;
- _cumulative_y_drag = cy - _grab_y;
+ _cumulative_y_drag = cy - _time_axis_view_grab_y;
cy = max (0.0, cy);
cy = min ((double) _line->height(), cy);
push = true;
}
- _line->line_drag (_before, _after, fraction, push);
+ /* we are ignoring x position for this drag, so we can just pass in anything */
+ _line->drag_motion (0, fraction, true, push);
_editor->set_verbose_canvas_cursor_text (_line->get_verbose_cursor_string (fraction));
}
LineDrag::finished (GdkEvent* event, bool)
{
motion (event, false);
- _line->end_drag (0);
+ _line->end_drag ();
+}
+
+void
+LineDrag::aborted ()
+{
+ _line->reset ();
}
void
RubberbandSelectDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
Drag::start_grab (event);
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
void
-RubberbandSelectDrag::motion (GdkEvent* event, bool first_move)
+RubberbandSelectDrag::motion (GdkEvent* event, bool)
{
nframes64_t start;
nframes64_t end;
double y1;
double y2;
- /* use a bigger drag threshold than the default */
+ nframes64_t const pf = adjusted_current_frame (event, Config->get_rubberbanding_snaps_to_grid ());
- if (abs ((int) (_current_pointer_frame - _grab_frame)) < 8) {
- return;
+ nframes64_t grab = grab_frame ();
+ if (Config->get_rubberbanding_snaps_to_grid ()) {
+ _editor->snap_to_with_modifier (grab, event);
}
- if (Config->get_rubberbanding_snaps_to_grid()) {
- if (first_move) {
- _editor->snap_to_with_modifier (_grab_frame, event);
- }
- _editor->snap_to_with_modifier (_current_pointer_frame, event);
- }
-
/* base start and end on initial click position */
- if (_current_pointer_frame < _grab_frame) {
- start = _current_pointer_frame;
- end = _grab_frame;
+ if (pf < grab) {
+ start = pf;
+ end = grab;
} else {
- end = _current_pointer_frame;
- start = _grab_frame;
+ end = pf;
+ start = grab;
}
- if (_current_pointer_y < _grab_y) {
- y1 = _current_pointer_y;
- y2 = _grab_y;
+ if (_drags->current_pointer_y() < grab_y()) {
+ y1 = _drags->current_pointer_y();
+ y2 = grab_y();
} else {
- y2 = _current_pointer_y;
- y1 = _grab_y;
+ y2 = _drags->current_pointer_y();
+ y1 = grab_y();
}
_editor->rubberband_rect->show();
_editor->rubberband_rect->raise_to_top();
- _last_pointer_frame = _current_pointer_frame;
-
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (pf, 10);
}
}
motion (event, false);
double y1,y2;
- if (_current_pointer_y < _grab_y) {
- y1 = _current_pointer_y;
- y2 = _grab_y;
+ if (_drags->current_pointer_y() < grab_y()) {
+ y1 = _drags->current_pointer_y();
+ y2 = grab_y();
} else {
- y2 = _current_pointer_y;
- y1 = _grab_y;
+ y2 = _drags->current_pointer_y();
+ y1 = grab_y();
}
_editor->begin_reversible_command (_("rubberband selection"));
- if (_grab_frame < _last_pointer_frame) {
- committed = _editor->select_all_within (_grab_frame, _last_pointer_frame - 1, y1, y2, _editor->track_views, op);
+ if (grab_frame() < last_pointer_frame()) {
+ committed = _editor->select_all_within (grab_frame(), last_pointer_frame() - 1, y1, y2, _editor->track_views, op);
} else {
- committed = _editor->select_all_within (_last_pointer_frame, _grab_frame - 1, y1, y2, _editor->track_views, op);
+ committed = _editor->select_all_within (last_pointer_frame(), grab_frame() - 1, y1, y2, _editor->track_views, op);
}
if (!committed) {
_editor->rubberband_rect->hide();
}
+void
+RubberbandSelectDrag::aborted ()
+{
+ _editor->rubberband_rect->hide ();
+}
+
void
TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
Drag::start_grab (event);
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
void
{
RegionView* rv = _primary;
- _editor->snap_to_with_modifier (_current_pointer_frame, event);
-
- if (_current_pointer_frame == _last_pointer_frame) {
- return;
- }
+ nframes64_t const pf = adjusted_current_frame (event);
- if (_current_pointer_frame > rv->region()->position()) {
- rv->get_time_axis_view().show_timestretch (rv->region()->position(), _current_pointer_frame);
+ if (pf > rv->region()->position()) {
+ rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf);
}
- _last_pointer_frame = _current_pointer_frame;
-
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (pf, 10);
}
void
return;
}
- if (_last_pointer_frame < _primary->region()->position()) {
+ if (last_pointer_frame() < _primary->region()->position()) {
/* backwards drag of the left edge - not usable */
return;
}
- nframes64_t newlen = _last_pointer_frame - _primary->region()->position();
+ nframes64_t newlen = last_pointer_frame() - _primary->region()->position();
float percentage = (double) newlen / (double) _primary->region()->length();
}
}
+void
+TimeFXDrag::aborted ()
+{
+ _primary->get_time_axis_view().hide_timestretch ();
+}
+
+
void
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
ScrubDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
{
- if (movement_occurred && _editor->session) {
+ if (movement_occurred && _editor->session()) {
/* make sure we stop */
- _editor->session->request_transport_speed (0.0);
+ _editor->session()->request_transport_speed (0.0);
}
}
+void
+ScrubDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
SelectionDrag::SelectionDrag (Editor* e, ArdourCanvas::Item* i, Operation o)
: Drag (e, i)
, _operation (o)
, _copy (false)
+ , _original_pointer_time_axis (-1)
+ , _last_pointer_time_axis (-1)
{
}
nframes64_t start = 0;
nframes64_t end = 0;
- if (_editor->session == 0) {
+ if (_editor->session() == 0) {
return;
}
if (_editor->clicked_axisview) {
_editor->clicked_axisview->order_selection_trims (_item, true);
}
- Drag::start_grab (event, cursor);
- cursor = _editor->trimmer_cursor;
+ Drag::start_grab (event, _editor->trimmer_cursor);
start = _editor->selection->time[_editor->clicked_selection].start;
- _pointer_frame_offset = _grab_frame - start;
+ _pointer_frame_offset = grab_frame() - start;
break;
case SelectionEndTrim:
if (_editor->clicked_axisview) {
_editor->clicked_axisview->order_selection_trims (_item, false);
}
- Drag::start_grab (event, cursor);
- cursor = _editor->trimmer_cursor;
+ Drag::start_grab (event, _editor->trimmer_cursor);
end = _editor->selection->time[_editor->clicked_selection].end;
- _pointer_frame_offset = _grab_frame - end;
+ _pointer_frame_offset = grab_frame() - end;
break;
case SelectionMove:
start = _editor->selection->time[_editor->clicked_selection].start;
Drag::start_grab (event, cursor);
- _pointer_frame_offset = _grab_frame - start;
+ _pointer_frame_offset = grab_frame() - start;
break;
}
if (_operation == SelectionMove) {
_editor->show_verbose_time_cursor (start, 10);
} else {
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
+
+ _original_pointer_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()).first->order ();
}
void
nframes64_t end = 0;
nframes64_t length;
-
+ pair<TimeAxisView*, int> const pending_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ());
+ if (pending_time_axis.first == 0) {
+ return;
+ }
+
nframes64_t const pending_position = adjusted_current_frame (event);
- /* only alter selection if the current frame is
- different from the last frame position (adjusted)
- */
+ /* only alter selection if things have changed */
- if (pending_position == _last_pointer_frame) {
+ if (pending_time_axis.first->order() == _last_pointer_time_axis && pending_position == last_pointer_frame()) {
return;
}
switch (_operation) {
case CreateSelection:
+ {
+ nframes64_t grab = grab_frame ();
if (first_move) {
- _editor->snap_to (_grab_frame);
+ _editor->snap_to (grab);
}
- if (pending_position < _grab_frame) {
+ if (pending_position < grab_frame()) {
start = pending_position;
- end = _grab_frame;
+ end = grab;
} else {
end = pending_position;
- start = _grab_frame;
+ start = grab;
}
/* first drag: Either add to the selection
- or create a new selection->
+ or create a new selection
*/
if (first_move) {
- _editor->begin_reversible_command (_("range selection"));
- _have_transaction = true;
-
if (_copy) {
/* adding to the selection */
+ _editor->selection->add (_editor->clicked_axisview);
_editor->clicked_selection = _editor->selection->add (start, end);
_copy = false;
} else {
- /* new selection-> */
- _editor->clicked_selection = _editor->selection->set (_editor->clicked_axisview, start, end);
+ /* new selection */
+
+ if (!_editor->selection->selected (_editor->clicked_axisview)) {
+ _editor->selection->set (_editor->clicked_axisview);
+ }
+
+ _editor->clicked_selection = _editor->selection->set (start, end);
}
}
- break;
-
- case SelectionStartTrim:
- if (first_move) {
- _editor->begin_reversible_command (_("trim selection start"));
- _have_transaction = true;
+ /* select the track that we're in */
+ if (find (_added_time_axes.begin(), _added_time_axes.end(), pending_time_axis.first) == _added_time_axes.end()) {
+ _editor->selection->add (pending_time_axis.first);
+ _added_time_axes.push_back (pending_time_axis.first);
}
+
+ /* deselect any tracks that this drag no longer includes, being careful to only deselect
+ tracks that we selected in the first place.
+ */
+ int min_order = min (_original_pointer_time_axis, pending_time_axis.first->order());
+ int max_order = max (_original_pointer_time_axis, pending_time_axis.first->order());
+
+ list<TimeAxisView*>::iterator i = _added_time_axes.begin();
+ while (i != _added_time_axes.end()) {
+
+ list<TimeAxisView*>::iterator tmp = i;
+ ++tmp;
+
+ if ((*i)->order() < min_order || (*i)->order() > max_order) {
+ _editor->selection->remove (*i);
+ _added_time_axes.remove (*i);
+ }
+
+ i = tmp;
+ }
+
+ }
+ break;
+
+ case SelectionStartTrim:
+
start = _editor->selection->time[_editor->clicked_selection].start;
end = _editor->selection->time[_editor->clicked_selection].end;
case SelectionEndTrim:
- if (first_move) {
- _editor->begin_reversible_command (_("trim selection end"));
- _have_transaction = true;
- }
-
start = _editor->selection->time[_editor->clicked_selection].start;
end = _editor->selection->time[_editor->clicked_selection].end;
case SelectionMove:
- if (first_move) {
- _editor->begin_reversible_command (_("move selection"));
- _have_transaction = true;
- }
-
start = _editor->selection->time[_editor->clicked_selection].start;
end = _editor->selection->time[_editor->clicked_selection].end;
_editor->selection->replace (_editor->clicked_selection, start, end);
}
- _last_pointer_frame = pending_position;
-
if (_operation == SelectionMove) {
_editor->show_verbose_time_cursor(start, 10);
} else {
void
SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
{
- Session* s = _editor->session;
+ Session* s = _editor->session();
if (movement_occurred) {
motion (event, false);
_editor->selection->TimeChanged ();
}
- if (_have_transaction) {
- _editor->commit_reversible_command ();
- }
-
/* XXX what if its a music time selection? */
if (s && (s->config.get_auto_play() || (s->get_play_range() && s->transport_rolling()))) {
s->request_play_range (&_editor->selection->time, true);
/* just a click, no pointer movement.*/
if (Keyboard::no_modifier_keys_pressed (&event->button)) {
-
_editor->selection->clear_time();
+ }
+ if (!_editor->selection->selected (_editor->clicked_axisview)) {
+ _editor->selection->set (_editor->clicked_axisview);
}
if (s && s->get_play_range () && s->transport_rolling()) {
_editor->stop_canvas_autoscroll ();
}
+void
+SelectionDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
RangeMarkerBarDrag::RangeMarkerBarDrag (Editor* e, ArdourCanvas::Item* i, Operation o)
: Drag (e, i),
_operation (o),
void
RangeMarkerBarDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
- if (_editor->session == 0) {
+ if (_editor->session() == 0) {
return;
}
Drag::start_grab (event, cursor);
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
void
break;
}
- _editor->snap_to_with_modifier (_current_pointer_frame, event);
+ nframes64_t const pf = adjusted_current_frame (event);
- /* only alter selection if the current frame is
- different from the last frame position.
- */
-
- if (_current_pointer_frame == _last_pointer_frame) {
- return;
- }
-
- switch (_operation) {
- case CreateRangeMarker:
- case CreateTransportMarker:
- case CreateCDMarker:
- if (first_move) {
- _editor->snap_to (_grab_frame);
- }
-
- if (_current_pointer_frame < _grab_frame) {
- start = _current_pointer_frame;
- end = _grab_frame;
+ if (_operation == CreateRangeMarker || _operation == CreateTransportMarker || _operation == CreateCDMarker) {
+ nframes64_t grab = grab_frame ();
+ _editor->snap_to (grab);
+
+ if (pf < grab_frame()) {
+ start = pf;
+ end = grab;
} else {
- end = _current_pointer_frame;
- start = _grab_frame;
+ end = pf;
+ start = grab;
}
/* first drag: Either add to the selection
//_drag_rect->raise_to_top();
}
- break;
}
if (event->button.x >= _editor->horizontal_adjustment.get_value() + _editor->_canvas_width) {
update_item (_editor->temp_location);
}
- _last_pointer_frame = _current_pointer_frame;
-
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (pf, 10);
}
case CreateCDMarker:
{
_editor->begin_reversible_command (_("new range marker"));
- XMLNode &before = _editor->session->locations()->get_state();
- _editor->session->locations()->next_available_name(rangename,"unnamed");
+ XMLNode &before = _editor->session()->locations()->get_state();
+ _editor->session()->locations()->next_available_name(rangename,"unnamed");
if (_operation == CreateCDMarker) {
flags = Location::IsRangeMarker | Location::IsCDMarker;
_editor->cd_marker_bar_drag_rect->hide();
_editor->range_bar_drag_rect->hide();
}
newloc = new Location(_editor->temp_location->start(), _editor->temp_location->end(), rangename, (Location::Flags) flags);
- _editor->session->locations()->add (newloc, true);
- XMLNode &after = _editor->session->locations()->get_state();
- _editor->session->add_command(new MementoCommand<Locations>(*(_editor->session->locations()), &before, &after));
+ _editor->session()->locations()->add (newloc, true);
+ XMLNode &after = _editor->session()->locations()->get_state();
+ _editor->session()->add_command(new MementoCommand<Locations>(*(_editor->session()->locations()), &before, &after));
_editor->commit_reversible_command ();
break;
}
nframes64_t start;
nframes64_t end;
- _editor->session->locations()->marks_either_side (_grab_frame, start, end);
+ _editor->session()->locations()->marks_either_side (grab_frame(), start, end);
if (end == max_frames) {
- end = _editor->session->current_end_frame ();
+ end = _editor->session()->current_end_frame ();
}
if (start == max_frames) {
- start = _editor->session->current_start_frame ();
+ start = _editor->session()->current_start_frame ();
}
switch (_editor->mouse_mode) {
case MouseRange:
/* find the two markers on either side of the click and make the range out of it */
- _editor->selection->set (0, start, end);
+ _editor->selection->set (start, end);
break;
default:
_editor->stop_canvas_autoscroll ();
}
-
+void
+RangeMarkerBarDrag::aborted ()
+{
+ /* XXX: TODO */
+}
void
RangeMarkerBarDrag::update_item (Location* location)
MouseZoomDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
Drag::start_grab (event, _editor->zoom_cursor);
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
void
nframes64_t start;
nframes64_t end;
- _editor->snap_to_with_modifier (_current_pointer_frame, event);
+ nframes64_t const pf = adjusted_current_frame (event);
- if (first_move) {
- _editor->snap_to_with_modifier (_grab_frame, event);
- }
-
- if (_current_pointer_frame == _last_pointer_frame) {
- return;
- }
+ nframes64_t grab = grab_frame ();
+ _editor->snap_to_with_modifier (grab, event);
/* base start and end on initial click position */
- if (_current_pointer_frame < _grab_frame) {
- start = _current_pointer_frame;
- end = _grab_frame;
+ if (pf < grab) {
+ start = pf;
+ end = grab;
} else {
- end = _current_pointer_frame;
- start = _grab_frame;
+ end = pf;
+ start = grab;
}
if (start != end) {
_editor->reposition_zoom_rect(start, end);
- _last_pointer_frame = _current_pointer_frame;
-
- _editor->show_verbose_time_cursor (_current_pointer_frame, 10);
+ _editor->show_verbose_time_cursor (pf, 10);
}
}
if (movement_occurred) {
motion (event, false);
- if (_grab_frame < _last_pointer_frame) {
- _editor->temporal_zoom_by_frame (_grab_frame, _last_pointer_frame, "mouse zoom");
+ if (grab_frame() < last_pointer_frame()) {
+ _editor->temporal_zoom_by_frame (grab_frame(), last_pointer_frame(), "mouse zoom");
} else {
- _editor->temporal_zoom_by_frame (_last_pointer_frame, _grab_frame, "mouse zoom");
+ _editor->temporal_zoom_by_frame (last_pointer_frame(), grab_frame(), "mouse zoom");
}
} else {
- _editor->temporal_zoom_to_frame (false, _grab_frame);
+ _editor->temporal_zoom_to_frame (false, grab_frame());
/*
temporal_zoom_step (false);
- center_screen (_grab_frame);
+ center_screen (grab_frame());
*/
}
_editor->zoom_rect->hide();
}
+void
+MouseZoomDrag::aborted ()
+{
+ _editor->zoom_rect->hide ();
+}
+
NoteDrag::NoteDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
{
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);
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);
region->note_dropped (cnote, drag_delta_x, drag_delta_note);
}
}
+
+void
+NoteDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
+AutomationRangeDrag::AutomationRangeDrag (Editor* e, ArdourCanvas::Item* i, list<AudioRange> const & r)
+ : Drag (e, i)
+ , _ranges (r)
+ , _nothing_to_drag (false)
+{
+ _atav = reinterpret_cast<AutomationTimeAxisView*> (_item->get_data ("trackview"));
+ assert (_atav);
+
+ _line = _atav->line ();
+}
+
+void
+AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
+{
+ Drag::start_grab (event, cursor);
+
+ list<ControlPoint*> points;
+
+ XMLNode* state = &_line->get_state ();
+
+ if (_ranges.empty()) {
+
+ uint32_t const N = _line->npoints ();
+ for (uint32_t i = 0; i < N; ++i) {
+ points.push_back (_line->nth (i));
+ }
+
+ } else {
+
+ boost::shared_ptr<AutomationList> the_list = _line->the_list ();
+ for (list<AudioRange>::const_iterator j = _ranges.begin(); j != _ranges.end(); ++j) {
+
+ /* fade into and out of the region that we're dragging;
+ 64 samples length plucked out of thin air.
+ */
+ nframes64_t const h = (j->start + j->end) / 2;
+ nframes64_t a = j->start + 64;
+ if (a > h) {
+ a = h;
+ }
+ nframes64_t b = j->end - 64;
+ if (b < h) {
+ b = h;
+ }
+
+ the_list->add (j->start, the_list->eval (j->start));
+ _line->add_always_in_view (j->start);
+ the_list->add (a, the_list->eval (a));
+ _line->add_always_in_view (a);
+ the_list->add (b, the_list->eval (b));
+ _line->add_always_in_view (b);
+ the_list->add (j->end, the_list->eval (j->end));
+ _line->add_always_in_view (j->end);
+ }
+
+ uint32_t const N = _line->npoints ();
+ for (uint32_t i = 0; i < N; ++i) {
+
+ ControlPoint* p = _line->nth (i);
+
+ list<AudioRange>::const_iterator j = _ranges.begin ();
+ while (j != _ranges.end() && (j->start >= (*p->model())->when || j->end <= (*p->model())->when)) {
+ ++j;
+ }
+
+ if (j != _ranges.end()) {
+ points.push_back (p);
+ }
+ }
+ }
+
+ if (points.empty()) {
+ _nothing_to_drag = true;
+ return;
+ }
+
+ _line->start_drag_multiple (points, 1 - (_drags->current_pointer_y() / _line->height ()), state);
+}
+
+void
+AutomationRangeDrag::motion (GdkEvent* event, bool first_move)
+{
+ if (_nothing_to_drag) {
+ return;
+ }
+
+ 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);
+}
+
+void
+AutomationRangeDrag::finished (GdkEvent* event, bool)
+{
+ if (_nothing_to_drag) {
+ return;
+ }
+
+ motion (event, false);
+ _line->end_drag ();
+ _line->clear_always_in_view ();
+}
+
+void
+AutomationRangeDrag::aborted ()
+{
+ _line->clear_always_in_view ();
+ _line->reset ();
+}