#include "gtkmm2ext/utils.h"
-#include "ardour/session.h"
+#include "ardour/audioregion.h"
#include "ardour/dB.h"
-#include "ardour/region_factory.h"
+#include "ardour/midi_region.h"
#include "ardour/operations.h"
+#include "ardour/region_factory.h"
+#include "ardour/session.h"
#include "editor.h"
#include "i18n.h"
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 ()
{
_editor->visible_order_range (&_visible_y_low, &_visible_y_high);
- /* Make a list of non-hidden tracks to refer to during the drag */
+ /* Make a list of tracks to refer to during the drag; we include hidden tracks,
+ as some of the regions we are dragging may be on such tracks.
+ */
TrackViewList track_views = _editor->track_views;
track_views.sort (EditorOrderTimeAxisViewSorter ());
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 ();
- for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) {
- _time_axis_views.push_back (j->get());
- }
+ _time_axis_views.push_back (*i);
+
+ TimeAxisView::Children children_list = (*i)->get_child_list ();
+ for (TimeAxisView::Children::iterator j = children_list.begin(); j != children_list.end(); ++j) {
+ _time_axis_views.push_back (j->get());
}
}
}
}
-/** Given a non-hidden TimeAxisView, return the index of it into the _time_axis_views vector */
+/** Given a TimeAxisView, return the index of it into the _time_axis_views vector,
+ * or -1 if it is not found.
+ */
int
RegionDrag::find_time_axis_view (TimeAxisView* t) const
{
if (first_move) {
- /* 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.
+
+ /* Reparent to a non scrolling group so that we can keep the
+ region selection above all time axis views.
+ Reparenting means that we will have to move the region view
+ later, 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);
+
+ if (!rv->get_time_axis_view().hidden()) {
+ /* the track that this region view is on is hidden, so hide the region too */
+ rv->get_canvas_group()->hide ();
+ }
}
- /* Work out the change in y position of this region view */
-
- double y_delta = 0;
-
/* If we have moved tracks, we'll fudge the layer delta so that the
region gets moved back onto layer 0 on its new track; this avoids
confusion when dragging regions from non-zero layers onto different
this_delta_layer = - i->layer;
}
- /* Move this region to layer 0 on its old track */
- StreamView* lv = _time_axis_views[i->time_axis_view]->view ();
- if (lv->layer_display() == Stacked) {
- y_delta -= (lv->layers() - i->layer - 1) * lv->child_height ();
- }
-
- /* Now move it to its right layer on the current track */
- StreamView* cv = _time_axis_views[i->time_axis_view + delta_time_axis_view]->view ();
- if (cv->layer_display() == Stacked) {
- y_delta += (cv->layers() - (i->layer + this_delta_layer) - 1) * cv->child_height ();
- }
+ /* The TimeAxisView that this region is now on */
+ TimeAxisView* tv = _time_axis_views[i->time_axis_view + delta_time_axis_view];
+
+ /* Set height */
+ rv->set_height (tv->view()->child_height ());
- /* Move tracks */
- if (delta_time_axis_view > 0) {
- for (int j = 0; j < delta_time_axis_view; ++j) {
- y_delta += _time_axis_views[i->time_axis_view + j]->current_height ();
- }
+ /* Update show/hidden status as the region view may have come from a hidden track,
+ or have moved to one.
+ */
+ if (tv->hidden ()) {
+ rv->get_canvas_group()->hide ();
} else {
- /* start by subtracting the height of the track above where we are now */
- for (int j = 1; j <= -delta_time_axis_view; ++j) {
- y_delta -= _time_axis_views[i->time_axis_view - j]->current_height ();
- }
+ rv->get_canvas_group()->show ();
}
- /* Set height */
- rv->set_height (_time_axis_views[i->time_axis_view + delta_time_axis_view]->view()->child_height ());
-
/* Update the DraggingView */
i->time_axis_view += delta_time_axis_view;
i->layer += this_delta_layer;
if (_brushing) {
_editor->mouse_brush_insert_region (rv, pending_region_position);
} else {
- rv->move (x_delta, y_delta);
+ double x = 0;
+ double y = 0;
+
+ /* Get the y coordinate of the top of the track that this region is now on */
+ tv->canvas_display()->i2w (x, y);
+ y += _editor->get_trackview_group_vertical_offset();
+
+ /* And adjust for the layer that it should be on */
+ StreamView* cv = tv->view ();
+ if (cv->layer_display() == Stacked) {
+ y += (cv->layers() - i->layer - 1) * cv->child_height ();
+ }
+
+ /* Now move the region view */
+ rv->move (x_delta, y - rv->get_canvas_group()->property_y());
}
} /* foreach region */
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.
/* 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 = 128;
+ double const dead_zone = 100;
/* current dy */
double dy = _drags->current_pointer_y() - grab_y();
}
void
-MarkerDrag::update_item (Location* location)
+MarkerDrag::update_item (Location*)
{
/* noop */
}
_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"));
frameoffset_t const dx = _editor->unit_to_frame (_drags->current_pointer_x() - grab_x());
/* primary note time */
- frameoffset_t const n = _region->beats_to_frames (_primary->note()->time ());
+ frameoffset_t const n = _region->source_beats_to_absolute_frames (_primary->note()->time ());
- /* new time of the primary note relative to the region position */
+ /* new time of the primary note in session frames */
frameoffset_t st = n + dx;
+ framepos_t const rp = _region->region()->position ();
+
/* prevent the note being dragged earlier than the region's position */
- if (st < 0) {
- st = 0;
- }
+ st = max (st, rp);
/* snap and return corresponding delta */
- return _region->snap_frame_to_frame (st) - n;
+ return _region->snap_frame_to_frame (st - rp) + rp - n;
}
-/** @return Current total drag y change in notes */
+/** @return Current total drag y change in note number */
int8_t
NoteDrag::total_dy () const
{
- /* this is `backwards' to make increasing note number go in the right direction */
- double const dy = _drags->current_pointer_y() - grab_y();
-
- /* dy in notes */
- int8_t ndy = 0;
-
- if (abs (dy) >= _note_height) {
- if (dy > 0) {
- ndy = (int8_t) ceil (dy / _note_height / 2.0);
- } else {
- ndy = (int8_t) floor (dy / _note_height / 2.0);
- }
- }
-
- /* 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 ((int8_t) (grab_y() / _note_height)) - ((int8_t) (_drags->current_pointer_y() / _note_height));
}
void
{
/* Total change in x and y since the start of the drag */
frameoffset_t const dx = total_dx ();
- int8_t const dy = -total_dy ();
+ int8_t const dy = total_dy ();
/* Now work out what we have to do to the note canvas items to set this new drag delta */
double const tdx = _editor->frame_to_unit (dx) - _cumulative_dx;
- double const tdy = dy * _note_height - _cumulative_dy;
+ double const tdy = -dy * _note_height - _cumulative_dy;
if (tdx || tdy) {
_cumulative_dx += tdx;
_region->move_selection (tdx, tdy, note_delta);
+ /* the new note value may be the same as the old one, but we
+ * don't know what that means because the selection may have
+ * involved more than one note and we might be doing something
+ * odd with them. so show the note value anyway, always.
+ */
+
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));
+ uint8_t new_note = min (max (_primary->note()->note() + note_delta, 0), 127);
+
+ snprintf (buf, sizeof (buf), "%s (%d)", Evoral::midi_note_name (new_note).c_str(),
+ (int) floor (new_note));
show_verbose_cursor_text (buf);
}
_region_view->move_patch_change (
*_patch_change,
- _region_view->frames_to_beats (f - r->position() - r->start())
+ _region_view->region_frames_to_region_beats (f - r->position() - r->start())
);
}
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();
+ _pointer_frame_offset = raw_grab_frame() - _region_view->source_beats_to_absolute_frames (_patch_change->patch()->time());
}