*/
+#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"
#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;
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)
+ , _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);
+ *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;
}
}
-/** @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* 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 ());
+ _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 (sigc::mem_fun (*this, &RegionDrag::region_going_away));
+ 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)
{
}
/* 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;
}
}
- 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;
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()) {
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);
{
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)
_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)
{
};
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)
}
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);
+ if (grab_x() <= middle_point) {
+ 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);
+ 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);
- 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;
+ Drag::start_grab (event, _editor->trimmer_cursor);
} 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)) {
+ 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) {
_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;
}
}
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
+ its current state has to be passed to the
various trim functions in order to work properly
*/
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
if (tv && tv->is_track()) {
- speed = tv->get_diskstream()->speed();
+ speed = tv->track()->speed();
}
- if (_last_pointer_frame > _current_pointer_frame) {
- left_direction = true;
- } else {
- left_direction = false;
- }
-
- _editor->snap_to_with_modifier (_current_pointer_frame, event);
+ nframes64_t const pf = adjusted_current_frame (event);
if (first_move) {
_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 (_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);
- } else {
- frame_delta = (_current_pointer_frame - _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)) {
- 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) && (_current_pointer_frame > (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->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;
}
_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 ();
}
}
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);
+ nframes64_t const pf = adjusted_current_frame (event);
- if (adjusted_frame == _last_pointer_frame) {
- return;
- }
-
- _marker->set_position (adjusted_frame);
-
- _last_pointer_frame = adjusted_frame;
-
- _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 ();
- }
+ 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);
}
{
nframes64_t const adjusted_frame = adjusted_current_frame (event);
- if (adjusted_frame == _last_pointer_frame) {
+ if (adjusted_frame == last_pointer_frame()) {
return;
}
_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
_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);
+ 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)
{
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);
+
}
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;
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 (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)
{
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);
}
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;
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 (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)
{
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) {
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);
nframes64_t next = newframe;
- if (_current_pointer_frame == _last_pointer_frame) {
+ if (newframe == last_pointer_frame()) {
return;
}
if (copy_location->is_mark()) {
- /* just move it */
+ /* now move it */
copy_location->set_start (copy_location->start() + f_delta);
}
}
- _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));
}
/* 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 ();
}
} 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 ();
+}
+
+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 *)
{
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, 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 *)
{
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();
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
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->left_side_trim_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->right_side_trim_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->clicked_axisview && !_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;
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->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->clicked_axisview && !_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;
}
Gdk::Cursor* cursor = 0;
if (!_editor->temp_location) {
- _editor->temp_location = new Location;
+ _editor->temp_location = new Location (*_editor->session());
}
switch (_operation) {
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);
-
- /* 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);
- }
+ nframes64_t const pf = adjusted_current_frame (event);
- 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) {
+ if (event->button.x >= _editor->horizontal_position() + _editor->_canvas_width) {
_editor->start_canvas_autoscroll (1, 0);
}
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();
flags = Location::IsRangeMarker;
_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));
+ 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));
_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 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:
/* 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);
-
- if (first_move) {
- _editor->snap_to_with_modifier (_grab_frame, event);
- }
+ nframes64_t const pf = adjusted_current_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);
}
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);
}
}
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 ();
+}
+
+DraggingView::DraggingView (RegionView* v)
+ : view (v)
+{
+ initial_y = v->get_canvas_group()->property_y ();
+}