Merge branch 'relative_snap'
- Many changes to the "User Interaction" pane wrt key modifiers. - Snap is now relative by default (override to absolute with the "Snap to absolute using:" modifier). - Midi notes now obey both snap modifiers (disable snap and absolute snap) - Timefx drag now selects the primary region (less user confusion). - Includes MIDI event id fix.
This commit is contained in:
commit
a14c7ff066
@ -2133,6 +2133,7 @@ Editor::set_snap_mode (SnapMode mode)
|
||||
|
||||
instant_save ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_edit_point_preference (EditPoint ep, bool force)
|
||||
{
|
||||
@ -2596,25 +2597,28 @@ Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundM
|
||||
return;
|
||||
}
|
||||
|
||||
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
||||
if (ArdourKeyboard::indicates_snap (event->button.state)) {
|
||||
if (_snap_mode == SnapOff) {
|
||||
snap_to_internal (start, direction, for_mark);
|
||||
}
|
||||
} else {
|
||||
if (_snap_mode != SnapOff) {
|
||||
snap_to_internal (start, direction, for_mark);
|
||||
} else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
|
||||
/* SnapOff, but we pressed the snap_delta modifier */
|
||||
snap_to_internal (start, direction, for_mark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark)
|
||||
Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
|
||||
{
|
||||
if (!_session || _snap_mode == SnapOff) {
|
||||
if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
snap_to_internal (start, direction, for_mark);
|
||||
snap_to_internal (start, direction, for_mark, ensure_snap);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2684,7 +2688,7 @@ Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool
|
||||
}
|
||||
|
||||
void
|
||||
Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark)
|
||||
Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
|
||||
{
|
||||
const framepos_t one_second = _session->frame_rate();
|
||||
const framepos_t one_minute = _session->frame_rate() * 60;
|
||||
@ -2854,6 +2858,10 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark)
|
||||
|
||||
case SnapMagnetic:
|
||||
|
||||
if (ensure_snap) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (presnap > start) {
|
||||
if (presnap > (start + pixel_to_sample(snap_threshold))) {
|
||||
start = presnap;
|
||||
|
@ -436,7 +436,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||
|
||||
void snap_to (framepos_t& first,
|
||||
ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
|
||||
bool for_mark = false);
|
||||
bool for_mark = false,
|
||||
bool ensure_snap = false);
|
||||
|
||||
void snap_to_with_modifier (framepos_t& first,
|
||||
GdkEvent const * ev,
|
||||
@ -2131,7 +2132,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||
|
||||
void snap_to_internal (framepos_t& first,
|
||||
ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
|
||||
bool for_mark = false);
|
||||
bool for_mark = false,
|
||||
bool ensure_snap = false);
|
||||
|
||||
void timecode_snap_to_internal (framepos_t& first,
|
||||
ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
|
||||
|
@ -218,6 +218,8 @@ Drag::Drag (Editor* e, ArdourCanvas::Item* i, bool trackview_only)
|
||||
: _editor (e)
|
||||
, _item (i)
|
||||
, _pointer_frame_offset (0)
|
||||
, _x_constrained (false)
|
||||
, _y_constrained (false)
|
||||
, _trackview_only (trackview_only)
|
||||
, _move_threshold_passed (false)
|
||||
, _starting_point_passed (false)
|
||||
@ -226,6 +228,7 @@ Drag::Drag (Editor* e, ArdourCanvas::Item* i, bool trackview_only)
|
||||
, _raw_grab_frame (0)
|
||||
, _grab_frame (0)
|
||||
, _last_pointer_frame (0)
|
||||
, _snap_delta (0)
|
||||
{
|
||||
|
||||
}
|
||||
@ -248,22 +251,11 @@ Drag::swap_grab (ArdourCanvas::Item* new_item, Gdk::Cursor* cursor, uint32_t /*t
|
||||
void
|
||||
Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
|
||||
{
|
||||
// if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained
|
||||
|
||||
if (Keyboard::is_button2_event (&event->button)) {
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::SecondaryModifier)) {
|
||||
_y_constrained = true;
|
||||
_x_constrained = false;
|
||||
} else {
|
||||
_y_constrained = false;
|
||||
_x_constrained = true;
|
||||
}
|
||||
} else {
|
||||
_x_constrained = false;
|
||||
_y_constrained = false;
|
||||
}
|
||||
/* we set up x/y dragging constraints on first move */
|
||||
|
||||
_raw_grab_frame = _editor->canvas_event_sample (event, &_grab_x, &_grab_y);
|
||||
|
||||
setup_pointer_frame_offset ();
|
||||
_grab_frame = adjusted_frame (_raw_grab_frame, event);
|
||||
_last_pointer_frame = _grab_frame;
|
||||
@ -343,6 +335,16 @@ Drag::adjusted_current_frame (GdkEvent const * event, bool snap) const
|
||||
return adjusted_frame (_drags->current_pointer_frame (), event, snap);
|
||||
}
|
||||
|
||||
frameoffset_t
|
||||
Drag::snap_delta (guint state) const
|
||||
{
|
||||
if (ArdourKeyboard::indicates_snap_delta (state)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _snap_delta;
|
||||
}
|
||||
|
||||
double
|
||||
Drag::current_pointer_x() const
|
||||
{
|
||||
@ -359,6 +361,14 @@ Drag::current_pointer_y () const
|
||||
return _drags->current_pointer_y () - _editor->get_trackview_group()->canvas_origin().y;
|
||||
}
|
||||
|
||||
void
|
||||
Drag::setup_snap_delta (framepos_t pos)
|
||||
{
|
||||
framepos_t temp = pos;
|
||||
_editor->snap_to (temp, ARDOUR::RoundNearest, false, true);
|
||||
_snap_delta = temp - pos;
|
||||
}
|
||||
|
||||
bool
|
||||
Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
|
||||
{
|
||||
@ -394,6 +404,39 @@ Drag::motion_handler (GdkEvent* event, bool from_autoscroll)
|
||||
} else {
|
||||
_initially_vertical = false;
|
||||
}
|
||||
/** check constraints for this drag.
|
||||
* Note that the current convention is to use "contains" for
|
||||
* key modifiers during motion and "equals" when initiating a drag.
|
||||
* In this case we haven't moved yet, so "equals" applies here.
|
||||
*/
|
||||
if (Config->get_edit_mode() != Lock) {
|
||||
if (event->motion.state & Gdk::BUTTON2_MASK) {
|
||||
// if dragging with button2, the motion is x constrained, with constraint modifier it is y constrained
|
||||
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::constraint_modifier ())) {
|
||||
_x_constrained = false;
|
||||
_y_constrained = true;
|
||||
} else {
|
||||
_x_constrained = true;
|
||||
_y_constrained = false;
|
||||
}
|
||||
} else if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::constraint_modifier ())) {
|
||||
// if dragging normally, the motion is constrained to the first direction of movement.
|
||||
if (_initially_vertical) {
|
||||
_x_constrained = true;
|
||||
_y_constrained = false;
|
||||
} else {
|
||||
_x_constrained = false;
|
||||
_y_constrained = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (event->button.state & Gdk::BUTTON2_MASK) {
|
||||
_x_constrained = false;
|
||||
} else {
|
||||
_x_constrained = true;
|
||||
}
|
||||
_y_constrained = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!from_autoscroll) {
|
||||
@ -555,7 +598,6 @@ RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView
|
||||
, _total_x_delta (0)
|
||||
, _last_pointer_time_axis_view (0)
|
||||
, _last_pointer_layer (0)
|
||||
, _single_axis (false)
|
||||
, _ndropzone (0)
|
||||
, _pdropzone (0)
|
||||
, _ddropzone (0)
|
||||
@ -567,10 +609,7 @@ void
|
||||
RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
|
||||
{
|
||||
Drag::start_grab (event, cursor);
|
||||
|
||||
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::TertiaryModifier)) {
|
||||
_single_axis = true;
|
||||
}
|
||||
setup_snap_delta (_last_frame_position);
|
||||
|
||||
show_verbose_cursor_time (_last_frame_position);
|
||||
|
||||
@ -588,7 +627,7 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
|
||||
/* compute the amount of pointer motion in frames, and where
|
||||
the region would be if we moved it by that much.
|
||||
*/
|
||||
*pending_region_position = adjusted_current_frame (event);
|
||||
*pending_region_position = adjusted_frame (_drags->current_pointer_frame () + snap_delta (event->button.state), event, true);
|
||||
|
||||
framepos_t sync_frame;
|
||||
framecnt_t sync_offset;
|
||||
@ -600,11 +639,11 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
|
||||
*/
|
||||
if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
|
||||
|
||||
sync_frame = *pending_region_position + (sync_dir*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);
|
||||
*pending_region_position = _primary->region()->adjust_to_sync (sync_frame) - snap_delta (event->button.state);
|
||||
|
||||
} else {
|
||||
*pending_region_position = _last_frame_position;
|
||||
@ -616,8 +655,7 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
|
||||
|
||||
double dx = 0;
|
||||
|
||||
/* in locked edit mode, reverse the usual meaning of _x_constrained */
|
||||
bool const x_move_allowed = Config->get_edit_mode() == Lock ? _x_constrained : !_x_constrained;
|
||||
bool const x_move_allowed = !_x_constrained;
|
||||
|
||||
if ((*pending_region_position != _last_frame_position) && x_move_allowed) {
|
||||
|
||||
@ -750,18 +788,6 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
|
||||
|
||||
assert (!_views.empty ());
|
||||
|
||||
if (first_move) {
|
||||
if (_single_axis) {
|
||||
if (initially_vertical()) {
|
||||
_y_constrained = false;
|
||||
_x_constrained = true;
|
||||
} else {
|
||||
_y_constrained = true;
|
||||
_x_constrained = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: time axis views in this method are often expressed as an index into the _time_axis_views vector */
|
||||
|
||||
/* Find the TimeAxisView that the pointer is now over */
|
||||
@ -1304,14 +1330,6 @@ RegionMoveDrag::finished (GdkEvent* ev, bool movement_occurred)
|
||||
return;
|
||||
}
|
||||
|
||||
/* reverse this here so that we have the correct logic to finalize
|
||||
the drag.
|
||||
*/
|
||||
|
||||
if (Config->get_edit_mode() == Lock) {
|
||||
_x_constrained = !_x_constrained;
|
||||
}
|
||||
|
||||
assert (!_views.empty ());
|
||||
|
||||
/* We might have hidden region views so that they weren't visible during the drag
|
||||
@ -2318,6 +2336,7 @@ RegionCreateDrag::aborted (bool)
|
||||
NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i)
|
||||
: Drag (e, i)
|
||||
, region (0)
|
||||
, _snap_delta (0)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::Drags, "New NoteResizeDrag\n");
|
||||
}
|
||||
@ -2342,9 +2361,13 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
|
||||
|
||||
region = &cnote->region_view();
|
||||
|
||||
double temp;
|
||||
temp = region->snap_to_pixel (cnote->x0 (), true);
|
||||
_snap_delta = temp - cnote->x0 ();
|
||||
|
||||
_item->grab ();
|
||||
|
||||
if (event->motion.state & Keyboard::PrimaryModifier) {
|
||||
if (event->motion.state & ArdourKeyboard::note_size_relative_modifier ()) {
|
||||
relative = false;
|
||||
} else {
|
||||
relative = true;
|
||||
@ -2377,7 +2400,7 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
|
||||
}
|
||||
|
||||
void
|
||||
NoteResizeDrag::motion (GdkEvent* /*event*/, bool /*first_move*/)
|
||||
NoteResizeDrag::motion (GdkEvent* event, bool /*first_move*/)
|
||||
{
|
||||
MidiRegionSelection& ms (_editor->get_selection().midi_regions);
|
||||
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
|
||||
@ -2385,21 +2408,62 @@ NoteResizeDrag::motion (GdkEvent* /*event*/, bool /*first_move*/)
|
||||
assert (nb);
|
||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
|
||||
if (mrv) {
|
||||
mrv->update_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative);
|
||||
double sd = 0.0;
|
||||
bool snap = true;
|
||||
bool apply_snap_delta = !ArdourKeyboard::indicates_snap_delta (event->button.state);
|
||||
|
||||
if (ArdourKeyboard::indicates_snap (event->button.state)) {
|
||||
if (_editor->snap_mode () != SnapOff) {
|
||||
snap = false;
|
||||
}
|
||||
} else {
|
||||
if (_editor->snap_mode () == SnapOff) {
|
||||
snap = false;
|
||||
/* inverted logic here - we;re in snapoff but we've pressed the snap delta modifier */
|
||||
if (!apply_snap_delta) {
|
||||
snap = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (apply_snap_delta) {
|
||||
sd = _snap_delta;
|
||||
}
|
||||
|
||||
mrv->update_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, sd, snap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NoteResizeDrag::finished (GdkEvent*, bool /*movement_occurred*/)
|
||||
NoteResizeDrag::finished (GdkEvent* event, bool /*movement_occurred*/)
|
||||
{
|
||||
MidiRegionSelection& ms (_editor->get_selection().midi_regions);
|
||||
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
|
||||
NoteBase* nb = reinterpret_cast<NoteBase*> (_item->get_data ("notebase"));
|
||||
assert (nb);
|
||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
|
||||
double sd = 0.0;
|
||||
bool snap = true;
|
||||
bool apply_snap_delta = !ArdourKeyboard::indicates_snap_delta (event->button.state);
|
||||
if (mrv) {
|
||||
mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative);
|
||||
if (ArdourKeyboard::indicates_snap (event->button.state)) {
|
||||
if (_editor->snap_mode () != SnapOff) {
|
||||
snap = false;
|
||||
}
|
||||
} else {
|
||||
if (_editor->snap_mode () == SnapOff) {
|
||||
snap = false;
|
||||
/* inverted logic here - we;re in snapoff but we've pressed the snap delta modifier */
|
||||
if (!apply_snap_delta) {
|
||||
snap = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (apply_snap_delta) {
|
||||
sd = _snap_delta;
|
||||
}
|
||||
mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, sd, snap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2597,8 +2661,9 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
|
||||
framecnt_t const region_length = (framecnt_t) (_primary->region()->length() / speed);
|
||||
|
||||
framepos_t const pf = adjusted_current_frame (event);
|
||||
setup_snap_delta (region_start);
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
||||
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::trim_contents_modifier ())) {
|
||||
/* Move the contents of the region around without changing the region bounds */
|
||||
_operation = ContentsTrim;
|
||||
Drag::start_grab (event, _editor->cursors()->trimmer);
|
||||
@ -2607,8 +2672,7 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
|
||||
if (pf < (region_start + region_length/2)) {
|
||||
/* closer to front */
|
||||
_operation = StartTrim;
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
||||
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::trim_anchored_modifier ())) {
|
||||
Drag::start_grab (event, _editor->cursors()->anchored_left_side_trim);
|
||||
} else {
|
||||
Drag::start_grab (event, _editor->cursors()->left_side_trim);
|
||||
@ -2616,17 +2680,18 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
|
||||
} else {
|
||||
/* closer to end */
|
||||
_operation = EndTrim;
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
||||
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::trim_anchored_modifier ())) {
|
||||
Drag::start_grab (event, _editor->cursors()->anchored_right_side_trim);
|
||||
} else {
|
||||
Drag::start_grab (event, _editor->cursors()->right_side_trim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
||||
/* jump trim disabled for now
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::trim_jump_modifier ())) {
|
||||
_jump_position_when_done = true;
|
||||
}
|
||||
*/
|
||||
|
||||
switch (_operation) {
|
||||
case StartTrim:
|
||||
@ -2636,7 +2701,7 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
|
||||
}
|
||||
break;
|
||||
case EndTrim:
|
||||
show_verbose_cursor_time (region_end);
|
||||
show_verbose_cursor_duration (region_start, region_end);
|
||||
break;
|
||||
case ContentsTrim:
|
||||
show_verbose_cursor_time (pf);
|
||||
@ -2662,8 +2727,8 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
||||
if (tv && tv->is_track()) {
|
||||
speed = tv->track()->speed();
|
||||
}
|
||||
|
||||
framecnt_t dt = adjusted_current_frame (event) - raw_grab_frame () + _pointer_frame_offset;
|
||||
framecnt_t adj_frame = adjusted_frame (_drags->current_pointer_frame () + snap_delta (event->button.state), event, true);
|
||||
framecnt_t dt = adj_frame - raw_grab_frame () + _pointer_frame_offset - snap_delta (event->button.state);
|
||||
|
||||
if (first_move) {
|
||||
|
||||
@ -2709,7 +2774,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
||||
|
||||
bool non_overlap_trim = false;
|
||||
|
||||
if (event && Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
||||
if (event && Keyboard::modifier_state_contains (event->button.state, ArdourKeyboard::trim_overlap_modifier ())) {
|
||||
non_overlap_trim = true;
|
||||
}
|
||||
|
||||
@ -2795,7 +2860,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
||||
show_verbose_cursor_time ((framepos_t) (rv->region()->position() / speed));
|
||||
break;
|
||||
case EndTrim:
|
||||
show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed));
|
||||
show_verbose_cursor_duration ((framepos_t) rv->region()->position() / speed, (framepos_t) rv->region()->last_frame() / speed);
|
||||
break;
|
||||
case ContentsTrim:
|
||||
// show_verbose_cursor_time (frame_delta);
|
||||
@ -2803,7 +2868,6 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrimDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||
{
|
||||
@ -3247,10 +3311,11 @@ void
|
||||
CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
|
||||
{
|
||||
Drag::start_grab (event, c);
|
||||
setup_snap_delta (_editor->playhead_cursor->current_frame ());
|
||||
|
||||
_grab_zoom = _editor->samples_per_pixel;
|
||||
|
||||
framepos_t where = _editor->canvas_event_sample (event);
|
||||
framepos_t where = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
|
||||
|
||||
_editor->snap_to_with_modifier (where, event);
|
||||
|
||||
@ -3288,15 +3353,16 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
|
||||
}
|
||||
}
|
||||
|
||||
fake_locate (where);
|
||||
fake_locate (where - snap_delta (event->button.state));
|
||||
}
|
||||
|
||||
void
|
||||
CursorDrag::motion (GdkEvent* event, bool)
|
||||
{
|
||||
framepos_t const adjusted_frame = adjusted_current_frame (event);
|
||||
if (adjusted_frame != last_pointer_frame()) {
|
||||
fake_locate (adjusted_frame);
|
||||
framepos_t where = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
|
||||
_editor->snap_to_with_modifier (where, event);
|
||||
if (where != last_pointer_frame()) {
|
||||
fake_locate (where - snap_delta (event->button.state));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3347,6 +3413,7 @@ FadeInDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
|
||||
|
||||
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
|
||||
boost::shared_ptr<AudioRegion> const r = arv->audio_region ();
|
||||
setup_snap_delta (r->position ());
|
||||
|
||||
show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32);
|
||||
}
|
||||
@ -3363,7 +3430,11 @@ void
|
||||
FadeInDrag::motion (GdkEvent* event, bool)
|
||||
{
|
||||
framecnt_t fade_length;
|
||||
framepos_t const pos = adjusted_current_frame (event);
|
||||
|
||||
framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
|
||||
_editor->snap_to_with_modifier (pos, event);
|
||||
pos -= snap_delta (event->button.state);
|
||||
|
||||
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
|
||||
|
||||
if (pos < (region->position() + 64)) {
|
||||
@ -3396,8 +3467,9 @@ FadeInDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||
}
|
||||
|
||||
framecnt_t fade_length;
|
||||
|
||||
framepos_t const pos = adjusted_current_frame (event);
|
||||
framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
|
||||
_editor->snap_to_with_modifier (pos, event);
|
||||
pos -= snap_delta (event->button.state);
|
||||
|
||||
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
|
||||
|
||||
@ -3459,6 +3531,7 @@ FadeOutDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
|
||||
|
||||
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
|
||||
boost::shared_ptr<AudioRegion> r = arv->audio_region ();
|
||||
setup_snap_delta (r->last_frame ());
|
||||
|
||||
show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame());
|
||||
}
|
||||
@ -3476,7 +3549,9 @@ FadeOutDrag::motion (GdkEvent* event, bool)
|
||||
{
|
||||
framecnt_t fade_length;
|
||||
|
||||
framepos_t const pos = adjusted_current_frame (event);
|
||||
framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
|
||||
_editor->snap_to_with_modifier (pos, event);
|
||||
pos -= snap_delta (event->button.state);
|
||||
|
||||
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
|
||||
|
||||
@ -3511,7 +3586,9 @@ FadeOutDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||
|
||||
framecnt_t fade_length;
|
||||
|
||||
framepos_t const pos = adjusted_current_frame (event);
|
||||
framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
|
||||
_editor->snap_to_with_modifier (pos, event);
|
||||
pos -= snap_delta (event->button.state);
|
||||
|
||||
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
|
||||
|
||||
@ -3707,7 +3784,7 @@ MarkerDrag::motion (GdkEvent* event, bool)
|
||||
framepos_t const newframe = adjusted_current_frame (event);
|
||||
framepos_t next = newframe;
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
|
||||
if (Keyboard::modifier_state_contains (event->button.state, ArdourKeyboard::push_points_modifier ())) {
|
||||
move_both = true;
|
||||
}
|
||||
|
||||
@ -3965,13 +4042,16 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
|
||||
_fixed_grab_x = _point->get_x();
|
||||
_fixed_grab_y = _point->get_y();
|
||||
|
||||
framepos_t pos = _editor->pixel_to_sample (_fixed_grab_x);
|
||||
setup_snap_delta (pos);
|
||||
|
||||
float const fraction = 1 - (_point->get_y() / _point->line().height());
|
||||
|
||||
_point->line().start_drag_single (_point, _fixed_grab_x, fraction);
|
||||
|
||||
show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction));
|
||||
|
||||
_pushing = Keyboard::modifier_state_contains (event->button.state, Keyboard::PrimaryModifier);
|
||||
_pushing = Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::push_points_modifier ());
|
||||
|
||||
if (!_point->can_slide ()) {
|
||||
_x_constrained = true;
|
||||
@ -3984,7 +4064,7 @@ ControlPointDrag::motion (GdkEvent* event, bool)
|
||||
double dx = _drags->current_pointer_x() - last_pointer_x();
|
||||
double dy = current_pointer_y() - last_pointer_y();
|
||||
|
||||
if (event->button.state & Keyboard::SecondaryModifier) {
|
||||
if (event->button.state & ArdourKeyboard::fine_adjust_modifier ()) {
|
||||
dx *= 0.1;
|
||||
dy *= 0.1;
|
||||
}
|
||||
@ -4017,12 +4097,13 @@ ControlPointDrag::motion (GdkEvent* event, bool)
|
||||
cy = max (0.0, cy);
|
||||
cy = min ((double) _point->line().height(), cy);
|
||||
|
||||
framepos_t cx_frames = _editor->pixel_to_sample (cx);
|
||||
framepos_t cx_frames = _editor->pixel_to_sample (cx) + snap_delta (event->button.state);
|
||||
|
||||
if (!_x_constrained) {
|
||||
_editor->snap_to_with_modifier (cx_frames, event);
|
||||
}
|
||||
|
||||
cx_frames -= snap_delta (event->button.state);
|
||||
cx_frames = min (cx_frames, _point->line().maximum_time());
|
||||
|
||||
float const fraction = 1.0 - (cy / _point->line().height());
|
||||
@ -4038,8 +4119,7 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||
if (!movement_occurred) {
|
||||
|
||||
/* just a click */
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::TertiaryModifier))) {
|
||||
_editor->reset_point_selection ();
|
||||
}
|
||||
|
||||
@ -4070,9 +4150,9 @@ ControlPointDrag::active (Editing::MouseMode m)
|
||||
}
|
||||
|
||||
LineDrag::LineDrag (Editor* e, ArdourCanvas::Item* i)
|
||||
: Drag (e, i),
|
||||
_line (0),
|
||||
_cumulative_y_drag (0)
|
||||
: Drag (e, i)
|
||||
, _line (0)
|
||||
, _cumulative_y_drag (0)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::Drags, "New LineDrag\n");
|
||||
}
|
||||
@ -4123,7 +4203,7 @@ LineDrag::motion (GdkEvent* event, bool)
|
||||
{
|
||||
double dy = current_pointer_y() - last_pointer_y();
|
||||
|
||||
if (event->button.state & Keyboard::SecondaryModifier) {
|
||||
if (event->button.state & ArdourKeyboard::fine_adjust_modifier ()) {
|
||||
dy *= 0.1;
|
||||
}
|
||||
|
||||
@ -4432,7 +4512,12 @@ TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
|
||||
{
|
||||
Drag::start_grab (event, cursor);
|
||||
|
||||
show_verbose_cursor_time (adjusted_current_frame (event));
|
||||
_editor->get_selection().add (_primary);
|
||||
|
||||
framepos_t where = _primary->region()->position();
|
||||
setup_snap_delta (where);
|
||||
|
||||
show_verbose_cursor_duration (where, adjusted_current_frame (event), 0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4444,14 +4529,15 @@ TimeFXDrag::motion (GdkEvent* event, bool)
|
||||
pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (grab_y());
|
||||
int layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
|
||||
int layers = tv.first->layer_display() == Overlaid ? 1 : cv->layers();
|
||||
|
||||
framepos_t const pf = adjusted_current_frame (event);
|
||||
framepos_t pf = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
|
||||
_editor->snap_to_with_modifier (pf, event);
|
||||
pf -= snap_delta (event->button.state);
|
||||
|
||||
if (pf > rv->region()->position()) {
|
||||
rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf, layers, layer);
|
||||
}
|
||||
|
||||
show_verbose_cursor_time (pf);
|
||||
show_verbose_cursor_duration (_primary->region()->position(), pf, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4909,7 +4995,7 @@ RangeMarkerBarDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
|
||||
case CreateTransportMarker:
|
||||
case CreateCDMarker:
|
||||
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::TertiaryModifier)) {
|
||||
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::CopyModifier)) {
|
||||
_copy = true;
|
||||
} else {
|
||||
_copy = false;
|
||||
@ -5130,6 +5216,7 @@ void
|
||||
NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
|
||||
{
|
||||
Drag::start_grab (event);
|
||||
setup_snap_delta (_region->source_beats_to_absolute_frames (_primary->note()->time ()));
|
||||
|
||||
if (!(_was_selected = _primary->selected())) {
|
||||
|
||||
@ -5157,7 +5244,7 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
|
||||
|
||||
/** @return Current total drag x change in frames */
|
||||
frameoffset_t
|
||||
NoteDrag::total_dx () const
|
||||
NoteDrag::total_dx (const guint state) const
|
||||
{
|
||||
/* dx in frames */
|
||||
frameoffset_t const dx = _editor->pixel_to_sample (_drags->current_pointer_x() - grab_x());
|
||||
@ -5166,15 +5253,32 @@ NoteDrag::total_dx () const
|
||||
frameoffset_t const n = _region->source_beats_to_absolute_frames (_primary->note()->time ());
|
||||
|
||||
/* new time of the primary note in session frames */
|
||||
frameoffset_t st = n + dx;
|
||||
frameoffset_t st = n + dx + snap_delta (state);
|
||||
|
||||
framepos_t const rp = _region->region()->position ();
|
||||
|
||||
/* prevent the note being dragged earlier than the region's position */
|
||||
st = max (st, rp);
|
||||
|
||||
/* snap and return corresponding delta */
|
||||
return _region->snap_frame_to_frame (st - rp) + rp - n;
|
||||
/* possibly snap and return corresponding delta */
|
||||
|
||||
bool snap = true;
|
||||
|
||||
if (ArdourKeyboard::indicates_snap (state)) {
|
||||
if (_editor->snap_mode () != SnapOff) {
|
||||
snap = false;
|
||||
}
|
||||
} else {
|
||||
if (_editor->snap_mode () == SnapOff) {
|
||||
snap = false;
|
||||
/* inverted logic here - we;re in snapoff but we've pressed the snap delta modifier */
|
||||
if (ArdourKeyboard::indicates_snap_delta (state)) {
|
||||
snap = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _region->snap_frame_to_frame (st - rp, snap) + rp - n - snap_delta (state);
|
||||
}
|
||||
|
||||
/** @return Current total drag y change in note number */
|
||||
@ -5193,10 +5297,10 @@ NoteDrag::total_dy () const
|
||||
}
|
||||
|
||||
void
|
||||
NoteDrag::motion (GdkEvent *, bool)
|
||||
NoteDrag::motion (GdkEvent * event, bool)
|
||||
{
|
||||
/* Total change in x and y since the start of the drag */
|
||||
frameoffset_t const dx = total_dx ();
|
||||
frameoffset_t const dx = total_dx (event->button.state);
|
||||
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 */
|
||||
@ -5265,7 +5369,7 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_region->note_dropped (_primary, total_dx(), total_dy());
|
||||
_region->note_dropped (_primary, total_dx (ev->button.state), total_dy());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,13 +213,18 @@ protected:
|
||||
return _last_pointer_y;
|
||||
}
|
||||
|
||||
double last_pointer_frame () const {
|
||||
ARDOUR::framepos_t last_pointer_frame () const {
|
||||
return _last_pointer_frame;
|
||||
}
|
||||
|
||||
ARDOUR::frameoffset_t snap_delta (guint const) const;
|
||||
|
||||
double current_pointer_x () const;
|
||||
double current_pointer_y () const;
|
||||
|
||||
/* sets snap delta from unsnapped pos */
|
||||
void setup_snap_delta (framepos_t pos);
|
||||
|
||||
boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*);
|
||||
|
||||
void show_verbose_cursor_time (framepos_t);
|
||||
@ -248,6 +253,11 @@ private:
|
||||
ARDOUR::framepos_t _raw_grab_frame; ///< unsnapped frame that the mouse was at when start_grab was called, or 0
|
||||
ARDOUR::framepos_t _grab_frame; ///< adjusted_frame that the mouse was at when start_grab was called, or 0
|
||||
ARDOUR::framepos_t _last_pointer_frame; ///< adjusted_frame the last time a motion occurred
|
||||
|
||||
/* difference between some key position's snapped and unsnapped
|
||||
* framepos. used for relative snap.
|
||||
*/
|
||||
ARDOUR::frameoffset_t _snap_delta;
|
||||
CursorContext::Handle _cursor_ctx; ///< cursor change context
|
||||
};
|
||||
|
||||
@ -335,8 +345,6 @@ protected:
|
||||
double _total_x_delta;
|
||||
int _last_pointer_time_axis_view;
|
||||
double _last_pointer_layer;
|
||||
bool _single_axis;
|
||||
|
||||
private:
|
||||
uint32_t _ndropzone;
|
||||
uint32_t _pdropzone;
|
||||
@ -503,6 +511,7 @@ private:
|
||||
MidiRegionView* region;
|
||||
bool relative;
|
||||
bool at_front;
|
||||
double _snap_delta;
|
||||
};
|
||||
|
||||
/** Drags to move MIDI notes */
|
||||
@ -518,7 +527,7 @@ class NoteDrag : public Drag
|
||||
|
||||
private:
|
||||
|
||||
ARDOUR::frameoffset_t total_dx () const;
|
||||
ARDOUR::frameoffset_t total_dx (const guint) const;
|
||||
int8_t total_dy () const;
|
||||
|
||||
MidiRegionView* _region;
|
||||
@ -541,7 +550,7 @@ public:
|
||||
void aborted (bool);
|
||||
|
||||
bool active (Editing::MouseMode mode) {
|
||||
return mode == Editing::MouseDraw;
|
||||
return mode == Editing::MouseDraw || mode == Editing::MouseContent;
|
||||
}
|
||||
|
||||
bool y_movement_matters () const {
|
||||
|
@ -48,6 +48,14 @@ accel_map_changed (GtkAccelMap* /*map*/,
|
||||
me->ui.setup_tooltips ();
|
||||
}
|
||||
|
||||
guint ArdourKeyboard::constraint_mod = Keyboard::SecondaryModifier;
|
||||
guint ArdourKeyboard::trim_contents_mod = Keyboard::PrimaryModifier;
|
||||
guint ArdourKeyboard::trim_overlap_mod = Keyboard::TertiaryModifier;
|
||||
guint ArdourKeyboard::trim_anchored_mod = Keyboard::TertiaryModifier;
|
||||
guint ArdourKeyboard::fine_adjust_mod = Keyboard::SecondaryModifier;
|
||||
guint ArdourKeyboard::push_points_mod = Keyboard::PrimaryModifier;
|
||||
guint ArdourKeyboard::note_size_relative_mod = Keyboard::PrimaryModifier;
|
||||
|
||||
void
|
||||
ArdourKeyboard::setup_keybindings ()
|
||||
{
|
||||
@ -174,6 +182,145 @@ ArdourKeyboard::setup_keybindings ()
|
||||
g_signal_connect (accelmap, "changed", (GCallback) accel_map_changed, this);
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
ArdourKeyboard::get_state (void)
|
||||
{
|
||||
XMLNode* node = &Keyboard::get_state ();
|
||||
char buf[32];
|
||||
|
||||
snprintf (buf, sizeof (buf), "%d", constraint_mod);
|
||||
node->add_property ("constraint-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", trim_contents_mod);
|
||||
node->add_property ("trim-contents-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", trim_overlap_mod);
|
||||
node->add_property ("trim-overlap-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", trim_anchored_mod);
|
||||
node->add_property ("trim-anchored-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", fine_adjust_mod);
|
||||
node->add_property ("fine-adjust-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", push_points_mod);
|
||||
node->add_property ("push-points-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", note_size_relative_mod);
|
||||
node->add_property ("note-size-relative-modifier", buf);
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
int
|
||||
ArdourKeyboard::set_state (const XMLNode& node, int version)
|
||||
{
|
||||
const XMLProperty* prop;
|
||||
|
||||
if ((prop = node.property ("constraint-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &constraint_mod);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("trim-contents-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &trim_contents_mod);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("trim-overlap-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &trim_overlap_mod);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("trim-anchored-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &trim_anchored_mod);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("fine-adjust-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &fine_adjust_mod);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("push-points-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &push_points_mod);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("note-size-relative-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", ¬e_size_relative_mod);
|
||||
}
|
||||
|
||||
return Keyboard::set_state (node, version);
|
||||
}
|
||||
|
||||
/* Snap and snap delta modifiers may contain each other, so we use the
|
||||
* following two methods to sort that out:
|
||||
*/
|
||||
bool
|
||||
ArdourKeyboard::indicates_snap (guint state)
|
||||
{
|
||||
const bool contains_s = Keyboard::modifier_state_contains (state, Keyboard::snap_modifier());
|
||||
const bool contains_d = Keyboard::modifier_state_contains (state, Keyboard::snap_delta_modifier());
|
||||
const bool equals_d = Keyboard::modifier_state_equals (state, Keyboard::snap_delta_modifier());
|
||||
|
||||
return (contains_s && ((contains_d && !equals_d) || !contains_d));
|
||||
}
|
||||
|
||||
bool
|
||||
ArdourKeyboard::indicates_snap_delta (guint state)
|
||||
{
|
||||
const bool contains_d = Keyboard::modifier_state_contains (state, Keyboard::snap_delta_modifier());
|
||||
const bool contains_s = Keyboard::modifier_state_contains (state, Keyboard::snap_modifier());
|
||||
const bool equals_s = Keyboard::modifier_state_equals (state, Keyboard::snap_modifier());
|
||||
|
||||
return (contains_d && ((contains_s && !equals_s) || !contains_s));
|
||||
}
|
||||
|
||||
void
|
||||
ArdourKeyboard::set_constraint_modifier (guint mod)
|
||||
{
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~constraint_mod);
|
||||
constraint_mod = mod;
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | constraint_mod);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourKeyboard::set_trim_contents_modifier (guint mod)
|
||||
{
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~trim_contents_mod);
|
||||
trim_contents_mod = mod;
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | trim_contents_mod);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourKeyboard::set_trim_overlap_modifier (guint mod)
|
||||
{
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~trim_overlap_mod);
|
||||
trim_overlap_mod = mod;
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | trim_overlap_mod);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourKeyboard::set_trim_anchored_modifier (guint mod)
|
||||
{
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~trim_anchored_mod);
|
||||
trim_anchored_mod = mod;
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | trim_anchored_mod);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourKeyboard::set_fine_adjust_modifier (guint mod)
|
||||
{
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~fine_adjust_mod);
|
||||
fine_adjust_mod = mod;
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | fine_adjust_mod);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourKeyboard::set_push_points_modifier (guint mod)
|
||||
{
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~push_points_mod);
|
||||
push_points_mod = mod;
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | push_points_mod);
|
||||
}
|
||||
|
||||
void
|
||||
ArdourKeyboard::set_note_size_relative_modifier (guint mod)
|
||||
{
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~note_size_relative_mod);
|
||||
note_size_relative_mod = mod;
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | note_size_relative_mod);
|
||||
}
|
||||
|
||||
Selection::Operation
|
||||
ArdourKeyboard::selection_type (guint state)
|
||||
{
|
||||
@ -187,5 +334,3 @@ ArdourKeyboard::selection_type (guint state)
|
||||
return Selection::Set;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,11 +32,67 @@ class ArdourKeyboard : public Gtkmm2ext::Keyboard
|
||||
public:
|
||||
ArdourKeyboard(ARDOUR_UI& ardour_ui) : ui(ardour_ui) {}
|
||||
|
||||
XMLNode& get_state (void);
|
||||
int set_state (const XMLNode&, int version);
|
||||
|
||||
void setup_keybindings ();
|
||||
|
||||
static Selection::Operation selection_type (guint state);
|
||||
|
||||
ARDOUR_UI& ui;
|
||||
|
||||
/** @param state The button state from a GdkEvent.
|
||||
* @return true if the modifier state indicates snap modifier
|
||||
*/
|
||||
static bool indicates_snap (guint state);
|
||||
|
||||
/** @param state The button state from a GdkEvent.
|
||||
* @return true if the modifier state indicates snap delta
|
||||
*/
|
||||
static bool indicates_snap_delta (guint state);
|
||||
|
||||
static void set_constraint_modifier (guint);
|
||||
/** @return Modifier mask to constrain drags in a particular direction;
|
||||
*/
|
||||
static ModifierMask constraint_modifier () { return ModifierMask (constraint_mod); }
|
||||
|
||||
static void set_trim_contents_modifier (guint);
|
||||
/** @return Modifier mask to move contents rather than region bounds during trim;
|
||||
*/
|
||||
static ModifierMask trim_contents_modifier () { return ModifierMask (trim_contents_mod); }
|
||||
|
||||
static void set_trim_overlap_modifier (guint);
|
||||
/** @return Modifier mask to remove region overlaps during trim;
|
||||
*/
|
||||
static ModifierMask trim_overlap_modifier () { return ModifierMask (trim_overlap_mod); }
|
||||
|
||||
static void set_trim_anchored_modifier (guint);
|
||||
/** @return Modifier mask to use anchored trim;
|
||||
*/
|
||||
static ModifierMask trim_anchored_modifier () { return ModifierMask (trim_anchored_mod); }
|
||||
|
||||
static void set_fine_adjust_modifier (guint);
|
||||
/** @return Modifier mask to fine adjust (control points only atm);
|
||||
*/
|
||||
static ModifierMask fine_adjust_modifier () { return ModifierMask (fine_adjust_mod); }
|
||||
|
||||
static void set_push_points_modifier (guint);
|
||||
/** @return Modifier mask to push proceeding points;
|
||||
*/
|
||||
static ModifierMask push_points_modifier () { return ModifierMask (push_points_mod); }
|
||||
|
||||
static void set_note_size_relative_modifier (guint);
|
||||
/** @return Modifier mask to resize notes relatively;
|
||||
*/
|
||||
static ModifierMask note_size_relative_modifier () { return ModifierMask (note_size_relative_mod); }
|
||||
private:
|
||||
static guint constraint_mod;
|
||||
static guint trim_contents_mod;
|
||||
static guint trim_overlap_mod;
|
||||
static guint trim_anchored_mod;
|
||||
static guint fine_adjust_mod;
|
||||
static guint push_points_mod;
|
||||
static guint note_size_relative_mod;
|
||||
};
|
||||
|
||||
#endif /* __ardour_keyboard_h__ */
|
||||
|
@ -104,6 +104,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
|
||||
, _current_range_max(0)
|
||||
, _region_relative_time_converter(r->session().tempo_map(), r->position())
|
||||
, _source_relative_time_converter(r->session().tempo_map(), r->position() - r->start())
|
||||
, _region_relative_time_converter_double(r->session().tempo_map(), r->position())
|
||||
, _active_notes(0)
|
||||
, _note_group (new ArdourCanvas::Container (group))
|
||||
, _note_diff_command (0)
|
||||
@ -151,6 +152,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
|
||||
, _current_range_max(0)
|
||||
, _region_relative_time_converter(r->session().tempo_map(), r->position())
|
||||
, _source_relative_time_converter(r->session().tempo_map(), r->position() - r->start())
|
||||
, _region_relative_time_converter_double(r->session().tempo_map(), r->position())
|
||||
, _active_notes(0)
|
||||
, _note_group (new ArdourCanvas::Container (group))
|
||||
, _note_diff_command (0)
|
||||
@ -203,6 +205,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
|
||||
, _current_range_max(0)
|
||||
, _region_relative_time_converter(other.region_relative_time_converter())
|
||||
, _source_relative_time_converter(other.source_relative_time_converter())
|
||||
, _region_relative_time_converter_double(other.region_relative_time_converter_double())
|
||||
, _active_notes(0)
|
||||
, _note_group (new ArdourCanvas::Container (get_canvas_group()))
|
||||
, _note_diff_command (0)
|
||||
@ -234,6 +237,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
|
||||
, _current_range_max(0)
|
||||
, _region_relative_time_converter(other.region_relative_time_converter())
|
||||
, _source_relative_time_converter(other.source_relative_time_converter())
|
||||
, _region_relative_time_converter_double(other.region_relative_time_converter_double())
|
||||
, _active_notes(0)
|
||||
, _note_group (new ArdourCanvas::Container (get_canvas_group()))
|
||||
, _note_diff_command (0)
|
||||
@ -1408,6 +1412,7 @@ MidiRegionView::region_resized (const PropertyChange& what_changed)
|
||||
|
||||
if (what_changed.contains (ARDOUR::Properties::position)) {
|
||||
_region_relative_time_converter.set_origin_b(_region->position());
|
||||
_region_relative_time_converter_double.set_origin_b(_region->position());
|
||||
set_duration(_region->length(), 0);
|
||||
if (_enable_display) {
|
||||
redisplay_model();
|
||||
@ -2619,22 +2624,25 @@ MidiRegionView::note_dropped(NoteBase *, frameoffset_t dt, int8_t dnote)
|
||||
}
|
||||
|
||||
/** @param x Pixel relative to the region position.
|
||||
* @param ensure_snap defaults to false. true = snap always, ignoring snap mode and magnetic snap.
|
||||
* Used for inverting the snap logic with key modifiers and snap delta calculation.
|
||||
* @return Snapped frame relative to the region position.
|
||||
*/
|
||||
framepos_t
|
||||
MidiRegionView::snap_pixel_to_sample(double x)
|
||||
MidiRegionView::snap_pixel_to_sample(double x, bool ensure_snap)
|
||||
{
|
||||
PublicEditor& editor (trackview.editor());
|
||||
return snap_frame_to_frame (editor.pixel_to_sample (x));
|
||||
return snap_frame_to_frame (editor.pixel_to_sample (x), ensure_snap);
|
||||
}
|
||||
|
||||
/** @param x Pixel relative to the region position.
|
||||
* @param ensure_snap defaults to false. true = ignore magnetic snap and snap mode (used for snap delta calculation).
|
||||
* @return Snapped pixel relative to the region position.
|
||||
*/
|
||||
double
|
||||
MidiRegionView::snap_to_pixel(double x)
|
||||
MidiRegionView::snap_to_pixel(double x, bool ensure_snap)
|
||||
{
|
||||
return (double) trackview.editor().sample_to_pixel(snap_pixel_to_sample(x));
|
||||
return (double) trackview.editor().sample_to_pixel(snap_pixel_to_sample(x, ensure_snap));
|
||||
}
|
||||
|
||||
double
|
||||
@ -2685,6 +2693,12 @@ MidiRegionView::region_frames_to_region_beats(framepos_t frames) const
|
||||
return _region_relative_time_converter.from(frames);
|
||||
}
|
||||
|
||||
double
|
||||
MidiRegionView::region_frames_to_region_beats_double (framepos_t frames) const
|
||||
{
|
||||
return _region_relative_time_converter_double.from(frames);
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::begin_resizing (bool /*at_front*/)
|
||||
{
|
||||
@ -2733,9 +2747,11 @@ MidiRegionView::begin_resizing (bool /*at_front*/)
|
||||
* a difference when multiple notes are being resized; in relative mode, each note's length is changed by the
|
||||
* amount of the drag. In non-relative mode, all selected notes are set to have the same start or end point
|
||||
* as the \a primary note.
|
||||
* @param snap_delta snap offset of the primary note in pixels. used in SnapRelative SnapDelta mode.
|
||||
* @param with_snap true if snap is to be used to determine the position, false if no snap is to be used.
|
||||
*/
|
||||
void
|
||||
MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative)
|
||||
MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap)
|
||||
{
|
||||
bool cursor_set = false;
|
||||
|
||||
@ -2746,15 +2762,15 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
|
||||
|
||||
if (at_front) {
|
||||
if (relative) {
|
||||
current_x = canvas_note->x0() + delta_x;
|
||||
current_x = canvas_note->x0() + delta_x + snap_delta;
|
||||
} else {
|
||||
current_x = primary->x0() + delta_x;
|
||||
current_x = primary->x0() + delta_x + snap_delta;
|
||||
}
|
||||
} else {
|
||||
if (relative) {
|
||||
current_x = canvas_note->x1() + delta_x;
|
||||
current_x = canvas_note->x1() + delta_x + snap_delta;
|
||||
} else {
|
||||
current_x = primary->x1() + delta_x;
|
||||
current_x = primary->x1() + delta_x + snap_delta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2768,26 +2784,47 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
|
||||
}
|
||||
|
||||
if (at_front) {
|
||||
resize_rect->set_x0 (snap_to_pixel(current_x));
|
||||
if (with_snap) {
|
||||
resize_rect->set_x0 (snap_to_pixel(current_x, true) - snap_delta);
|
||||
} else {
|
||||
resize_rect->set_x0 (current_x - snap_delta);
|
||||
}
|
||||
resize_rect->set_x1 (canvas_note->x1());
|
||||
} else {
|
||||
resize_rect->set_x1 (snap_to_pixel(current_x));
|
||||
if (with_snap) {
|
||||
resize_rect->set_x1 (snap_to_pixel(current_x, true) - snap_delta);
|
||||
} else {
|
||||
resize_rect->set_x1 (current_x - snap_delta);
|
||||
}
|
||||
resize_rect->set_x0 (canvas_note->x0());
|
||||
}
|
||||
|
||||
if (!cursor_set) {
|
||||
const double snapped_x = snap_pixel_to_sample (current_x);
|
||||
/* Convert snap delta from pixels to beats. */
|
||||
framepos_t snap_delta_samps = trackview.editor().pixel_to_sample (snap_delta);
|
||||
double snap_delta_beats;
|
||||
int sign = 1;
|
||||
|
||||
/* negative beat offsets aren't allowed */
|
||||
if (snap_delta_samps > 0) {
|
||||
snap_delta_beats = region_frames_to_region_beats_double (snap_delta_samps);
|
||||
} else if (snap_delta_samps < 0) {
|
||||
snap_delta_beats = region_frames_to_region_beats_double ( - snap_delta_samps);
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
const double snapped_x = (with_snap ? snap_pixel_to_sample (current_x, true) : trackview.editor ().pixel_to_sample (current_x));
|
||||
Evoral::Beats beats = region_frames_to_region_beats (snapped_x);
|
||||
Evoral::Beats len = Evoral::Beats();
|
||||
|
||||
if (at_front) {
|
||||
if (beats < canvas_note->note()->end_time()) {
|
||||
len = canvas_note->note()->time() - beats;
|
||||
len = canvas_note->note()->time() - beats + (sign * snap_delta_beats);
|
||||
len += canvas_note->note()->length();
|
||||
}
|
||||
} else {
|
||||
if (beats >= canvas_note->note()->time()) {
|
||||
len = beats - canvas_note->note()->time();
|
||||
len = beats - canvas_note->note()->time() - (sign * snap_delta_beats);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2808,7 +2845,7 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
|
||||
* Parameters the same as for \a update_resizing().
|
||||
*/
|
||||
void
|
||||
MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative)
|
||||
MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap)
|
||||
{
|
||||
_note_diff_command = _model->new_note_diff_command (_("resize notes"));
|
||||
|
||||
@ -2824,15 +2861,15 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
|
||||
|
||||
if (at_front) {
|
||||
if (relative) {
|
||||
current_x = canvas_note->x0() + delta_x;
|
||||
current_x = canvas_note->x0() + delta_x + snap_delta;
|
||||
} else {
|
||||
current_x = primary->x0() + delta_x;
|
||||
current_x = primary->x0() + delta_x + snap_delta;
|
||||
}
|
||||
} else {
|
||||
if (relative) {
|
||||
current_x = canvas_note->x1() + delta_x;
|
||||
current_x = canvas_note->x1() + delta_x + snap_delta;
|
||||
} else {
|
||||
current_x = primary->x1() + delta_x;
|
||||
current_x = primary->x1() + delta_x + snap_delta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2843,16 +2880,27 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
|
||||
current_x = trackview.editor().sample_to_pixel(_region->length());
|
||||
}
|
||||
|
||||
/* Convert that to a frame within the source */
|
||||
current_x = snap_pixel_to_sample (current_x) + _region->start ();
|
||||
/* Convert snap delta from pixels to beats with sign. */
|
||||
framepos_t snap_delta_samps = trackview.editor().pixel_to_sample (snap_delta);
|
||||
double snap_delta_beats;
|
||||
int sign = 1;
|
||||
|
||||
if (snap_delta_samps > 0) {
|
||||
snap_delta_beats = region_frames_to_region_beats_double (snap_delta_samps);
|
||||
} else if (snap_delta_samps < 0) {
|
||||
snap_delta_beats = region_frames_to_region_beats_double ( - snap_delta_samps);
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
/* Convert the new x position to a frame within the source */
|
||||
const framepos_t current_fr = snap_pixel_to_sample (current_x, with_snap) + _region->start ();
|
||||
|
||||
/* and then to beats */
|
||||
const Evoral::Beats x_beats = region_frames_to_region_beats (current_x);
|
||||
const Evoral::Beats x_beats = region_frames_to_region_beats (current_fr);
|
||||
|
||||
if (at_front && x_beats < canvas_note->note()->end_time()) {
|
||||
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, x_beats);
|
||||
|
||||
Evoral::Beats len = canvas_note->note()->time() - x_beats;
|
||||
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, x_beats - (sign * snap_delta_beats));
|
||||
Evoral::Beats len = canvas_note->note()->time() - x_beats + (sign * snap_delta_beats);
|
||||
len += canvas_note->note()->length();
|
||||
|
||||
if (!!len) {
|
||||
@ -2861,8 +2909,8 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
|
||||
}
|
||||
|
||||
if (!at_front) {
|
||||
const Evoral::Beats len = std::max(Evoral::Beats(1 / 512.0),
|
||||
x_beats - canvas_note->note()->time());
|
||||
Evoral::Beats len = std::max(Evoral::Beats(1 / 512.0),
|
||||
x_beats - canvas_note->note()->time() - (sign * snap_delta_beats));
|
||||
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len);
|
||||
}
|
||||
|
||||
|
@ -223,8 +223,8 @@ public:
|
||||
*/
|
||||
void begin_resizing(bool at_front);
|
||||
|
||||
void update_resizing (NoteBase*, bool, double, bool);
|
||||
void commit_resizing (NoteBase*, bool, double, bool);
|
||||
void update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap);
|
||||
void commit_resizing (NoteBase* primary, bool at_front, double delat_x, bool relative, double snap_delta, bool with_snap);
|
||||
void abort_resizing ();
|
||||
|
||||
/** Change the channel of the selection.
|
||||
@ -250,15 +250,18 @@ public:
|
||||
|
||||
/** Snap a region relative pixel coordinate to pixel units.
|
||||
* @param x a pixel coordinate relative to region start
|
||||
* @param ensure_snap do not use magnetic snap (required for snap delta calculation)
|
||||
* @return the snapped pixel coordinate relative to region start
|
||||
*/
|
||||
double snap_to_pixel(double x);
|
||||
double snap_to_pixel(double x, bool ensure_snap = false);
|
||||
|
||||
/** Snap a region relative pixel coordinate to frame units.
|
||||
* @param x a pixel coordinate relative to region start
|
||||
* @param ensure_snap ignore SnapOff and magnetic snap.
|
||||
* Required for inverting snap logic with modifier keys and snap delta calculation.
|
||||
* @return the snapped framepos_t coordinate relative to region start
|
||||
*/
|
||||
framepos_t snap_pixel_to_sample(double x);
|
||||
framepos_t snap_pixel_to_sample(double x, bool ensure_snap = false);
|
||||
|
||||
/** Convert a timestamp in beats into frames (both relative to region position) */
|
||||
framepos_t region_beats_to_region_frames(Evoral::Beats beats) const;
|
||||
@ -268,6 +271,7 @@ public:
|
||||
}
|
||||
/** Convert a timestamp in frames to beats (both relative to region position) */
|
||||
Evoral::Beats region_frames_to_region_beats(framepos_t) const;
|
||||
double region_frames_to_region_beats_double(framepos_t) const;
|
||||
|
||||
/** Convert a timestamp in beats measured from source start into absolute frames */
|
||||
framepos_t source_beats_to_absolute_frames(Evoral::Beats beats) const;
|
||||
@ -286,6 +290,10 @@ public:
|
||||
return _source_relative_time_converter;
|
||||
}
|
||||
|
||||
ARDOUR::DoubleBeatsFramesConverter const & region_relative_time_converter_double () const {
|
||||
return _region_relative_time_converter_double;
|
||||
}
|
||||
|
||||
void goto_previous_note (bool add_to_selection);
|
||||
void goto_next_note (bool add_to_selection);
|
||||
void change_note_lengths (bool, bool, Evoral::Beats beats, bool start, bool end);
|
||||
@ -400,6 +408,7 @@ private:
|
||||
|
||||
ARDOUR::BeatsFramesConverter _region_relative_time_converter;
|
||||
ARDOUR::BeatsFramesConverter _source_relative_time_converter;
|
||||
ARDOUR::DoubleBeatsFramesConverter _region_relative_time_converter_double;
|
||||
|
||||
boost::shared_ptr<ARDOUR::MidiModel> _model;
|
||||
Events _events;
|
||||
|
@ -141,10 +141,14 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
|
||||
*/
|
||||
virtual void set_snap_threshold (double t) = 0;
|
||||
|
||||
/** Snap a value according to the current snap setting. */
|
||||
/**
|
||||
* Snap a value according to the current snap setting.
|
||||
* ensure_snap overrides SnapOff and magnetic snap
|
||||
*/
|
||||
virtual void snap_to (framepos_t& first,
|
||||
ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
|
||||
bool for_mark = false) = 0;
|
||||
bool for_mark = false,
|
||||
bool ensure_snap = false) = 0;
|
||||
|
||||
/** Undo some transactions.
|
||||
* @param n Number of transactions to undo.
|
||||
|
@ -271,20 +271,22 @@ static const struct {
|
||||
{ "Option", GDK_MOD1_MASK },
|
||||
{ "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
|
||||
{ "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
|
||||
{ "Shift-Option", GDK_SHIFT_MASK|GDK_MOD1_MASK },
|
||||
{ "Option-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
|
||||
{ "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
|
||||
{ "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
|
||||
|
||||
#else
|
||||
{ "Key|Shift", GDK_SHIFT_MASK },
|
||||
{ "Control", GDK_CONTROL_MASK },
|
||||
{ "Alt (Mod1)", GDK_MOD1_MASK },
|
||||
{ "Alt", GDK_MOD1_MASK },
|
||||
{ "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
|
||||
{ "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
|
||||
{ "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
|
||||
{ "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
|
||||
{ "Alt-Windows", GDK_MOD1_MASK|GDK_MOD4_MASK },
|
||||
{ "Mod2", GDK_MOD2_MASK },
|
||||
{ "Mod3", GDK_MOD3_MASK },
|
||||
{ "Mod4", GDK_MOD4_MASK },
|
||||
{ "Windows", GDK_MOD4_MASK },
|
||||
{ "Mod5", GDK_MOD5_MASK },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
@ -319,25 +321,57 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
Table* t = manage (new Table (4, 4));
|
||||
Table* t = manage (new Table (5, 11));
|
||||
t->set_spacings (4);
|
||||
|
||||
Label* l = manage (left_aligned_label (_("Edit using:")));
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
|
||||
Label* l = manage (left_aligned_label (_("Select Keyboard layout:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, 0, 1, 0, 1, FILL | EXPAND, FILL);
|
||||
t->attach (_edit_modifier_combo, 1, 2, 0, 1, FILL | EXPAND, FILL);
|
||||
vector<string> strs;
|
||||
|
||||
for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
|
||||
strs.push_back (bf->first);
|
||||
}
|
||||
|
||||
set_popdown_strings (_keyboard_layout_selector, strs);
|
||||
_keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
|
||||
_keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_keyboard_layout_selector, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 0;
|
||||
|
||||
l = manage (left_aligned_label (_("When Clicking:")));
|
||||
l->set_name ("OptionEditorHeading");
|
||||
t->attach (*l, col, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
l = manage (left_aligned_label (_("Edit using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_edit_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
l = manage (new Label (_("+ button")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, 3, 4, 0, 1, FILL | EXPAND, FILL);
|
||||
t->attach (_edit_button_spin, 4, 5, 0, 1, FILL | EXPAND, FILL);
|
||||
t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_edit_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
_edit_button_spin.set_name ("OptionsEntry");
|
||||
_edit_button_adjustment.set_value (Keyboard::edit_button());
|
||||
_edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
set_popdown_strings (_delete_modifier_combo, dumb);
|
||||
_delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
|
||||
|
||||
@ -351,19 +385,21 @@ public:
|
||||
l = manage (left_aligned_label (_("Delete using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, 0, 1, 1, 2, FILL | EXPAND, FILL);
|
||||
t->attach (_delete_modifier_combo, 1, 2, 1, 2, FILL | EXPAND, FILL);
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_delete_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
l = manage (new Label (_("+ button")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, 3, 4, 1, 2, FILL | EXPAND, FILL);
|
||||
t->attach (_delete_button_spin, 4, 5, 1, 2, FILL | EXPAND, FILL);
|
||||
t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_delete_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
_delete_button_spin.set_name ("OptionsEntry");
|
||||
_delete_button_adjustment.set_value (Keyboard::delete_button());
|
||||
_delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
set_popdown_strings (_insert_note_modifier_combo, dumb);
|
||||
_insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
|
||||
@ -378,20 +414,165 @@ public:
|
||||
l = manage (left_aligned_label (_("Insert note using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, 0, 1, 2, 3, FILL | EXPAND, FILL);
|
||||
t->attach (_insert_note_modifier_combo, 1, 2, 2, 3, FILL | EXPAND, FILL);
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_insert_note_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
l = manage (new Label (_("+ button")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, 3, 4, 2, 3, FILL | EXPAND, FILL);
|
||||
t->attach (_insert_note_button_spin, 4, 5, 2, 3, FILL | EXPAND, FILL);
|
||||
t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_insert_note_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
_insert_note_button_spin.set_name ("OptionsEntry");
|
||||
_insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
|
||||
_insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
|
||||
|
||||
++row;
|
||||
|
||||
l = manage (left_aligned_label (_("When Beginning a Drag:")));
|
||||
l->set_name ("OptionEditorHeading");
|
||||
t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* copy modifier */
|
||||
set_popdown_strings (_copy_modifier_combo, dumb);
|
||||
_copy_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::copy_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) Keyboard::CopyModifier) {
|
||||
_copy_modifier_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Copy items using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_copy_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* constraint modifier */
|
||||
set_popdown_strings (_constraint_modifier_combo, dumb);
|
||||
_constraint_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::constraint_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) ArdourKeyboard::constraint_modifier ()) {
|
||||
_constraint_modifier_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Constrain drag using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_constraint_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
|
||||
l = manage (left_aligned_label (_("When Beginning a Trim:")));
|
||||
l->set_name ("OptionEditorHeading");
|
||||
t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* trim_contents */
|
||||
set_popdown_strings (_trim_contents_combo, dumb);
|
||||
_trim_contents_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_contents_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_contents_modifier ()) {
|
||||
_trim_contents_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Trim contents using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_trim_contents_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* anchored trim */
|
||||
set_popdown_strings (_trim_anchored_combo, dumb);
|
||||
_trim_anchored_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_anchored_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_anchored_modifier ()) {
|
||||
_trim_anchored_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Anchored trim using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
++col;
|
||||
t->attach (_trim_anchored_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* jump trim disabled for now
|
||||
set_popdown_strings (_trim_jump_combo, dumb);
|
||||
_trim_jump_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_jump_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) Keyboard::trim_jump_modifier ()) {
|
||||
_trim_jump_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Jump after trim using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
++col;
|
||||
t->attach (_trim_jump_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
*/
|
||||
|
||||
/* note resize relative */
|
||||
set_popdown_strings (_note_size_relative_combo, dumb);
|
||||
_note_size_relative_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::note_size_relative_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) ArdourKeyboard::note_size_relative_modifier ()) {
|
||||
_note_size_relative_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Resize notes relatively using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
++col;
|
||||
t->attach (_note_size_relative_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
|
||||
l = manage (left_aligned_label (_("While Dragging:")));
|
||||
l->set_name ("OptionEditorHeading");
|
||||
t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* ignore snap */
|
||||
set_popdown_strings (_snap_modifier_combo, dumb);
|
||||
_snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
|
||||
|
||||
@ -405,24 +586,100 @@ public:
|
||||
l = manage (left_aligned_label (_("Ignore snap using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, 0, 1, 3, 4, FILL | EXPAND, FILL);
|
||||
t->attach (_snap_modifier_combo, 1, 2, 3, 4, FILL | EXPAND, FILL);
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_snap_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
vector<string> strs;
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
|
||||
strs.push_back (bf->first);
|
||||
/* snap delta */
|
||||
set_popdown_strings (_snap_delta_combo, dumb);
|
||||
_snap_delta_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_delta_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) Keyboard::snap_delta_modifier ()) {
|
||||
_snap_delta_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
set_popdown_strings (_keyboard_layout_selector, strs);
|
||||
_keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
|
||||
_keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
|
||||
|
||||
l = manage (left_aligned_label (_("Keyboard layout:")));
|
||||
l = manage (left_aligned_label (_("Snap to absolute using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, 0, 1, 4, 5, FILL | EXPAND, FILL);
|
||||
t->attach (_keyboard_layout_selector, 1, 2, 4, 5, FILL | EXPAND, FILL);
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_snap_delta_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
|
||||
l = manage (left_aligned_label (_("While Trimming:")));
|
||||
l->set_name ("OptionEditorHeading");
|
||||
t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* trim_overlap */
|
||||
set_popdown_strings (_trim_overlap_combo, dumb);
|
||||
_trim_overlap_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_overlap_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_overlap_modifier ()) {
|
||||
_trim_overlap_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Resize overlaped regions using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_trim_overlap_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
|
||||
l = manage (left_aligned_label (_("While Dragging Control Points:")));
|
||||
l->set_name ("OptionEditorHeading");
|
||||
t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* fine adjust */
|
||||
set_popdown_strings (_fine_adjust_combo, dumb);
|
||||
_fine_adjust_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::fine_adjust_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) ArdourKeyboard::fine_adjust_modifier ()) {
|
||||
_fine_adjust_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Fine adjust using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_fine_adjust_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
++row;
|
||||
col = 1;
|
||||
|
||||
/* push points */
|
||||
set_popdown_strings (_push_points_combo, dumb);
|
||||
_push_points_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::push_points_modifier_chosen));
|
||||
|
||||
for (int x = 0; modifiers[x].name; ++x) {
|
||||
if (modifiers[x].modifier == (guint) ArdourKeyboard::push_points_modifier ()) {
|
||||
_push_points_combo.set_active_text (S_(modifiers[x].name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l = manage (left_aligned_label (_("Push points using:")));
|
||||
l->set_name ("OptionsLabel");
|
||||
|
||||
t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
|
||||
t->attach (_push_points_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
|
||||
|
||||
_box->pack_start (*t, false, false);
|
||||
}
|
||||
@ -478,6 +735,18 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void copy_modifier_chosen ()
|
||||
{
|
||||
string const txt = _copy_modifier_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
Keyboard::set_copy_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void insert_note_modifier_chosen ()
|
||||
{
|
||||
string const txt = _insert_note_modifier_combo.get_active_text();
|
||||
@ -502,6 +771,102 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void snap_delta_modifier_chosen ()
|
||||
{
|
||||
string const txt = _snap_delta_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
Keyboard::set_snap_delta_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void constraint_modifier_chosen ()
|
||||
{
|
||||
string const txt = _constraint_modifier_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
ArdourKeyboard::set_constraint_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void trim_contents_modifier_chosen ()
|
||||
{
|
||||
string const txt = _trim_contents_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
ArdourKeyboard::set_trim_contents_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void trim_overlap_modifier_chosen ()
|
||||
{
|
||||
string const txt = _trim_overlap_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
ArdourKeyboard::set_trim_overlap_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void trim_anchored_modifier_chosen ()
|
||||
{
|
||||
string const txt = _trim_anchored_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
ArdourKeyboard::set_trim_anchored_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fine_adjust_modifier_chosen ()
|
||||
{
|
||||
string const txt = _fine_adjust_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
ArdourKeyboard::set_fine_adjust_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void push_points_modifier_chosen ()
|
||||
{
|
||||
string const txt = _push_points_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
ArdourKeyboard::set_push_points_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void note_size_relative_modifier_chosen ()
|
||||
{
|
||||
string const txt = _note_size_relative_combo.get_active_text();
|
||||
|
||||
for (int i = 0; modifiers[i].name; ++i) {
|
||||
if (txt == _(modifiers[i].name)) {
|
||||
ArdourKeyboard::set_note_size_relative_modifier (modifiers[i].modifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delete_button_changed ()
|
||||
{
|
||||
Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
|
||||
@ -520,8 +885,18 @@ private:
|
||||
ComboBoxText _keyboard_layout_selector;
|
||||
ComboBoxText _edit_modifier_combo;
|
||||
ComboBoxText _delete_modifier_combo;
|
||||
ComboBoxText _copy_modifier_combo;
|
||||
ComboBoxText _insert_note_modifier_combo;
|
||||
ComboBoxText _snap_modifier_combo;
|
||||
ComboBoxText _snap_delta_combo;
|
||||
ComboBoxText _constraint_modifier_combo;
|
||||
ComboBoxText _trim_contents_combo;
|
||||
ComboBoxText _trim_overlap_combo;
|
||||
ComboBoxText _trim_anchored_combo;
|
||||
ComboBoxText _trim_jump_combo;
|
||||
ComboBoxText _fine_adjust_combo;
|
||||
ComboBoxText _push_points_combo;
|
||||
ComboBoxText _note_size_relative_combo;
|
||||
Adjustment _delete_button_adjustment;
|
||||
SpinButton _delete_button_spin;
|
||||
Adjustment _edit_button_adjustment;
|
||||
|
@ -939,10 +939,12 @@ RegionView::move_contents (frameoffset_t distance)
|
||||
|
||||
/** Snap a frame offset within our region using the current snap settings.
|
||||
* @param x Frame offset from this region's position.
|
||||
* @param ensure_snap whether to ignore snap_mode (in the case of SnapOff) and magnetic snap.
|
||||
* Used when inverting snap mode logic with key modifiers, or snap distance calculation.
|
||||
* @return Snapped frame offset from this region's position.
|
||||
*/
|
||||
frameoffset_t
|
||||
RegionView::snap_frame_to_frame (frameoffset_t x) const
|
||||
RegionView::snap_frame_to_frame (frameoffset_t x, bool ensure_snap) const
|
||||
{
|
||||
PublicEditor& editor = trackview.editor();
|
||||
|
||||
@ -951,12 +953,12 @@ RegionView::snap_frame_to_frame (frameoffset_t x) const
|
||||
|
||||
/* try a snap in either direction */
|
||||
framepos_t frame = session_frame;
|
||||
editor.snap_to (frame, RoundNearest);
|
||||
editor.snap_to (frame, RoundNearest, false, ensure_snap);
|
||||
|
||||
/* if we went off the beginning of the region, snap forwards */
|
||||
if (frame < _region->position ()) {
|
||||
frame = session_frame;
|
||||
editor.snap_to (frame, RoundUpAlways);
|
||||
editor.snap_to (frame, RoundUpAlways, false, ensure_snap);
|
||||
}
|
||||
|
||||
/* back to region relative */
|
||||
|
@ -121,8 +121,8 @@ class RegionView : public TimeAxisViewItem
|
||||
}
|
||||
};
|
||||
|
||||
ARDOUR::frameoffset_t snap_frame_to_frame (ARDOUR::frameoffset_t) const;
|
||||
|
||||
ARDOUR::frameoffset_t snap_frame_to_frame (ARDOUR::frameoffset_t, bool ensure_snap = false) const;
|
||||
|
||||
protected:
|
||||
|
||||
/** Allows derived types to specify their visibility requirements
|
||||
|
@ -86,7 +86,7 @@ Event<Timestamp>::Event(const Event& copy, bool owns_buf)
|
||||
, _nominal_time(copy._nominal_time)
|
||||
, _size(copy._size)
|
||||
, _buf(copy._buf)
|
||||
, _id(copy.id())
|
||||
, _id (next_event_id ())
|
||||
, _owns_buf(owns_buf)
|
||||
{
|
||||
if (owns_buf) {
|
||||
@ -110,7 +110,7 @@ template<typename Timestamp>
|
||||
const Event<Timestamp>&
|
||||
Event<Timestamp>::operator=(const Event& copy)
|
||||
{
|
||||
_id = copy.id(); // XXX is this right? do we want ID copy semantics?
|
||||
_id = next_event_id ();
|
||||
_type = copy._type;
|
||||
_original_time = copy._original_time;
|
||||
_nominal_time = copy._nominal_time;
|
||||
|
@ -115,13 +115,22 @@ class LIBGTKMM2EXT_API Keyboard : public sigc::trackable, PBD::Stateful
|
||||
static bool no_modifiers_active (guint state);
|
||||
|
||||
static void set_snap_modifier (guint);
|
||||
|
||||
/** @return Modifier mask to temporarily toggle grid setting; with this modifier
|
||||
* - magnetic or normal grid should become no grid and
|
||||
* - no grid should become normal grid
|
||||
*/
|
||||
static ModifierMask snap_modifier () { return ModifierMask (snap_mod); }
|
||||
|
||||
static void set_snap_delta_modifier (guint);
|
||||
/** @return Modifier mask to temporarily toggle between relative and absolute grid setting.
|
||||
* Absolute grid is for aligning objects with the grid lines.
|
||||
* Relative grid is for maintaining an initial position relative to the grid lines.
|
||||
* With this modifier:
|
||||
* - magnetic or normal grid should snap absolutely to the grid lines
|
||||
* - no grid should become absolute grid.
|
||||
*/
|
||||
static ModifierMask snap_delta_modifier () { return ModifierMask (snap_delta_mod); }
|
||||
|
||||
static guint edit_button() { return edit_but; }
|
||||
static void set_edit_button (guint);
|
||||
static guint edit_modifier() { return edit_mod; }
|
||||
@ -186,6 +195,7 @@ class LIBGTKMM2EXT_API Keyboard : public sigc::trackable, PBD::Stateful
|
||||
static guint insert_note_but;
|
||||
static guint insert_note_mod;
|
||||
static guint snap_mod;
|
||||
static guint snap_delta_mod;
|
||||
static guint button2_modifiers;
|
||||
static Gtk::Window* current_window;
|
||||
static std::string user_keybindings_path;
|
||||
|
@ -58,7 +58,6 @@ guint Keyboard::delete_but = 3;
|
||||
guint Keyboard::delete_mod = GDK_SHIFT_MASK;
|
||||
guint Keyboard::insert_note_but = 1;
|
||||
guint Keyboard::insert_note_mod = GDK_CONTROL_MASK;
|
||||
guint Keyboard::snap_mod = GDK_MOD3_MASK;
|
||||
|
||||
#ifdef GTKOSX
|
||||
|
||||
@ -77,6 +76,9 @@ const char* Keyboard::level4_modifier_name() { return _("Option"); }
|
||||
const char* Keyboard::copy_modifier_name() { return _("Control"); }
|
||||
const char* Keyboard::rangeselect_modifier_name() { return S_("Key|Shift"); }
|
||||
|
||||
guint Keyboard::snap_mod = Keyboard::Level4Modifier|Keyboard::TertiaryModifier; // XXX this is probably completely wrong
|
||||
guint Keyboard::snap_delta_mod = Keyboard::Level4Modifier;
|
||||
|
||||
#else
|
||||
|
||||
guint Keyboard::PrimaryModifier = GDK_CONTROL_MASK; // Control
|
||||
@ -94,6 +96,9 @@ const char* Keyboard::level4_modifier_name() { return _("Meta"); }
|
||||
const char* Keyboard::copy_modifier_name() { return _("Control"); }
|
||||
const char* Keyboard::rangeselect_modifier_name() { return S_("Key|Shift"); }
|
||||
|
||||
guint Keyboard::snap_mod = Keyboard::SecondaryModifier|Keyboard::Level4Modifier;
|
||||
guint Keyboard::snap_delta_mod = Keyboard::SecondaryModifier;
|
||||
|
||||
#endif
|
||||
|
||||
guint Keyboard::GainFineScaleModifier = Keyboard::PrimaryModifier;
|
||||
@ -103,7 +108,6 @@ guint Keyboard::ScrollZoomVerticalModifier = Keyboard::SecondaryModifier;
|
||||
guint Keyboard::ScrollZoomHorizontalModifier = Keyboard::PrimaryModifier;
|
||||
guint Keyboard::ScrollHorizontalModifier = Keyboard::TertiaryModifier;
|
||||
|
||||
|
||||
Keyboard* Keyboard::_the_keyboard = 0;
|
||||
Gtk::Window* Keyboard::current_window = 0;
|
||||
bool Keyboard::_some_magic_widget_has_focus = false;
|
||||
@ -169,6 +173,8 @@ Keyboard::get_state (void)
|
||||
XMLNode* node = new XMLNode ("Keyboard");
|
||||
char buf[32];
|
||||
|
||||
snprintf (buf, sizeof (buf), "%d", CopyModifier);
|
||||
node->add_property ("copy-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", edit_but);
|
||||
node->add_property ("edit-button", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", edit_mod);
|
||||
@ -179,6 +185,8 @@ Keyboard::get_state (void)
|
||||
node->add_property ("delete-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", snap_mod);
|
||||
node->add_property ("snap-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", snap_delta_mod);
|
||||
node->add_property ("snap-delta-modifier", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", insert_note_but);
|
||||
node->add_property ("insert-note-button", buf);
|
||||
snprintf (buf, sizeof (buf), "%d", insert_note_mod);
|
||||
@ -192,6 +200,10 @@ Keyboard::set_state (const XMLNode& node, int /*version*/)
|
||||
{
|
||||
const XMLProperty* prop;
|
||||
|
||||
if ((prop = node.property ("copy-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &CopyModifier);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("edit-button")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &edit_but);
|
||||
}
|
||||
@ -212,6 +224,10 @@ Keyboard::set_state (const XMLNode& node, int /*version*/)
|
||||
sscanf (prop->value().c_str(), "%d", &snap_mod);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("snap-delta-modifier")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &snap_delta_mod);
|
||||
}
|
||||
|
||||
if ((prop = node.property ("insert-note-button")) != 0) {
|
||||
sscanf (prop->value().c_str(), "%d", &insert_note_but);
|
||||
}
|
||||
@ -466,6 +482,14 @@ Keyboard::set_snap_modifier (guint mod)
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_mod);
|
||||
}
|
||||
|
||||
void
|
||||
Keyboard::set_snap_delta_modifier (guint mod)
|
||||
{
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_delta_mod);
|
||||
snap_delta_mod = mod;
|
||||
RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_delta_mod);
|
||||
}
|
||||
|
||||
bool
|
||||
Keyboard::is_edit_event (GdkEventButton *ev)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user