#include "ardour/session.h"
#include "ardour/dB.h"
#include "ardour/region_factory.h"
+#include "ardour/operations.h"
+
#include "editor.h"
#include "i18n.h"
#include "keyboard.h"
#include "midi_selection.h"
#include "automation_time_axis.h"
#include "debug.h"
+#include "editor_cursors.h"
+#include "mouse_cursors.h"
+#include "verbose_cursor.h"
using namespace std;
using namespace ARDOUR;
using Gtkmm2ext::Keyboard;
-double const ControlPointDrag::_zero_gain_fraction = gain_to_slider_position (dB_to_coefficient (0.0));
+double ControlPointDrag::_zero_gain_fraction = -1.0;
DragManager::DragManager (Editor* e)
: _editor (e)
, _ending (false)
, _current_pointer_frame (0)
{
-
}
DragManager::~DragManager ()
DragManager::abort ()
{
_ending = true;
-
+
for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
(*i)->abort ();
delete *i;
}
+ if (!_drags.empty ()) {
+ _editor->set_follow_playhead (_old_follow_playhead, false);
+ }
+
_drags.clear ();
_ending = false;
void
DragManager::start_grab (GdkEvent* e, Gdk::Cursor* c)
{
+ /* Prevent follow playhead during the drag to be nice to the user */
+ _old_follow_playhead = _editor->follow_playhead ();
+ _editor->set_follow_playhead (false);
+
_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, c);
}
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);
_drags.clear ();
_ending = false;
-
+
+ _editor->set_follow_playhead (_old_follow_playhead, false);
+
return r;
}
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;
return j != _drags.end ();
}
-Drag::Drag (Editor* e, ArdourCanvas::Item* i)
+Drag::Drag (Editor* e, ArdourCanvas::Item* i)
: _editor (e)
, _item (i)
, _pointer_frame_offset (0)
}
_raw_grab_frame = _editor->event_frame (event, &_grab_x, &_grab_y);
+ setup_pointer_frame_offset ();
_grab_frame = adjusted_frame (_raw_grab_frame, event);
_last_pointer_frame = _grab_frame;
_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;
finished (event, _move_threshold_passed);
- _editor->hide_verbose_canvas_cursor();
+ _editor->verbose_cursor()->hide ();
return _move_threshold_passed;
}
Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
{
/* 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 ()) ) {
+ if (_move_threshold_passed &&
+ (!x_movement_matters() || _last_pointer_frame == adjusted_current_frame (event)) &&
+ (!y_movement_matters() || _last_pointer_y == _drags->current_pointer_y ()) ) {
return false;
}
if (!from_autoscroll && !_move_threshold_passed) {
- bool const xp = (::llabs (adjusted_current_frame (event) - _grab_frame) >= threshold.first);
+ bool const xp = (::llabs (_drags->current_pointer_frame () - _raw_grab_frame) >= threshold.first);
bool const yp = (::fabs ((_drags->current_pointer_y () - _grab_y)) >= threshold.second);
_move_threshold_passed = ((xp && x_movement_matters()) || (yp && y_movement_matters()));
_last_pointer_x = _drags->current_pointer_x ();
_last_pointer_y = _drags->current_pointer_y ();
_last_pointer_frame = adjusted_current_frame (event);
-
+
return true;
}
}
_item->ungrab (0);
}
- aborted ();
+ aborted (_move_threshold_passed);
_editor->stop_canvas_autoscroll ();
- _editor->hide_verbose_canvas_cursor ();
+ _editor->verbose_cursor()->hide ();
}
+void
+Drag::show_verbose_cursor_time (framepos_t frame)
+{
+ _editor->verbose_cursor()->set_time (
+ frame,
+ _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
+ _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize
+ );
+
+ _editor->verbose_cursor()->show ();
+}
+
+void
+Drag::show_verbose_cursor_duration (framepos_t start, framepos_t end, double xoffset)
+{
+ _editor->verbose_cursor()->show (xoffset);
+
+ _editor->verbose_cursor()->set_duration (
+ start, end,
+ _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
+ _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize
+ );
+}
+
+void
+Drag::show_verbose_cursor_text (string const & text)
+{
+ _editor->verbose_cursor()->show ();
+
+ _editor->verbose_cursor()->set (
+ text,
+ _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
+ _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value() + _editor->canvas_timebars_vsize
+ );
+}
+
+
struct EditorOrderTimeAxisViewSorter {
bool operator() (TimeAxisView* a, TimeAxisView* b) {
RouteTimeAxisView* ra = dynamic_cast<RouteTimeAxisView*> (a);
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
if (!(*i)->hidden()) {
-
+
_time_axis_views.push_back (*i);
TimeAxisView::Children children_list = (*i)->get_child_list ();
}
}
- /* the list of views can be empty at this point if this is a region list-insert drag
- */
-
+ /* the list of views can be empty at this point if this is a region list-insert drag
+ */
+
for (list<RegionView*>::const_iterator i = v.begin(); i != v.end(); ++i) {
_views.push_back (DraggingView (*i, this));
}
-
+
RegionView::RegionViewGoingAway.connect (death_connection, invalidator (*this), ui_bind (&RegionDrag::region_going_away, this, _1), gui_context());
}
if (i == N) {
return -1;
}
-
+
return i;
}
{
Drag::start_grab (event, cursor);
- _editor->show_verbose_time_cursor (_last_frame_position, 10);
+ show_verbose_cursor_time (_last_frame_position);
pair<TimeAxisView*, int> const tv = _editor->trackview_by_y_position (_drags->current_pointer_y ());
_last_pointer_time_axis_view = find_time_axis_view (tv.first);
framepos_t sync_frame;
framecnt_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 != _last_frame_position) && x_move_allowed) {
- /* x movement since last time */
+ /* x movement since last time (in pixels) */
dx = (static_cast<double> (*pending_region_position) - _last_frame_position) / _editor->frames_per_unit;
/* total x movement */
framecnt_t total_dx = *pending_region_position;
if (regions_came_from_canvas()) {
- total_dx = total_dx - grab_frame () + _pointer_frame_offset;
+ total_dx = total_dx - grab_frame ();
}
/* check that no regions have gone off the start of the session */
/* not a track, or the wrong type */
return false;
}
-
+
int const l = i->layer + delta_layer;
if (delta_track == 0 && (l < 0 || l >= int (to->view()->layers()))) {
/* Off the top or bottom layer; note that we only refuse if the track hasn't changed.
/* Bail early if we're not over a track */
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv.first);
if (!rtv || !rtv->is_track()) {
- _editor->hide_verbose_canvas_cursor ();
+ _editor->verbose_cursor()->hide ();
return;
}
/* here we are calculating the y distance from the
top of the first track view to the top of the region
area of the track view that we're working on */
-
+
/* this x value is just a dummy value so that we have something
to pass to i2w () */
-
+
double ix1 = 0;
-
+
/* distance from the top of this track view to the region area
of our track view is always 1 */
-
+
double iy1 = 1;
-
+
/* convert to world coordinates, ie distance from the top of
the ruler section */
-
+
rv->get_canvas_frame()->i2w (ix1, iy1);
-
+
/* compensate for the ruler section and the vertical scrollbar position */
iy1 += _editor->get_trackview_group_vertical_offset ();
-
+
// hide any dependent views
-
+
rv->get_time_axis_view().hide_dependent_views (*rv);
-
+
/*
reparent to a non scrolling group so that we can keep the
region selection above all time axis views.
reparenting means we have to move the rv as the two
parent groups have different coordinates.
*/
-
+
rv->get_canvas_group()->property_y() = iy1 - 1;
rv->get_canvas_group()->reparent (*(_editor->_region_motion_group));
-
+
rv->fake_set_opaque (true);
}
} /* foreach region */
_total_x_delta += x_delta;
-
+
if (first_move) {
_editor->cursor_group->raise_to_top();
}
if (x_delta != 0 && !_brushing) {
- _editor->show_verbose_time_cursor (_last_frame_position, 10);
+ show_verbose_cursor_time (_last_frame_position);
}
_last_pointer_time_axis_view += delta_time_axis_view;
list<DraggingView> new_regionviews;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++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, true);
- region_copy->set_position (original->position(), this);
-
+ region_copy->set_position (original->position());
+
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
} else {
continue;
}
-
+
nrv->get_canvas_group()->show ();
new_regionviews.push_back (DraggingView (nrv, this));
-
+
/* swap _primary to the copy */
-
+
if (rv == _primary) {
_primary = nrv;
}
-
+
/* ..and deselect the one we copied */
-
+
rv->set_selected (false);
}
-
+
if (!new_regionviews.empty()) {
-
+
/* reflect the fact that we are dragging the copies */
-
+
_views = new_regionviews;
-
+
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
framecnt_t const drag_delta = _primary->region()->position() - _last_frame_position;
_editor->update_canvas_now ();
-
+
if (_copy) {
-
+
finished_copy (
changed_position,
changed_tracks,
drag_delta
);
-
+
} else {
-
+
finished_no_copy (
changed_position,
changed_tracks,
drag_delta
);
-
+
}
}
}
if (_x_constrained) {
- _editor->begin_reversible_command (_("fixed time region copy"));
+ _editor->begin_reversible_command (Operations::fixed_time_region_copy);
} else {
- _editor->begin_reversible_command (_("region copy"));
+ _editor->begin_reversible_command (Operations::region_copy);
}
/* insert the regions into their new playlists */
RegionView* new_view = insert_region_into_playlist (
i->view->region(), dynamic_cast<RouteTimeAxisView*> (_time_axis_views[i->time_axis_view]), i->layer, where, modified_playlists
);
-
+
if (new_view == 0) {
continue;
}
new_views.push_back (new_view);
-
+
/* we don't need the copied RegionView any more */
views_to_delete.push_back (i->view);
}
delete *i;
}
- /* 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 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) {
if (_x_constrained) {
_editor->begin_reversible_command (_("fixed time region drag"));
} else {
- _editor->begin_reversible_command (_("region drag"));
+ _editor->begin_reversible_command (Operations::region_drag);
}
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ) {
remove_region_from_playlist (rv->region(), i->initial_playlist, modified_playlists);
} else {
-
+
rv->region()->clear_changes ();
/*
/* 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 */
pair<PlaylistSet::iterator, bool> r = frozen_playlists.insert (playlist);
/* this movement may result in a crossfade being modified, so we need to get undo
data from the playlist as well as the region.
*/
-
+
r = modified_playlists.insert (playlist);
if (r.second) {
playlist->clear_changes ();
}
- rv->region()->set_position (where, (void*) this);
+ rv->region()->set_position (where);
_editor->session()->add_command (new StatefulDiffCommand (rv->region()));
}
if (changed_tracks) {
-
+
/* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
was selected in all of them, then removing it from a playlist will have removed all
trace of it from _views (i.e. there were N regions selected, we removed 1,
we can just iterate.
*/
-
+
if (_views.empty()) {
- break;
+ break;
} else {
i = _views.begin();
}
}
}
- /* 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 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) {
playlist->remove_region (region);
}
-
+
/** Insert a region into a playlist, handling the recovery of the resulting new RegionView, and
* clearing the playlist's diff history first if necessary.
* @param dest_layer Destination layer.
* @param where Destination position.
* @param modified_playlists The playlist will be added to this if it is not there already; used to ensure
- * that clear_changes () is only called once per playlist.
+ * that clear_changes () is only called once per playlist.
* @return New RegionView, or 0 if no insert was performed.
*/
RegionView *
_new_region_view = 0;
sigc::connection c = dest_rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &RegionMoveDrag::collect_new_region_view));
- /* clear history for the playlist we are about to insert to, provided we haven't already done so */
+ /* clear history for the playlist we are about to insert to, provided we haven't already done so */
pair<PlaylistSet::iterator, bool> r = modified_playlists.insert (dest_playlist);
if (r.second) {
dest_playlist->clear_changes ();
for (PlaylistSet::const_iterator i = playlists.begin(); i != playlists.end(); ++i) {
StatefulDiffCommand* c = new StatefulDiffCommand (*i);
if (!c->empty()) {
- _editor->session()->add_command (new StatefulDiffCommand (*i));
+ _editor->session()->add_command (c);
} else {
delete c;
}
void
-RegionMoveDrag::aborted ()
+RegionMoveDrag::aborted (bool movement_occurred)
{
if (_copy) {
_views.clear ();
} else {
- RegionMotionDrag::aborted ();
+ RegionMotionDrag::aborted (movement_occurred);
}
}
void
-RegionMotionDrag::aborted ()
+RegionMotionDrag::aborted (bool)
{
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
RegionView* rv = i->view;
_editor->update_canvas_now ();
}
-
+
+/** @param b true to brush, otherwise false.
+ * @param c true to make copies of the regions being moved, otherwise false.
+ */
RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b, bool c)
: RegionMotionDrag (e, i, p, v, b),
_copy (c)
{
DEBUG_TRACE (DEBUG::Drags, "New RegionMoveDrag\n");
-
+
double speed = 1;
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&_primary->get_time_axis_view ());
if (rtv && rtv->is_track()) {
}
void
-RegionMoveDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
+RegionMoveDrag::setup_pointer_frame_offset ()
{
- RegionMotionDrag::start_grab (event, c);
-
_pointer_frame_offset = raw_grab_frame() - _last_frame_position;
}
: RegionMotionDrag (e, 0, 0, list<RegionView*> (), false)
{
DEBUG_TRACE (DEBUG::Drags, "New RegionInsertDrag\n");
-
+
assert ((boost::dynamic_pointer_cast<AudioRegion> (r) && dynamic_cast<AudioTimeAxisView*> (v)) ||
(boost::dynamic_pointer_cast<MidiRegion> (r) && dynamic_cast<MidiTimeAxisView*> (v)));
boost::shared_ptr<Playlist> playlist = dest_rtv->playlist();
- _editor->begin_reversible_command (_("insert region"));
- playlist->clear_changes ();
+ _editor->begin_reversible_command (Operations::insert_region);
+ playlist->clear_changes ();
playlist->add_region (_primary->region (), _last_frame_position);
_editor->session()->add_command (new StatefulDiffCommand (playlist));
_editor->commit_reversible_command ();
}
void
-RegionInsertDrag::aborted ()
+RegionInsertDrag::aborted (bool)
{
delete _primary;
_primary = 0;
pair<TimeAxisView*, int> const tvp = _editor->trackview_by_y_position (_drags->current_pointer_y ());
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
- layer_t layer = tvp.second;
-
- if (tv && tv->layer_display() == Overlaid) {
- layer = 0;
- }
/* The region motion is only processed if the pointer is over
an audio track.
/* To make sure we hide the verbose canvas cursor when the mouse is
not held over and audiotrack.
*/
- _editor->hide_verbose_canvas_cursor ();
+ _editor->verbose_cursor()->hide ();
return;
}
}
void
-RegionSpliceDrag::aborted ()
+RegionSpliceDrag::aborted (bool)
{
/* XXX: TODO */
}
_view (dynamic_cast<MidiTimeAxisView*> (v))
{
DEBUG_TRACE (DEBUG::Drags, "New RegionCreateDrag\n");
-
+
assert (_view);
}
RegionCreateDrag::motion (GdkEvent* event, bool first_move)
{
if (first_move) {
- add_region();
+ add_region();
+ _view->playlist()->freeze ();
} else {
- if (_region) {
- framepos_t const f = adjusted_current_frame (event);
- if (f < grab_frame()) {
- _region->set_position (f, this);
- }
-
- /* again, don't use a zero-length region (see above) */
- framecnt_t const len = abs (f - grab_frame ());
- _region->set_length (len < 1 ? 1 : len, this);
- }
- }
+ if (_region) {
+ framepos_t const f = adjusted_current_frame (event);
+ if (f < grab_frame()) {
+ _region->set_position (f);
+ }
+
+ /* Don't use a zero-length region, and subtract 1 frame from the snapped length
+ so that if this region is duplicated, its duplicate starts on
+ a snap point rather than 1 frame after a snap point. Otherwise things get
+ a bit confusing as if a region starts 1 frame after a snap point, one cannot
+ place snapped notes at the start of the region.
+ */
+
+ framecnt_t const len = abs (f - grab_frame () - 1);
+ _region->set_length (len < 1 ? 1 : len);
+ }
+ }
}
void
RegionCreateDrag::finished (GdkEvent*, bool movement_occurred)
{
if (!movement_occurred) {
- add_region ();
+ add_region ();
+ } else {
+ _view->playlist()->thaw ();
}
- if (_region) {
- _editor->commit_reversible_command ();
- }
+ if (_region) {
+ _editor->commit_reversible_command ();
+ }
}
void
RegionCreateDrag::add_region ()
{
- if (_editor->session()) {
- const TempoMap& map (_editor->session()->tempo_map());
- framecnt_t pos = grab_frame();
- const Meter& m = map.meter_at (pos);
- /* not that the frame rate used here can be affected by pull up/down which
- might be wrong.
- */
- framecnt_t len = m.frames_per_bar (map.tempo_at (pos), _editor->session()->frame_rate());
- _region = _view->add_region (grab_frame(), len, false);
- }
+ if (_editor->session()) {
+ const TempoMap& map (_editor->session()->tempo_map());
+ framecnt_t pos = grab_frame();
+ const Meter& m = map.meter_at (pos);
+ /* not that the frame rate used here can be affected by pull up/down which
+ might be wrong.
+ */
+ framecnt_t len = m.frames_per_bar (map.tempo_at (pos), _editor->session()->frame_rate());
+ _region = _view->add_region (grab_frame(), len, false);
+ }
}
void
-RegionCreateDrag::aborted ()
+RegionCreateDrag::aborted (bool)
{
+ if (_region) {
+ _view->playlist()->thaw ();
+ }
+
/* XXX */
}
NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
{
Gdk::Cursor* cursor;
- ArdourCanvas::CanvasNote* cnote = dynamic_cast<ArdourCanvas::CanvasNote*>(_item);
- float x_fraction = cnote->mouse_x_fraction ();
+ ArdourCanvas::CanvasNoteEvent* cnote = dynamic_cast<ArdourCanvas::CanvasNoteEvent*>(_item);
+ float x_fraction = cnote->mouse_x_fraction ();
- if (x_fraction > 0.0 && x_fraction < 0.25) {
- cursor = _editor->left_side_trim_cursor;
- } else {
- cursor = _editor->right_side_trim_cursor;
- }
+ if (x_fraction > 0.0 && x_fraction < 0.25) {
+ cursor = _editor->cursors()->left_side_trim;
+ } else {
+ cursor = _editor->cursors()->right_side_trim;
+ }
Drag::start_grab (event, cursor);
double const middle_point = region_start + cnote->x1() + (cnote->x2() - cnote->x1()) / 2.0L;
if (grab_x() <= middle_point) {
- cursor = _editor->left_side_trim_cursor;
+ cursor = _editor->cursors()->left_side_trim;
at_front = true;
} else {
- cursor = _editor->right_side_trim_cursor;
+ cursor = _editor->cursors()->right_side_trim;
at_front = false;
}
{
MidiRegionSelection& ms (_editor->get_selection().midi_regions);
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
- (*r)->update_resizing (dynamic_cast<ArdourCanvas::CanvasNote*>(_item), at_front, _drags->current_pointer_x() - grab_x(), relative);
+ (*r)->update_resizing (dynamic_cast<ArdourCanvas::CanvasNoteEvent*>(_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 (dynamic_cast<ArdourCanvas::CanvasNote*>(_item), at_front, _drags->current_pointer_x() - grab_x(), relative);
+ (*r)->commit_resizing (dynamic_cast<ArdourCanvas::CanvasNoteEvent*>(_item), at_front, _drags->current_pointer_x() - grab_x(), relative);
}
}
void
-NoteResizeDrag::aborted ()
+NoteResizeDrag::aborted (bool)
{
/* XXX: TODO */
}
}
void
-RegionGainDrag::aborted ()
+RegionGainDrag::aborted (bool)
{
/* XXX: TODO */
}
TrimDrag::TrimDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionDrag (e, i, p, v)
- , _have_transaction (false)
{
DEBUG_TRACE (DEBUG::Drags, "New TrimDrag\n");
}
framepos_t const pf = adjusted_current_frame (event);
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
+ /* Move the contents of the region around without changing the region bounds */
_operation = ContentsTrim;
- Drag::start_grab (event, _editor->trimmer_cursor);
+ Drag::start_grab (event, _editor->cursors()->trimmer);
} else {
/* These will get overridden for a point trim.*/
if (pf < (region_start + region_length/2)) {
- /* closer to start */
+ /* closer to front */
_operation = StartTrim;
- Drag::start_grab (event, _editor->left_side_trim_cursor);
+ Drag::start_grab (event, _editor->cursors()->left_side_trim);
} else {
/* closer to end */
_operation = EndTrim;
- Drag::start_grab (event, _editor->right_side_trim_cursor);
- }
+ Drag::start_grab (event, _editor->cursors()->right_side_trim);
+ }
}
switch (_operation) {
case StartTrim:
- _editor->show_verbose_time_cursor (region_start, 10);
+ show_verbose_cursor_time (region_start);
+ for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
+ i->view->trim_front_starting ();
+ }
break;
case EndTrim:
- _editor->show_verbose_time_cursor (region_end, 10);
+ show_verbose_cursor_time (region_end);
break;
case ContentsTrim:
- _editor->show_verbose_time_cursor (pf, 10);
+ show_verbose_cursor_time (pf);
break;
}
speed = tv->track()->speed();
}
- framecnt_t const dt = adjusted_current_frame (event) - grab_frame ();
+ framecnt_t const dt = adjusted_current_frame (event) - raw_grab_frame () + _pointer_frame_offset;
if (first_move) {
}
_editor->begin_reversible_command (trim_type);
- _have_transaction = true;
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_changes ();
+ rv->region()->playlist()->clear_owned_changes ();
AudioRegionView* const arv = dynamic_cast<AudioRegionView*> (rv);
switch (_operation) {
case StartTrim:
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- i->view->trim_start (i->initial_position + dt, non_overlap_trim);
+ i->view->trim_front (i->initial_position + dt, non_overlap_trim);
}
break;
}
framecnt_t frame_delta = 0;
-
+
bool left_direction = false;
if (last_pointer_frame() > adjusted_current_frame(event)) {
left_direction = true;
switch (_operation) {
case StartTrim:
- _editor->show_verbose_time_cursor ((framepos_t) (rv->region()->position() / speed), 10);
+ show_verbose_cursor_time ((framepos_t) (rv->region()->position() / speed));
break;
case EndTrim:
- _editor->show_verbose_time_cursor ((framepos_t) (rv->region()->last_frame() / speed), 10);
+ show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed));
break;
case ContentsTrim:
- _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+ show_verbose_cursor_time (adjusted_current_frame (event));
break;
}
}
if (movement_occurred) {
motion (event, false);
+ /* This must happen before the region's StatefulDiffCommand is created, as it may
+ `correct' (ahem) the region's _start from being negative to being zero. It
+ needs to be zero in the undo record.
+ */
+ if (_operation == StartTrim) {
+ for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ i->view->trim_front_ending ();
+ }
+ }
+
if (!_editor->selection->selected (_primary)) {
_primary->thaw_after_trim ();
} else {
+ set<boost::shared_ptr<Playlist> > diffed_playlists;
+
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
- i->view->thaw_after_trim ();
+ i->view->thaw_after_trim ();
i->view->enable_display (true);
i->view->fake_set_opaque (true);
- if (_have_transaction) {
- _editor->session()->add_command (new StatefulDiffCommand (i->view->region()));
- }
+
+ /* Trimming one region may affect others on the playlist, so we need
+ to get undo Commands from the whole playlist rather than just the
+ region. Use diffed_playlists to make sure we don't diff a given
+ playlist more than once.
+ */
+ boost::shared_ptr<Playlist> p = i->view->region()->playlist ();
+ if (diffed_playlists.find (p) == diffed_playlists.end()) {
+ vector<Command*> cmds;
+ p->rdiff (cmds);
+ _editor->session()->add_commands (cmds);
+ diffed_playlists.insert (p);
+ }
}
}
for (set<boost::shared_ptr<Playlist> >::iterator p = _editor->motion_frozen_playlists.begin(); p != _editor->motion_frozen_playlists.end(); ++p) {
}
_editor->motion_frozen_playlists.clear ();
-
- if (_have_transaction) {
- _editor->commit_reversible_command();
- }
+ _editor->commit_reversible_command();
} else {
/* no mouse movement */
}
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
+ if (_operation == StartTrim) {
+ i->view->trim_front_ending ();
+ }
+
i->view->region()->resume_property_changes ();
}
}
void
-TrimDrag::aborted ()
+TrimDrag::aborted (bool movement_occurred)
{
/* Our motion method is changing model state, so use the Undo system
to cancel. Perhaps not ideal, as this will leave an Undo point
*/
finished (0, true);
-
- if (_have_transaction) {
+
+ if (movement_occurred) {
_editor->undo ();
}
}
}
+void
+TrimDrag::setup_pointer_frame_offset ()
+{
+ list<DraggingView>::iterator i = _views.begin ();
+ while (i != _views.end() && i->view != _primary) {
+ ++i;
+ }
+
+ if (i == _views.end()) {
+ return;
+ }
+
+ switch (_operation) {
+ case StartTrim:
+ _pointer_frame_offset = raw_grab_frame() - i->initial_position;
+ break;
+ case EndTrim:
+ _pointer_frame_offset = raw_grab_frame() - i->initial_end;
+ break;
+ case ContentsTrim:
+ break;
+ }
+}
+
MeterMarkerDrag::MeterMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
: Drag (e, i),
_copy (c)
{
DEBUG_TRACE (DEBUG::Drags, "New MeterMarkerDrag\n");
-
+
_marker = reinterpret_cast<MeterMarker*> (_item->get_data ("marker"));
assert (_marker);
}
MeterMarker* new_marker = new MeterMarker (
*_editor,
*_editor->meter_group,
- *_editor->cursor_group,
ARDOUR_UI::config()->canvasvar_MeterMarker.get(),
name,
*new MeterSection (_marker->meter())
Drag::start_grab (event, cursor);
- _pointer_frame_offset = raw_grab_frame() - _marker->meter().frame();
+ show_verbose_cursor_time (adjusted_current_frame(event));
+}
- _editor->show_verbose_time_cursor (adjusted_current_frame(event), 10);
+void
+MeterMarkerDrag::setup_pointer_frame_offset ()
+{
+ _pointer_frame_offset = raw_grab_frame() - _marker->meter().frame();
}
void
framepos_t const pf = adjusted_current_frame (event);
_marker->set_position (pf);
-
- _editor->show_verbose_time_cursor (pf, 10);
+
+ show_verbose_cursor_time (pf);
}
void
motion (event, false);
- BBT_Time when;
+ Timecode::BBT_Time when;
TempoMap& map (_editor->session()->tempo_map());
map.bbt_time (last_pointer_frame(), when);
}
void
-MeterMarkerDrag::aborted ()
+MeterMarkerDrag::aborted (bool)
{
_marker->set_position (_marker->meter().frame ());
}
_copy (c)
{
DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n");
-
+
_marker = reinterpret_cast<TempoMarker*> (_item->get_data ("marker"));
assert (_marker);
}
void
TempoMarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{
-
if (_copy) {
// create a dummy marker for visual representation of moving the copy.
TempoMarker* new_marker = new TempoMarker (
*_editor,
*_editor->tempo_group,
- *_editor->cursor_group,
ARDOUR_UI::config()->canvasvar_TempoMarker.get(),
name,
*new TempoSection (_marker->tempo())
_item = &new_marker->the_item ();
_marker = new_marker;
- } else {
-
- MetricSection& section (_marker->tempo());
-
- if (!section.movable()) {
- return;
- }
}
Drag::start_grab (event, cursor);
+ show_verbose_cursor_time (adjusted_current_frame (event));
+}
+
+void
+TempoMarkerDrag::setup_pointer_frame_offset ()
+{
_pointer_frame_offset = raw_grab_frame() - _marker->tempo().frame();
- _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
}
void
{
framepos_t const pf = adjusted_current_frame (event);
_marker->set_position (pf);
- _editor->show_verbose_time_cursor (pf, 10);
+ show_verbose_cursor_time (pf);
}
void
motion (event, false);
- BBT_Time when;
+ Timecode::BBT_Time when;
TempoMap& map (_editor->session()->tempo_map());
map.bbt_time (last_pointer_frame(), when);
}
void
-TempoMarkerDrag::aborted ()
+TempoMarkerDrag::aborted (bool)
{
_marker->set_position (_marker->tempo().frame());
}
_stop (s)
{
DEBUG_TRACE (DEBUG::Drags, "New CursorDrag\n");
-
- _cursor = reinterpret_cast<EditorCursor*> (_item->get_data ("cursor"));
- assert (_cursor);
}
+/** Do all the things we do when dragging the playhead to make it look as though
+ * we have located, without actually doing the locate (because that would cause
+ * the diskstream buffers to be refilled, which is too slow).
+ */
void
-CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
+CursorDrag::fake_locate (framepos_t t)
{
- Drag::start_grab (event, c);
+ _editor->playhead_cursor->set_position (t);
- if (!_stop) {
+ Session* s = _editor->session ();
+ if (s->timecode_transmission_suspended ()) {
+ framepos_t const f = _editor->playhead_cursor->current_frame;
+ s->send_mmc_locate (f);
+ s->send_full_time_code (f);
+ }
- framepos_t where = _editor->event_frame (event, 0, 0);
+ show_verbose_cursor_time (t);
+ _editor->UpdateAllTransportClocks (t);
+}
- _editor->snap_to_with_modifier (where, event);
- _editor->playhead_cursor->set_position (where);
+void
+CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
+{
+ Drag::start_grab (event, c);
- }
+ _grab_zoom = _editor->frames_per_unit;
- if (_cursor == _editor->playhead_cursor) {
- _editor->_dragging_playhead = true;
+ framepos_t where = _editor->event_frame (event, 0, 0);
+ _editor->snap_to_with_modifier (where, event);
- Session* s = _editor->session ();
+ _editor->_dragging_playhead = true;
- if (s) {
- if (_was_rolling && _stop) {
- s->request_stop ();
- }
+ Session* s = _editor->session ();
- if (s->is_auditioning()) {
- s->cancel_audition ();
- }
+ if (s) {
+ if (_was_rolling && _stop) {
+ s->request_stop ();
+ }
- s->request_suspend_timecode_transmission ();
+ if (s->is_auditioning()) {
+ s->cancel_audition ();
+ }
- if (s->timecode_transmission_suspended ()) {
- framepos_t const f = _editor->playhead_cursor->current_frame;
- s->send_mmc_locate (f);
- s->send_full_time_code (f);
- }
+ s->request_suspend_timecode_transmission ();
+ while (!s->timecode_transmission_suspended ()) {
+ /* twiddle our thumbs */
}
}
- _pointer_frame_offset = raw_grab_frame() - _cursor->current_frame;
-
- _editor->show_verbose_time_cursor (_cursor->current_frame, 10);
+ fake_locate (where);
}
void
CursorDrag::motion (GdkEvent* event, bool)
{
- framepos_t const adjusted_frame = adjusted_current_frame (event);
+ if (_drags->current_pointer_y() != last_pointer_y()) {
- if (adjusted_frame == last_pointer_frame()) {
- return;
- }
+ /* zoom when we move the pointer up and down */
- _cursor->set_position (adjusted_frame);
+ /* y range to operate over (pixels) */
+ double const y_range = 512;
+ /* we will multiply the grab zoom by a factor between scale_range and scale_range^-1 */
+ double const scale_range = 4;
+ /* dead zone around the grab point in which to do no zooming (pixels) */
+ double const dead_zone = 100;
- _editor->show_verbose_time_cursor (_cursor->current_frame, 10);
+ /* current dy */
+ double dy = _drags->current_pointer_y() - grab_y();
- Session* s = _editor->session ();
- if (s && _item == &_editor->playhead_cursor->canvas_item && s->timecode_transmission_suspended ()) {
- framepos_t const f = _editor->playhead_cursor->current_frame;
- s->send_mmc_locate (f);
- s->send_full_time_code (f);
+ if (dy < -dead_zone || dy > dead_zone) {
+ /* we are outside the dead zone; remove it from our calculation */
+ if (dy < 0) {
+ dy += dead_zone;
+ } else {
+ dy -= dead_zone;
+ }
+
+ /* get a number from -1 to 1 as dy ranges from -y_range to y_range */
+ double udy = max (min (dy / y_range, 1.0), -1.0);
+
+ /* and zoom, using playhead focus temporarily */
+ Editing::ZoomFocus const zf = _editor->get_zoom_focus ();
+ _editor->set_zoom_focus (Editing::ZoomFocusPlayhead);
+ _editor->temporal_zoom (_grab_zoom * pow (scale_range, -udy));
+ _editor->set_zoom_focus (zf);
+ }
}
-
+ framepos_t const adjusted_frame = adjusted_current_frame (event);
+ if (adjusted_frame != last_pointer_frame()) {
+ fake_locate (adjusted_frame);
#ifdef GTKOSX
- _editor->update_canvas_now ();
+ _editor->update_canvas_now ();
#endif
- _editor->UpdateAllTransportClocks (_cursor->current_frame);
+ }
}
void
motion (event, false);
- if (_item == &_editor->playhead_cursor->canvas_item) {
- 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 ();
- }
+ 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 ()
+CursorDrag::aborted (bool)
{
if (_editor->_dragging_playhead) {
_editor->session()->request_resume_timecode_transmission ();
_editor->_dragging_playhead = false;
}
-
- _cursor->set_position (adjusted_frame (grab_frame (), 0, false));
+
+ _editor->playhead_cursor->set_position (adjusted_frame (grab_frame (), 0, false));
}
FadeInDrag::FadeInDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> const r = arv->audio_region ();
- _pointer_frame_offset = raw_grab_frame() - ((framecnt_t) r->fade_in()->back()->when + r->position());
- _editor->show_verbose_duration_cursor (r->position(), r->position() + r->fade_in()->back()->when, 10);
-
+ show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32);
+
arv->show_fade_line((framepos_t) r->fade_in()->back()->when);
}
+void
+FadeInDrag::setup_pointer_frame_offset ()
+{
+ AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
+ boost::shared_ptr<AudioRegion> const r = arv->audio_region ();
+ _pointer_frame_offset = raw_grab_frame() - ((framecnt_t) r->fade_in()->back()->when + r->position());
+}
+
void
FadeInDrag::motion (GdkEvent* event, bool)
{
tmp->show_fade_line((framecnt_t) fade_length);
}
- _editor->show_verbose_duration_cursor (region->position(), region->position() + fade_length, 10);
+ show_verbose_cursor_duration (region->position(), region->position() + fade_length, 32);
}
void
}
void
-FadeInDrag::aborted ()
+FadeInDrag::aborted (bool)
{
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> r = arv->audio_region ();
- _pointer_frame_offset = raw_grab_frame() - (r->length() - (framecnt_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);
-
+ show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame());
+
arv->show_fade_line(r->length() - r->fade_out()->back()->when);
}
+void
+FadeOutDrag::setup_pointer_frame_offset ()
+{
+ AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
+ boost::shared_ptr<AudioRegion> r = arv->audio_region ();
+ _pointer_frame_offset = raw_grab_frame() - (r->length() - (framecnt_t) r->fade_out()->back()->when + r->position());
+}
+
void
FadeOutDrag::motion (GdkEvent* event, bool)
{
tmp->show_fade_line(region->length() - fade_length);
}
- _editor->show_verbose_duration_cursor (region->last_frame() - fade_length, region->last_frame(), 10);
+ show_verbose_cursor_duration (region->last_frame() - fade_length, region->last_frame());
}
void
}
void
-FadeOutDrag::aborted ()
+FadeOutDrag::aborted (bool)
{
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (i->view);
: Drag (e, i)
{
DEBUG_TRACE (DEBUG::Drags, "New MarkerDrag\n");
-
+
_marker = reinterpret_cast<Marker*> (_item->get_data ("marker"));
assert (_marker);
_points.push_back (Gnome::Art::Point (0, 0));
_points.push_back (Gnome::Art::Point (0, physical_screen_height (_editor->get_window())));
-
- _line = new ArdourCanvas::Line (*_editor->timebar_group);
- _line->property_width_pixels() = 1;
- _line->property_points () = _points;
- _line->hide ();
-
- _line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerDragLine.get();
}
MarkerDrag::~MarkerDrag ()
Location *location = _editor->find_location_from_marker (_marker, is_start);
_editor->_dragging_edit_point = true;
- _pointer_frame_offset = raw_grab_frame() - (is_start ? location->start() : location->end());
-
update_item (location);
// _drag_line->show();
// _line->raise_to_top();
if (is_start) {
- _editor->show_verbose_time_cursor (location->start(), 10);
+ show_verbose_cursor_time (location->start());
} else {
- _editor->show_verbose_time_cursor (location->end(), 10);
+ show_verbose_cursor_time (location->end());
}
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
}
}
+void
+MarkerDrag::setup_pointer_frame_offset ()
+{
+ bool is_start;
+ Location *location = _editor->find_location_from_marker (_marker, is_start);
+ _pointer_frame_offset = raw_grab_frame() - (is_start ? location->start() : location->end());
+}
+
void
MarkerDrag::motion (GdkEvent* event, bool)
{
framepos_t next = newframe;
- if (newframe == last_pointer_frame()) {
- return;
- }
-
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
move_both = true;
}
copy_location->set_end (new_end);
} else if (new_start < copy_location->end()) {
copy_location->set_start (new_start);
- } else {
+ } else if (newframe > 0) {
_editor->snap_to (next, 1, true);
copy_location->set_end (next);
copy_location->set_start (newframe);
assert (!_copied_locations.empty());
- _editor->show_verbose_time_cursor (newframe, 10);
+ show_verbose_cursor_time (newframe);
#ifdef GTKOSX
_editor->update_canvas_now ();
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 ()
+MarkerDrag::aborted (bool)
{
/* XXX: TODO */
}
void
MarkerDrag::update_item (Location* location)
{
- double const x1 = _editor->frame_to_pixel (location->start());
-
- _points.front().set_x(x1);
- _points.back().set_x(x1);
- _line->property_points() = _points;
+ /* noop */
}
ControlPointDrag::ControlPointDrag (Editor* e, ArdourCanvas::Item* i)
_cumulative_x_drag (0),
_cumulative_y_drag (0)
{
+ if (_zero_gain_fraction < 0.0) {
+ _zero_gain_fraction = gain_to_slider_position_with_max (dB_to_coefficient (0.0), Config->get_max_gain());
+ }
+
DEBUG_TRACE (DEBUG::Drags, "New ControlPointDrag\n");
-
+
_point = reinterpret_cast<ControlPoint*> (_item->get_data ("control_point"));
assert (_point);
}
void
ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
{
- Drag::start_grab (event, _editor->fader_cursor);
+ Drag::start_grab (event, _editor->cursors()->fader);
// start the grab at the center of the control point so
// the point doesn't 'jump' to the mouse after the first drag
_point->line().start_drag_single (_point, _fixed_grab_x, fraction);
- _editor->set_verbose_canvas_cursor (_point->line().get_verbose_cursor_string (fraction),
- event->button.x + 10, event->button.y + 10);
+ _editor->verbose_cursor()->set (_point->line().get_verbose_cursor_string (fraction),
+ event->button.x + 10, event->button.y + 10);
- _editor->show_verbose_canvas_cursor ();
+ _editor->verbose_cursor()->show ();
}
void
cy = min ((double) _point->line().height(), cy);
framepos_t cx_frames = _editor->unit_to_frame (cx);
-
+
if (!_x_constrained) {
_editor->snap_to_with_modifier (cx_frames, event);
}
_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));
+ _editor->verbose_cursor()->set_text (_point->line().get_verbose_cursor_string (fraction));
}
void
} else {
motion (event, false);
}
-
+
_point->line().end_drag ();
_editor->session()->commit_reversible_command ();
}
void
-ControlPointDrag::aborted ()
+ControlPointDrag::aborted (bool)
{
_point->line().reset ();
}
uint32_t before;
uint32_t after;
-
+
if (!_line->control_points_adjacent (frame_within_region, before, after)) {
/* no adjacent points */
return;
}
- Drag::start_grab (event, _editor->fader_cursor);
+ Drag::start_grab (event, _editor->cursors()->fader);
/* store grab start in parent frame */
_line->start_drag_line (before, after, fraction);
- _editor->set_verbose_canvas_cursor (_line->get_verbose_cursor_string (fraction),
- event->button.x + 10, event->button.y + 10);
+ _editor->verbose_cursor()->set (_line->get_verbose_cursor_string (fraction),
+ event->button.x + 10, event->button.y + 10);
- _editor->show_verbose_canvas_cursor ();
+ _editor->verbose_cursor()->show ();
}
void
/* 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));
+ _editor->verbose_cursor()->set_text (_line->get_verbose_cursor_string (fraction));
}
void
}
void
-LineDrag::aborted ()
+LineDrag::aborted (bool)
{
_line->reset ();
}
FeatureLineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
{
Drag::start_grab (event);
-
- _line = reinterpret_cast<SimpleLine*> (_item);
+
+ _line = reinterpret_cast<Line*> (_item);
assert (_line);
/* need to get x coordinate in terms of parent (AudioRegionView) origin. */
/* store grab start in parent frame */
_region_view_grab_x = cx;
-
- _before = _line->property_x1();
-
+
+ _before = *(float*) _item->get_data ("position");
+
_arv = reinterpret_cast<AudioRegionView*> (_item->get_data ("regionview"));
-
+
_max_x = _editor->frame_to_pixel(_arv->get_duration());
}
FeatureLineDrag::motion (GdkEvent*, 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();
+ ArdourCanvas::Points points;
+
+ double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+
+ _line->get_bounds(x1, y2, x2, y2);
+
+ points.push_back(Gnome::Art::Point(cx, 2.0)); // first x-coord needs to be a non-normal value
+ points.push_back(Gnome::Art::Point(cx, y2 - y1));
+
+ _line->property_points() = points;
+
+ float *pos = new float;
+ *pos = cx;
+
+ _line->set_data ("position", pos);
+
+ _before = cx;
}
void
FeatureLineDrag::finished (GdkEvent*, bool)
{
_arv = reinterpret_cast<AudioRegionView*> (_item->get_data ("regionview"));
- _arv->update_transient(_before, _line->property_x1());
+ _arv->update_transient(_before, _before);
}
void
-FeatureLineDrag::aborted ()
+FeatureLineDrag::aborted (bool)
{
//_line->reset ();
}
RubberbandSelectDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
Drag::start_grab (event);
- _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+ show_verbose_cursor_time (adjusted_current_frame (event));
}
void
_editor->rubberband_rect->show();
_editor->rubberband_rect->raise_to_top();
- _editor->show_verbose_time_cursor (pf, 10);
+ show_verbose_cursor_time (pf);
}
}
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
- bool committed;
_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, false);
+ _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, false);
+ _editor->select_all_within (last_pointer_frame(), grab_frame() - 1, y1, y2, _editor->track_views, op, false);
}
- if (!committed) {
- _editor->commit_reversible_command ();
- }
+ _editor->commit_reversible_command ();
} else {
if (!getenv("ARDOUR_SAE")) {
}
void
-RubberbandSelectDrag::aborted ()
+RubberbandSelectDrag::aborted (bool)
{
_editor->rubberband_rect->hide ();
}
{
Drag::start_grab (event, cursor);
- _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+ show_verbose_cursor_time (adjusted_current_frame (event));
}
void
rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf);
}
- _editor->show_verbose_time_cursor (pf, 10);
+ show_verbose_cursor_time (pf);
}
void
}
#endif
- _editor->begin_reversible_command (_("timestretch"));
-
// XXX how do timeFX on multiple regions ?
RegionSelection rs;
}
void
-TimeFXDrag::aborted ()
+TimeFXDrag::aborted (bool)
{
_primary->get_time_axis_view().hide_timestretch ();
}
}
void
-ScrubDrag::aborted ()
+ScrubDrag::aborted (bool)
{
/* XXX: TODO */
}
void
SelectionDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
{
- framepos_t start = 0;
- framepos_t end = 0;
-
if (_editor->session() == 0) {
return;
}
} else {
_copy = false;
}
- cursor = _editor->selector_cursor;
+ cursor = _editor->cursors()->selector;
Drag::start_grab (event, cursor);
break;
if (_editor->clicked_axisview) {
_editor->clicked_axisview->order_selection_trims (_item, true);
}
- Drag::start_grab (event, _editor->left_side_trim_cursor);
- start = _editor->selection->time[_editor->clicked_selection].start;
- _pointer_frame_offset = raw_grab_frame() - start;
+ Drag::start_grab (event, _editor->cursors()->left_side_trim);
break;
case SelectionEndTrim:
if (_editor->clicked_axisview) {
_editor->clicked_axisview->order_selection_trims (_item, false);
}
- Drag::start_grab (event, _editor->right_side_trim_cursor);
- end = _editor->selection->time[_editor->clicked_selection].end;
- _pointer_frame_offset = raw_grab_frame() - end;
+ Drag::start_grab (event, _editor->cursors()->right_side_trim);
break;
case SelectionMove:
- start = _editor->selection->time[_editor->clicked_selection].start;
Drag::start_grab (event, cursor);
- _pointer_frame_offset = raw_grab_frame() - start;
break;
}
if (_operation == SelectionMove) {
- _editor->show_verbose_time_cursor (start, 10);
+ show_verbose_cursor_time (_editor->selection->time[_editor->clicked_selection].start);
} else {
- _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+ show_verbose_cursor_time (adjusted_current_frame (event));
}
_original_pointer_time_axis = _editor->trackview_by_y_position (_drags->current_pointer_y ()).first->order ();
}
+void
+SelectionDrag::setup_pointer_frame_offset ()
+{
+ switch (_operation) {
+ case CreateSelection:
+ _pointer_frame_offset = 0;
+ break;
+
+ case SelectionStartTrim:
+ case SelectionMove:
+ _pointer_frame_offset = raw_grab_frame() - _editor->selection->time[_editor->clicked_selection].start;
+ break;
+
+ case SelectionEndTrim:
+ _pointer_frame_offset = raw_grab_frame() - _editor->selection->time[_editor->clicked_selection].end;
+ break;
+ }
+}
+
void
SelectionDrag::motion (GdkEvent* event, bool first_move)
{
if (pending_time_axis.first == 0) {
return;
}
-
+
framepos_t const pending_position = adjusted_current_frame (event);
/* only alter selection if things have changed */
if (_copy) {
/* adding to the selection */
- _editor->set_selected_track_as_side_effect (Selection::Add);
+ _editor->set_selected_track_as_side_effect (Selection::Add);
//_editor->selection->add (_editor->clicked_axisview);
_editor->clicked_selection = _editor->selection->add (start, end);
_copy = false;
/* new selection */
if (_editor->clicked_axisview && !_editor->selection->selected (_editor->clicked_axisview)) {
- //_editor->selection->set (_editor->clicked_axisview);
- _editor->set_selected_track_as_side_effect (Selection::Set);
+ //_editor->selection->set (_editor->clicked_axisview);
+ _editor->set_selected_track_as_side_effect (Selection::Set);
}
-
+
_editor->clicked_selection = _editor->selection->set (start, end);
}
}
/* 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->set_selected_track_as_side_effect (Selection::Add);
+ // _editor->set_selected_track_as_side_effect (Selection::Add);
_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 tmp = i;
++tmp;
-
+
if ((*i)->order() < min_order || (*i)->order() > max_order) {
_editor->selection->remove (*i);
_added_time_axes.remove (*i);
}
if (_operation == SelectionMove) {
- _editor->show_verbose_time_cursor(start, 10);
+ show_verbose_cursor_time(start);
} else {
- _editor->show_verbose_time_cursor(pending_position, 10);
+ show_verbose_cursor_time(pending_position);
}
}
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()) {
s->request_stop (false, false);
}
}
void
-SelectionDrag::aborted ()
+SelectionDrag::aborted (bool)
{
/* XXX: TODO */
}
_copy (false)
{
DEBUG_TRACE (DEBUG::Drags, "New RangeMarkerBarDrag\n");
-
- _drag_rect = new ArdourCanvas::SimpleRect (*_editor->time_line_group, 0.0, 0.0, 0.0,
- physical_screen_height (_editor->get_window()));
+
+ _drag_rect = new ArdourCanvas::SimpleRect (*_editor->time_line_group, 0.0, 0.0, 0.0,
+ physical_screen_height (_editor->get_window()));
_drag_rect->hide ();
_drag_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeDragRect.get();
} else {
_copy = false;
}
- cursor = _editor->selector_cursor;
+ cursor = _editor->cursors()->selector;
break;
}
Drag::start_grab (event, cursor);
- _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+ show_verbose_cursor_time (adjusted_current_frame (event));
}
void
if (_operation == CreateRangeMarker || _operation == CreateTransportMarker || _operation == CreateCDMarker) {
framepos_t grab = grab_frame ();
_editor->snap_to (grab);
-
+
if (pf < grab_frame()) {
start = pf;
end = grab;
update_item (_editor->temp_location);
}
- _editor->show_verbose_time_cursor (pf, 10);
+ show_verbose_cursor_time (pf);
}
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));
}
void
-RangeMarkerBarDrag::aborted ()
+RangeMarkerBarDrag::aborted (bool)
{
/* XXX: TODO */
}
MouseZoomDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{
if (Keyboard::the_keyboard().key_is_down (GDK_Control_L)) {
- Drag::start_grab (event, _editor->zoom_out_cursor);
+ Drag::start_grab (event, _editor->cursors()->zoom_out);
_zoom_out = true;
} else {
- Drag::start_grab (event, _editor->zoom_in_cursor);
+ Drag::start_grab (event, _editor->cursors()->zoom_in);
_zoom_out = false;
}
-
- _editor->show_verbose_time_cursor (adjusted_current_frame (event), 10);
+
+ show_verbose_cursor_time (adjusted_current_frame (event));
}
void
_editor->reposition_zoom_rect(start, end);
- _editor->show_verbose_time_cursor (pf, 10);
+ show_verbose_cursor_time (pf);
}
}
_editor->temporal_zoom_by_frame (last_pointer_frame(), grab_frame(), "mouse zoom");
}
} else {
- _editor->temporal_zoom_to_frame (_zoom_out, grab_frame());
+ if (Keyboard::the_keyboard().key_is_down (GDK_Shift_L)) {
+ _editor->tav_zoom_step (_zoom_out);
+ } else {
+ _editor->temporal_zoom_to_frame (_zoom_out, grab_frame());
+ }
}
_editor->zoom_rect->hide();
}
void
-MouseZoomDrag::aborted ()
+MouseZoomDrag::aborted (bool)
{
_editor->zoom_rect->hide ();
}
/* primary note time */
frameoffset_t const n = _region->beats_to_frames (_primary->note()->time ());
-
+
/* new time of the primary note relative to the region position */
- frameoffset_t const st = n + dx;
+ frameoffset_t st = n + dx;
+
+ /* prevent the note being dragged earlier than the region's position */
+ if (st < 0) {
+ st = 0;
+ }
/* snap and return corresponding delta */
return _region->snap_frame_to_frame (st) - n;
}
}
- /* more positive value = higher pitch and higher y-axis position on track,
- which is the inverse of the X-centric geometric universe
- */
+ /* more positive value = higher pitch and higher y-axis position on track,
+ which is the inverse of the X-centric geometric universe
+ */
- return -ndy;
-}
+ return -ndy;
+}
void
NoteDrag::motion (GdkEvent *, bool)
_cumulative_dx += tdx;
_cumulative_dy += tdy;
- int8_t note_delta = total_dy();
+ int8_t note_delta = total_dy();
_region->move_selection (tdx, tdy, note_delta);
- char buf[12];
- snprintf (buf, sizeof (buf), "%s (%d)", Evoral::midi_note_name (_primary->note()->note() + note_delta).c_str(),
- (int) floor (_primary->note()->note() + note_delta));
-
- _editor->show_verbose_canvas_cursor_with (buf);
- }
+ char buf[12];
+ snprintf (buf, sizeof (buf), "%s (%d)", Evoral::midi_note_name (_primary->note()->note() + note_delta).c_str(),
+ (int) floor (_primary->note()->note() + note_delta));
+
+ show_verbose_cursor_text (buf);
+ }
}
void
}
void
-NoteDrag::aborted ()
+NoteDrag::aborted (bool)
{
/* XXX: TODO */
}
, _nothing_to_drag (false)
{
DEBUG_TRACE (DEBUG::Drags, "New AutomationRangeDrag\n");
-
+
_atav = reinterpret_cast<AutomationTimeAxisView*> (_item->get_data ("trackview"));
assert (_atav);
i->points.push_back (i->line->nth (j));
}
}
-
+
} else {
for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
framecnt_t const half = (i->start + i->end) / 2;
-
+
/* find the line that this audio range starts in */
list<Line>::iterator j = _lines.begin();
while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
if (j != _lines.end()) {
boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
-
+
/* j is the line that this audio range starts in; fade into it;
64 samples length plucked out of thin air.
*/
}
/* same thing for the end */
-
+
j = _lines.begin();
while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
++j;
if (j != _lines.end()) {
boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
-
+
/* j is the line that this audio range starts in; fade out of it;
64 samples length plucked out of thin air.
*/
-
+
framepos_t b = i->end - 64;
if (b < half) {
b = half;
double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ());
double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ());
-
+
the_list->add (p, the_list->eval (p));
j->line->add_always_in_view (p);
the_list->add (q, the_list->eval (q));
if (_nothing_to_drag) {
return;
}
-
+
motion (event, false);
for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
i->line->end_drag ();
}
void
-AutomationRangeDrag::aborted ()
+AutomationRangeDrag::aborted (bool)
{
for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
i->line->clear_always_in_view ();
initial_position = v->region()->position ();
initial_end = v->region()->position () + v->region()->length ();
}
+
+PatchChangeDrag::PatchChangeDrag (Editor* e, CanvasPatchChange* i, MidiRegionView* r)
+ : Drag (e, i)
+ , _region_view (r)
+ , _patch_change (i)
+ , _cumulative_dx (0)
+{
+ DEBUG_TRACE (DEBUG::Drags, "New PatchChangeDrag\n");
+}
+
+void
+PatchChangeDrag::motion (GdkEvent* ev, bool)
+{
+ framepos_t f = adjusted_current_frame (ev);
+ boost::shared_ptr<Region> r = _region_view->region ();
+ f = max (f, r->position ());
+ f = min (f, r->last_frame ());
+
+ framecnt_t const dxf = f - grab_frame();
+ double const dxu = _editor->frame_to_unit (dxf);
+ _patch_change->move (dxu - _cumulative_dx, 0);
+ _cumulative_dx = dxu;
+}
+
+void
+PatchChangeDrag::finished (GdkEvent* ev, bool movement_occurred)
+{
+ if (!movement_occurred) {
+ return;
+ }
+
+ boost::shared_ptr<Region> r (_region_view->region ());
+
+ framepos_t f = adjusted_current_frame (ev);
+ f = max (f, r->position ());
+ f = min (f, r->last_frame ());
+
+ _region_view->move_patch_change (
+ *_patch_change,
+ _region_view->frames_to_beats (f - r->position() - r->start())
+ );
+}
+
+void
+PatchChangeDrag::aborted (bool)
+{
+ _patch_change->move (-_cumulative_dx, 0);
+}
+
+void
+PatchChangeDrag::setup_pointer_frame_offset ()
+{
+ boost::shared_ptr<Region> region = _region_view->region ();
+ _pointer_frame_offset = raw_grab_frame() - _region_view->beats_to_frames (_patch_change->patch()->time()) - region->position() + region->start();
+}
+