*/
+#define __STDC_LIMIT_MACROS 1
+#include <stdint.h>
#include "pbd/memento_command.h"
#include "pbd/basename.h"
-#include "ardour/diskstream.h"
+#include "pbd/stateful_diff_command.h"
#include "ardour/session.h"
#include "ardour/dB.h"
#include "ardour/region_factory.h"
-#include "ardour/midi_diskstream.h"
#include "editor.h"
#include "i18n.h"
#include "keyboard.h"
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 ();
+}
+
+/** Call abort for each active drag */
+void
+DragManager::abort ()
+{
+ _ending = true;
+
+ for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
+ (*i)->abort ();
+ 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);
+ }
+}
+
+/** Call end_grab for each active drag.
+ * @return true if any drag reported movement having occurred.
+ */
+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)
- , _have_transaction (false)
- , _had_movement (false)
, _move_threshold_passed (false)
, _grab_frame (0)
, _last_pointer_frame (0)
- , _current_pointer_frame (0)
{
}
}
_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);
+ *cursor,
+ event->button.time);
if (_editor->session() && _editor->session()->transport_rolling()) {
_was_rolling = true;
}
}
-/** @param event GDK event, or 0.
+/** Call to end a drag `successfully'. Ungrabs item and calls
+ * subclass' finished() method.
+ *
+ * @param event GDK event, or 0.
* @return true if some movement occurred, otherwise 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 const * event, bool snap) 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;
}
if (snap) {
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;
- _last_pointer_frame = adjusted_current_frame (event);
- _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 ());
+ _editor->maybe_autoscroll (true, 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;
}
-
+/** Call to abort a drag. Ungrabs item and calls subclass's aborted () */
void
-Drag::break_drag ()
+Drag::abort ()
{
- _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)
+ _primary (p)
{
- RegionView::RegionViewGoingAway.connect (death_connection, ui_bind (&RegionDrag::region_going_away, this, _1), gui_context());
+ for (list<RegionView*>::const_iterator i = v.begin(); i != v.end(); ++i) {
+ _views.push_back (DraggingView (*i));
+ }
+
+ RegionView::RegionViewGoingAway.connect (death_connection, invalidator (*this), ui_bind (&RegionDrag::region_going_away, this, _1), gui_context());
}
void
RegionDrag::region_going_away (RegionView* v)
{
- _views.remove (v);
+ list<DraggingView>::iterator i = _views.begin ();
+ while (i != _views.end() && i->view != v) {
+ ++i;
+ }
+
+ if (i != _views.end()) {
+ _views.erase (i);
+ }
}
RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b)
: RegionDrag (e, i, p, v),
_dest_trackview (0),
_dest_layer (0),
- _brushing (b)
+ _brushing (b),
+ _total_x_delta (0)
{
}
}
}
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- RegionView* rv = (*i);
+ RegionView* rv = i->view;
if (rv->region()->locked()) {
continue;
if (*pending_region_position <= _last_frame_position) {
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- RegionView* rv = (*i);
+ RegionView* rv = i->view;
// If any regionview is at zero, we need to know so we can stop further leftward motion.
rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
rv->get_canvas_frame()->i2w (ix1, iy1);
- if (-x_delta > ix1 + _editor->horizontal_adjustment.get_value()) {
+ if (-x_delta > ix1 + _editor->horizontal_position()) {
x_delta = 0;
*pending_region_position = _last_frame_position;
break;
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- RegionView* rv = (*i);
+ RegionView* rv = i->view;
if (rv->region()->locked()) {
continue;
} /* foreach region */
+ _total_x_delta += x_delta;
+
if (first_move) {
_editor->cursor_group->raise_to_top();
}
RegionMoveDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
{
vector<RegionView*> copies;
- boost::shared_ptr<Diskstream> ds;
+ boost::shared_ptr<Track> tr;
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 */
/* all changes were made during motion event handlers */
if (_copy) {
- for (list<RegionView*>::iterator i = _views.begin(); i != _views.end(); ++i) {
- copies.push_back (*i);
+ for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
+ copies.push_back (i->view);
}
}
}
}
- _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 ();
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ) {
+ cerr << "Iterate over " << _views.size() << " views\n";
- RegionView* rv = (*i);
- RouteTimeAxisView* dest_rtv = final[*i].first;
- layer_t dest_layer = final[*i].second;
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ) {
+
+ RegionView* rv = i->view;
+ RouteTimeAxisView* dest_rtv = final[rv].first;
+ layer_t dest_layer = final[rv].second;
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_canvas_group()->property_y() = i->initial_y;
+ 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) {
*/
source_tv = dynamic_cast<RouteTimeAxisView*> (&rv->get_time_axis_view());
- ds = source_tv->get_diskstream();
- from_playlist = ds->playlist();
+ tr = source_tv->track();
+ from_playlist = tr->playlist();
assert (source_tv);
- assert (ds);
+ assert (tr);
assert (from_playlist);
/* moved to a different audio track, without copying */
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<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ delete i->view;
+ }
+
+ _views.clear ();
+
+ } else {
+ RegionMotionDrag::aborted ();
+ }
+}
+
+void
+RegionMotionDrag::aborted ()
+{
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ RegionView* rv = i->view;
+ TimeAxisView* tv = &(rv->get_time_axis_view ());
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
+ assert (rtv);
+ rv->get_canvas_group()->reparent (*rtv->view()->canvas_item());
+ rv->get_canvas_group()->property_y() = 0;
+ rv->get_time_axis_view().reveal_dependent_views (*rv);
+ rv->fake_set_opaque (false);
+ rv->move (-_total_x_delta, 0);
+ rv->set_height (rtv->view()->child_height ());
+ }
+
+ _editor->update_canvas_now ();
+}
+
bool
RegionMotionDrag::x_move_allowed () const
{
/* duplicate the regionview(s) and region(s) */
- list<RegionView*> new_regionviews;
+ list<DraggingView> new_regionviews;
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- RegionView* rv = (*i);
+ RegionView* rv = i->view;
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(rv);
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
}
nrv->get_canvas_group()->show ();
- new_regionviews.push_back (nrv);
+ new_regionviews.push_back (DraggingView (nrv));
/* swap _primary to the copy */
_views = new_regionviews;
- swap_grab (new_regionviews.front()->get_canvas_group (), 0, event ? event->motion.time : 0);
+ swap_grab (new_regionviews.front().view->get_canvas_group (), 0, event ? event->motion.time : 0);
/*
sync the canvas to what we think is its current state
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;
double speed = 1;
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
if (rtv && rtv->is_track()) {
- speed = rtv->get_diskstream()->speed ();
+ speed = rtv->track()->speed ();
}
_last_frame_position = static_cast<nframes64_t> (_primary->region()->position() / speed);
_primary->get_canvas_group()->show ();
_primary->set_position (pos, 0);
- _views.push_back (_primary);
+ _views.push_back (DraggingView (_primary));
_last_frame_position = pos;
{
map<RegionView*, pair<RouteTimeAxisView*, int> > tav;
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
double ix1, ix2, iy1, iy2;
- (*i)->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
- (*i)->get_canvas_frame()->i2w (ix1, iy1);
+ RegionView* rv = i->view;
+ rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
+ rv->get_canvas_frame()->i2w (ix1, iy1);
iy1 += _editor->vertical_adjustment.get_value() - _editor->canvas_timebars_vsize;
pair<TimeAxisView*, int> tv = _editor->trackview_by_y_position (iy1);
- tav[*i] = make_pair (dynamic_cast<RouteTimeAxisView*> (tv.first), tv.second);
+ tav[rv] = make_pair (dynamic_cast<RouteTimeAxisView*> (tv.first), tv.second);
}
return tav;
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 ()
+{
+ delete _primary;
+ _primary = 0;
+ _views.clear ();
+}
+
RegionSpliceDrag::RegionSpliceDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionMoveDrag (e, i, p, v, false, false)
{
int dir;
- if ((current_pointer_x() - last_pointer_x()) > 0) {
+ if ((_drags->current_pointer_x() - last_pointer_x()) > 0) {
dir = 1;
} else {
dir = -1;
}
+void
+RegionSpliceDrag::aborted ()
+{
+ /* XXX: TODO */
+}
RegionCreateDrag::RegionCreateDrag (Editor* e, ArdourCanvas::Item* i, TimeAxisView* v)
: Drag (e, i),
}
}
+void
+RegionCreateDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
, region (0)
}
void
-NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
+NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
{
- Gdk::Cursor cursor;
- ArdourCanvas::CanvasNote* cnote = dynamic_cast<ArdourCanvas::CanvasNote*>(_item);
+ Gdk::Cursor* cursor;
+ ArdourCanvas::CanvasNote* cnote = dynamic_cast<ArdourCanvas::CanvasNote*>(_item);
Drag::start_grab (event);
region = &cnote->region_view();
- double region_start = region->get_position_pixels();
- double middle_point = region_start + cnote->x1() + (cnote->x2() - cnote->x1()) / 2.0L;
+ double const region_start = region->get_position_pixels();
+ double const middle_point = region_start + cnote->x1() + (cnote->x2() - cnote->x1()) / 2.0L;
if (grab_x() <= middle_point) {
- cursor = Gdk::Cursor(Gdk::LEFT_SIDE);
+ cursor = _editor->left_side_trim_cursor;
at_front = true;
} else {
- cursor = Gdk::Cursor(Gdk::RIGHT_SIDE);
+ cursor = _editor->right_side_trim_cursor;
at_front = false;
}
- _item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, cursor, event->motion.time);
+ _item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, *cursor, event->motion.time);
if (event->motion.state & Keyboard::PrimaryModifier) {
relative = false;
relative = true;
}
- region->note_selected (cnote, 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 ());
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ) {
MidiRegionSelection::iterator next;
{
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 (dynamic_cast<ArdourCanvas::CanvasNote*>(_item), 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 (dynamic_cast<ArdourCanvas::CanvasNote*>(_item), 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)
{
}
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
if (tv && tv->is_track()) {
- speed = tv->get_diskstream()->speed();
+ speed = tv->track()->speed();
}
- nframes64_t region_start = (nframes64_t) (_primary->region()->position() / speed);
- nframes64_t region_end = (nframes64_t) (_primary->region()->last_frame() / speed);
- nframes64_t region_length = (nframes64_t) (_primary->region()->length() / speed);
-
- Drag::start_grab (event, _editor->trimmer_cursor);
+ nframes64_t const region_start = (nframes64_t) (_primary->region()->position() / speed);
+ nframes64_t const region_end = (nframes64_t) (_primary->region()->last_frame() / speed);
+ nframes64_t const region_length = (nframes64_t) (_primary->region()->length() / speed);
nframes64_t const pf = adjusted_current_frame (event);
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
_operation = ContentsTrim;
+ Drag::start_grab (event, _editor->trimmer_cursor);
} else {
/* These will get overridden for a point trim.*/
if (pf < (region_start + region_length/2)) {
/* closer to start */
_operation = StartTrim;
- } else if (pf > (region_end - region_length/2)) {
+ Drag::start_grab (event, _editor->left_side_trim_cursor);
+ } else {
/* closer to end */
_operation = EndTrim;
- }
+ Drag::start_grab (event, _editor->right_side_trim_cursor);
+ }
}
switch (_operation) {
TrimDrag::motion (GdkEvent* event, bool first_move)
{
RegionView* rv = _primary;
- nframes64_t frame_delta = 0;
-
- bool left_direction;
- bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier());
/* snap modifier works differently here..
its current state has to be passed to the
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
if (tv && tv->is_track()) {
- speed = tv->get_diskstream()->speed();
+ speed = tv->track()->speed();
}
nframes64_t const pf = adjusted_current_frame (event);
- if (last_pointer_frame() > pf) {
- left_direction = true;
- } else {
- left_direction = false;
- }
-
if (first_move) {
string trim_type;
_editor->begin_reversible_command (trim_type);
_have_transaction = true;
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- (*i)->fake_set_opaque(false);
- (*i)->region()->freeze ();
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ RegionView* rv = i->view;
+ rv->fake_set_opaque(false);
+ rv->enable_display (false);
+ rv->region()->clear_history ();
+ rv->region()->suspend_property_changes ();
- AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (rv);
if (arv){
arv->temporarily_hide_envelope ();
}
- boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
+ boost::shared_ptr<Playlist> pl = rv->region()->playlist();
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 (pf == 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() - pf);
- } else {
- 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) && (pf <= rv->region()->first_frame()/speed)) {
- break;
- } else {
-
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- _editor->single_start_trim (**i, frame_delta, left_direction, obey_snap, non_overlap_trim);
- }
- break;
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ _editor->single_start_trim (*i->view, pf, non_overlap_trim);
}
+ break;
case EndTrim:
- if ((left_direction == true) && (pf > (nframes64_t) (rv->region()->last_frame()/speed))) {
- break;
- } else {
-
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- _editor->single_end_trim (**i, frame_delta, left_direction, obey_snap, non_overlap_trim);
- }
- break;
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ _editor->single_end_trim (*i->view, pf, non_overlap_trim);
}
+ break;
case ContentsTrim:
{
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) {
- _editor->single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap);
+ nframes64_t frame_delta = 0;
+
+ bool left_direction = false;
+ if (last_pointer_frame() > pf) {
+ left_direction = true;
+ }
+
+ if (left_direction) {
+ frame_delta = (last_pointer_frame() - pf);
+ } else {
+ frame_delta = (pf - last_pointer_frame());
+ }
+
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ _editor->single_contents_trim (*i->view, frame_delta, left_direction, swap_direction);
}
}
break;
_editor->thaw_region_after_trim (*_primary);
} else {
- for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- _editor->thaw_region_after_trim (**i);
- (*i)->fake_set_opaque (true);
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ _editor->thaw_region_after_trim (*i->view);
+ i->view->enable_display (true);
+ i->view->fake_set_opaque (true);
+ if (_have_transaction) {
+ _editor->session()->add_command (new StatefulDiffCommand (i->view->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 ();
}
}
{
nframes64_t const pf = adjusted_current_frame (event);
- if (pf == last_pointer_frame()) {
- return;
- }
-
_marker->set_position (pf);
_editor->show_verbose_time_cursor (pf, 10);
}
}
+void
+MeterMarkerDrag::aborted ()
+{
+ _marker->set_position (_marker->meter().frame ());
+}
+
TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
: Drag (e, i),
_copy (c)
TempoMarkerDrag::motion (GdkEvent* event, bool)
{
nframes64_t const pf = adjusted_current_frame (event);
-
- if (pf == last_pointer_frame()) {
- return;
- }
-
- /* OK, we've moved far enough to make it worth actually move the thing. */
-
_marker->set_position (pf);
-
_editor->show_verbose_time_cursor (pf, 10);
}
}
}
+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 ();
- }
+ Session* s = _editor->session ();
+
+ if (s) {
+ if (_was_rolling && _stop) {
+ s->request_stop ();
+ }
- if (_editor->session() && _editor->session()->is_auditioning()) {
- _editor->session()->cancel_audition ();
+ if (s->is_auditioning()) {
+ s->cancel_audition ();
+ }
+
+ s->request_suspend_timecode_transmission ();
+
+ if (s->timecode_transmission_suspended ()) {
+ nframes64_t const f = _editor->playhead_cursor->current_frame;
+ s->send_mmc_locate (f);
+ s->send_full_time_code (f);
+ }
}
}
+ _pointer_frame_offset = grab_frame() - _cursor->current_frame;
+
_editor->show_verbose_time_cursor (_cursor->current_frame, 10);
}
_editor->show_verbose_time_cursor (_cursor->current_frame, 10);
+ Session* s = _editor->session ();
+ if (s && _item == &_editor->playhead_cursor->canvas_item && s->timecode_transmission_suspended ()) {
+ nframes64_t const f = _editor->playhead_cursor->current_frame;
+ s->send_mmc_locate (f);
+ s->send_full_time_code (f);
+ }
+
+
#ifdef GTKOSX
_editor->update_canvas_now ();
#endif
motion (event, false);
if (_item == &_editor->playhead_cursor->canvas_item) {
- if (_editor->session()) {
- _editor->session()->request_locate (_editor->playhead_cursor->current_frame, _was_rolling);
+ Session* s = _editor->session ();
+ if (s) {
+ s->request_locate (_editor->playhead_cursor->current_frame, _was_rolling);
_editor->_pending_locate_request = true;
+ s->request_resume_timecode_transmission ();
}
}
}
+void
+CursorDrag::aborted ()
+{
+ if (_editor->_dragging_playhead) {
+ _editor->session()->request_resume_timecode_transmission ();
+ _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)
{
_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);
+
}
void
fade_length = pos - region->position();
}
- for (RegionSelection::iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
- AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
if (!tmp) {
continue;
_editor->begin_reversible_command (_("change fade in length"));
- for (RegionSelection::iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
- AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
if (!tmp) {
continue;
_editor->commit_reversible_command ();
}
+void
+FadeInDrag::aborted ()
+{
+ for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
+
+ 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)
{
fade_length = region->last_frame() - pos;
}
- for (RegionSelection::iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
- AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
if (!tmp) {
continue;
_editor->begin_reversible_command (_("change fade out length"));
- for (RegionSelection::iterator i = _views.begin(); i != _views.end(); ++i) {
+ for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
- AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
if (!tmp) {
continue;
_editor->commit_reversible_command ();
}
+void
+FadeOutDrag::aborted ()
+{
+ for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
+ AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
+
+ 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)
{
break;
}
- /* set up copies for us to manipulate during the drag */
+ /* Set up copies for us to manipulate during the drag */
for (MarkerSelection::iterator i = _editor->selection->markers.begin(); i != _editor->selection->markers.end(); ++i) {
- Location *l = _editor->find_location_from_marker (*i, is_start);
+ Location* l = _editor->find_location_from_marker (*i, is_start);
_copied_locations.push_back (new Location (*l));
}
}
bool is_start;
bool move_both = false;
Marker* marker;
- Location *real_location;
+ Location *real_location;
Location *copy_location = 0;
nframes64_t const newframe = adjusted_current_frame (event);
if (copy_location->is_mark()) {
- /* just move it */
+ /* now move it */
copy_location->set_start (copy_location->start() + f_delta);
_line->hide();
}
+void
+MarkerDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
void
MarkerDrag::update_item (Location* location)
{
// the point doesn't 'jump' to the mouse after the first drag
_time_axis_view_grab_x = _point->get_x();
_time_axis_view_grab_y = _point->get_y();
- nframes64_t grab_frame = _editor->pixel_to_frame (_time_axis_view_grab_x);
float const fraction = 1 - (_point->get_y() / _point->line().height());
- _point->line().start_drag_single (_point, grab_frame, fraction);
+ _point->line().start_drag_single (_point, _time_axis_view_grab_x, fraction);
_editor->set_verbose_canvas_cursor (_point->line().get_verbose_cursor_string (fraction),
event->button.x + 10, event->button.y + 10);
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;
bool const push = Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier);
- _point->line().drag_motion (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));
}
/* just a click */
- if ((event->type == GDK_BUTTON_RELEASE) && (event->button.button == 1) && Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
_editor->reset_point_selection ();
}
_point->line().end_drag ();
}
+void
+ControlPointDrag::aborted ()
+{
+ _point->line().reset ();
+}
+
bool
ControlPointDrag::active (Editing::MouseMode m)
{
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;
push = true;
}
- /* we are ignoring x position for this drag, so we can just pass in 0 */
- _line->drag_motion (0, 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));
}
_line->end_drag ();
}
+void
+LineDrag::aborted ()
+{
+ _line->reset ();
+}
+
+FeatureLineDrag::FeatureLineDrag (Editor* e, ArdourCanvas::Item* i)
+ : Drag (e, i),
+ _line (0),
+ _cumulative_x_drag (0)
+{
+
+}
+void
+FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
+{
+
+ Drag::start_grab (event);
+
+ _line = reinterpret_cast<SimpleLine*> (_item);
+ assert (_line);
+
+ /* need to get x coordinate in terms of parent (AudioRegionView) origin. */
+
+ double cx = event->button.x;
+ double cy = event->button.y;
+
+ _item->property_parent().get_value()->w2i(cx, cy);
+
+ /* store grab start in parent frame */
+ _region_view_grab_x = cx;
+
+ _before = _line->property_x1();
+
+ _arv = reinterpret_cast<AudioRegionView*> (_item->get_data ("regionview"));
+
+ _max_x = _editor->frame_to_pixel(_arv->get_duration());
+}
+
+void
+FeatureLineDrag::motion (GdkEvent* event, bool)
+{
+ double dx = _drags->current_pointer_x() - last_pointer_x();
+
+ double cx = _region_view_grab_x + _cumulative_x_drag + dx;
+
+ _cumulative_x_drag += dx;
+
+ /* Clamp the min and max extent of the drag to keep it within the region view bounds */
+
+ if (cx > _max_x){
+ cx = _max_x;
+ }
+ else if(cx < 0){
+ cx = 0;
+ }
+
+ _line->property_x1() = cx;
+ _line->property_x2() = cx;
+
+ _before = _line->property_x1();
+}
+
+void
+FeatureLineDrag::finished (GdkEvent* event, bool)
+{
+ _arv = reinterpret_cast<AudioRegionView*> (_item->get_data ("regionview"));
+ _arv->update_transient(_before, _line->property_x1());
+}
+
+void
+FeatureLineDrag::aborted ()
+{
+ //_line->reset ();
+}
+
void
RubberbandSelectDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
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) (pf - grab_frame())) < 8) {
- return;
- }
-
nframes64_t grab = grab_frame ();
if (Config->get_rubberbanding_snaps_to_grid ()) {
_editor->snap_to_with_modifier (grab, event);
start = grab;
}
- if (current_pointer_y() < grab_y()) {
- y1 = current_pointer_y();
+ if (_drags->current_pointer_y() < grab_y()) {
+ y1 = _drags->current_pointer_y();
y2 = grab_y();
} else {
- y2 = current_pointer_y();
+ y2 = _drags->current_pointer_y();
y1 = grab_y();
}
motion (event, false);
double y1,y2;
- if (current_pointer_y() < grab_y()) {
- y1 = current_pointer_y();
+ if (_drags->current_pointer_y() < grab_y()) {
+ y1 = _drags->current_pointer_y();
y2 = grab_y();
} else {
- y2 = current_pointer_y();
+ y2 = _drags->current_pointer_y();
y1 = grab_y();
}
_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);
+ committed = _editor->select_all_within (grab_frame(), last_pointer_frame() - 1, y1, y2, _editor->track_views, op, false);
} 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, false);
}
if (!committed) {
_editor->rubberband_rect->hide();
}
+void
+RubberbandSelectDrag::aborted ()
+{
+ _editor->rubberband_rect->hide ();
+}
+
void
TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
nframes64_t const pf = adjusted_current_frame (event);
- if (pf == last_pointer_frame()) {
- return;
- }
-
if (pf > rv->region()->position()) {
rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf);
}
RegionSelection rs;
rs.add (_primary);
- if (!_editor->time_stretch (rs, percentage) == 0) {
+ if (_editor->time_stretch (rs, percentage) == -1) {
error << _("An error occurred while executing time stretch operation") << endmsg;
}
}
+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
}
}
+void
+ScrubDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
SelectionDrag::SelectionDrag (Editor* e, ArdourCanvas::Item* i, Operation o)
: Drag (e, i)
, _operation (o)
if (_editor->clicked_axisview) {
_editor->clicked_axisview->order_selection_trims (_item, true);
}
- Drag::start_grab (event, _editor->trimmer_cursor);
+ Drag::start_grab (event, _editor->left_side_trim_cursor);
start = _editor->selection->time[_editor->clicked_selection].start;
_pointer_frame_offset = grab_frame() - start;
break;
if (_editor->clicked_axisview) {
_editor->clicked_axisview->order_selection_trims (_item, false);
}
- Drag::start_grab (event, _editor->trimmer_cursor);
+ Drag::start_grab (event, _editor->right_side_trim_cursor);
end = _editor->selection->time[_editor->clicked_selection].end;
_pointer_frame_offset = grab_frame() - end;
break;
_editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
- _original_pointer_time_axis = _editor->trackview_by_y_position (current_pointer_y ()).first->order ();
+ _original_pointer_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()).first->order ();
}
void
nframes64_t end = 0;
nframes64_t length;
- pair<TimeAxisView*, int> const pending_time_axis = _editor->trackview_by_y_position (current_pointer_y ());
+ pair<TimeAxisView*, int> const pending_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ());
if (pending_time_axis.first == 0) {
return;
}
if (first_move) {
- _editor->begin_reversible_command (_("range selection"));
- _have_transaction = true;
-
if (_copy) {
/* adding to the selection */
_editor->selection->add (_editor->clicked_axisview);
} else {
/* new selection */
- if (!_editor->selection->selected (_editor->clicked_axisview)) {
+ if (_editor->clicked_axisview && !_editor->selection->selected (_editor->clicked_axisview)) {
_editor->selection->set (_editor->clicked_axisview);
}
case SelectionStartTrim:
- if (first_move) {
- _editor->begin_reversible_command (_("trim selection start"));
- _have_transaction = true;
- }
-
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;
break;
}
- if (event->button.x >= _editor->horizontal_adjustment.get_value() + _editor->_canvas_width) {
+ if (event->button.x >= _editor->horizontal_position() + _editor->_canvas_width) {
_editor->start_canvas_autoscroll (1, 0);
}
_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);
_editor->selection->clear_time();
}
- if (!_editor->selection->selected (_editor->clicked_axisview)) {
+ if (_editor->clicked_axisview && !_editor->selection->selected (_editor->clicked_axisview)) {
_editor->selection->set (_editor->clicked_axisview);
}
_editor->stop_canvas_autoscroll ();
}
+void
+SelectionDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
RangeMarkerBarDrag::RangeMarkerBarDrag (Editor* e, ArdourCanvas::Item* i, Operation o)
: Drag (e, i),
_operation (o),
Gdk::Cursor* cursor = 0;
if (!_editor->temp_location) {
- _editor->temp_location = new Location;
+ _editor->temp_location = new Location (*_editor->session());
}
switch (_operation) {
nframes64_t const pf = adjusted_current_frame (event);
- /* only alter selection if the current frame is
- different from the last frame position.
- */
-
- if (pf == last_pointer_frame()) {
- return;
- }
-
if (_operation == CreateRangeMarker || _operation == CreateTransportMarker || _operation == CreateCDMarker) {
nframes64_t grab = grab_frame ();
_editor->snap_to (grab);
}
}
- if (event->button.x >= _editor->horizontal_adjustment.get_value() + _editor->_canvas_width) {
+ if (event->button.x >= _editor->horizontal_position() + _editor->_canvas_width) {
_editor->start_canvas_autoscroll (1, 0);
}
flags = Location::IsRangeMarker;
_editor->range_bar_drag_rect->hide();
}
- newloc = new Location(_editor->temp_location->start(), _editor->temp_location->end(), rangename, (Location::Flags) flags);
+ newloc = new Location (
+ *_editor->session(), _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));
switch (_editor->mouse_mode) {
case MouseObject:
/* find the two markers on either side and then make the selection from it */
- _editor->select_all_within (start, end, 0.0f, FLT_MAX, _editor->track_views, Selection::Set);
+ _editor->select_all_within (start, end, 0.0f, FLT_MAX, _editor->track_views, Selection::Set, false);
break;
case MouseRange:
_editor->stop_canvas_autoscroll ();
}
-
+void
+RangeMarkerBarDrag::aborted ()
+{
+ /* XXX: TODO */
+}
void
RangeMarkerBarDrag::update_item (Location* location)
nframes64_t const pf = adjusted_current_frame (event);
- if (pf == last_pointer_frame()) {
- return;
- }
-
nframes64_t grab = grab_frame ();
_editor->snap_to_with_modifier (grab, event);
_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);
}
if (dx || dy) {
+
+ CanvasNoteEvent* cnote = dynamic_cast<CanvasNoteEvent*>(_item);
+ Evoral::MusicalTime new_time;
+
+ if (drag_delta_x) {
+ nframes64_t start_frames = region->beats_to_frames(cnote->note()->time());
+ if (drag_delta_x >= 0) {
+ start_frames += region->snap_frame_to_frame(_editor->pixel_to_frame(drag_delta_x));
+ } else {
+ start_frames -= region->snap_frame_to_frame(_editor->pixel_to_frame(-drag_delta_x));
+ }
+ new_time = region->frames_to_beats(start_frames);
+ } else {
+ new_time = cnote->note()->time();
+ }
+
+ boost::shared_ptr<Evoral::Note<Evoral::MusicalTime> > check_note (
+ new Evoral::Note<Evoral::MusicalTime> (cnote->note()->channel(),
+ new_time,
+ cnote->note()->length(),
+ cnote->note()->note() + drag_delta_note,
+ cnote->note()->velocity()));
+
region->move_selection (dx, dy);
- CanvasNoteEvent* cnote = dynamic_cast<CanvasNoteEvent*>(_item);
- char buf[4];
- snprintf (buf, sizeof (buf), "%g", (int) cnote->note()->note() + drag_delta_note);
- //editor.show_verbose_canvas_cursor_with (Evoral::midi_note_name (ev->note()->note()));
+ char buf[12];
+ snprintf (buf, sizeof (buf), "%s (%d)", Evoral::midi_note_name (cnote->note()->note() + drag_delta_note).c_str(),
+ (int) floor ((cnote->note()->note() + drag_delta_note)));
_editor->show_verbose_canvas_cursor_with (buf);
}
}
}
}
+void
+NoteDrag::aborted ()
+{
+ /* XXX: TODO */
+}
+
AutomationRangeDrag::AutomationRangeDrag (Editor* e, ArdourCanvas::Item* i, list<AudioRange> const & r)
: Drag (e, i)
, _ranges (r)
}
uint32_t const N = _line->npoints ();
- AutomationList::const_iterator j = the_list->begin ();
for (uint32_t i = 0; i < N; ++i) {
ControlPoint* p = _line->nth (i);
- list<AudioRange>::const_iterator k = _ranges.begin ();
- while (k != _ranges.end() && (k->start >= (*j)->when || k->end <= (*j)->when)) {
- ++k;
+ list<AudioRange>::const_iterator j = _ranges.begin ();
+ while (j != _ranges.end() && (j->start >= (*p->model())->when || j->end <= (*p->model())->when)) {
+ ++j;
}
- if (k != _ranges.end()) {
+ if (j != _ranges.end()) {
points.push_back (p);
}
-
- ++j;
}
}
return;
}
- _line->start_drag_multiple (points, 1 - (current_pointer_y() / _line->height ()), state);
+ _line->start_drag_multiple (points, 1 - (_drags->current_pointer_y() / _line->height ()), state);
}
void
return;
}
- float const f = 1 - (current_pointer_y() / _line->height());
+ float const f = 1 - (_drags->current_pointer_y() / _line->height());
- /* we are ignoring x position for this drag, so we can just pass in 0 */
- _line->drag_motion (0, f, false);
+ /* we are ignoring x position for this drag, so we can just pass in anything */
+ _line->drag_motion (0, f, true, false);
}
void
_line->end_drag ();
_line->clear_always_in_view ();
}
+
+void
+AutomationRangeDrag::aborted ()
+{
+ _line->clear_always_in_view ();
+ _line->reset ();
+}
+
+DraggingView::DraggingView (RegionView* v)
+ : view (v)
+{
+ initial_y = v->get_canvas_group()->property_y ();
+}