MIDI: ctrl-d now duplicates selected notes
This commit also fixes selection-after-paste, so that the selection is always the newly pasted notes.
This commit is contained in:
parent
8d4516228a
commit
9e77d8923a
|
@ -487,6 +487,7 @@ This mode provides many different operations on both regions and control points,
|
|||
@notes|Notes/alt-add-select-previous|<@PRIMARY@><@TERTIARY@>ISO_Left_Tab|Add previous note to selection
|
||||
@notes|Notes/extend-selection|<@PRIMARY@>e|Extend selection to end of region
|
||||
@notes|Notes/invert-selection|<@PRIMARY@>i|Invert note selection
|
||||
@notes|Notes/duplicate-selection|<@PRIMARY@>d|Duplicate note selection
|
||||
|
||||
@rec|Recorder/arm-all|<@PRIMARY@>r|record arm all tracks
|
||||
@rec|Recorder/arm-none|<@PRIMARY@><@TERTIARY@>r|disable record arm of all tracks
|
||||
|
|
|
@ -798,6 +798,7 @@ Editor::register_midi_actions (Bindings* midi_bindings)
|
|||
ActionManager::register_action (_midi_actions, X_("clear-selection"), _("Clear Note Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::clear_note_selection));
|
||||
ActionManager::register_action (_midi_actions, X_("invert-selection"), _("Invert Note Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::invert_selection));
|
||||
ActionManager::register_action (_midi_actions, X_("extend-selection"), _("Extend Note Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::extend_selection));
|
||||
ActionManager::register_action (_midi_actions, X_("duplicate-selection"), _("Duplicate Note Selection"), sigc::bind (sigc::mem_fun (*this, &Editor::midi_action), &MidiRegionView::duplicate_selection));
|
||||
|
||||
/* Lengthen */
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
|
|||
, _last_event_y (0)
|
||||
, _entered (false)
|
||||
, _entered_note (0)
|
||||
, _pasting (false)
|
||||
, _mouse_changed_selection (false)
|
||||
{
|
||||
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
|
||||
|
@ -1935,7 +1936,9 @@ MidiRegionView::add_note(const boost::shared_ptr<NoteType> note, bool visible)
|
|||
}
|
||||
}
|
||||
|
||||
if (_marked_for_selection.find(note) != _marked_for_selection.end()) {
|
||||
if (_pasting) {
|
||||
note_selected (event, true);
|
||||
} else if (_marked_for_selection.find(note) != _marked_for_selection.end()) {
|
||||
note_selected (event, false);
|
||||
}
|
||||
|
||||
|
@ -3800,20 +3803,61 @@ MidiRegionView::selection_as_cut_buffer () const
|
|||
return cb;
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::duplicate_selection ()
|
||||
{
|
||||
std::cerr << "dup selection\n";
|
||||
|
||||
if (_selection.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* find last selection position */
|
||||
timepos_t dup_pos = timepos_t (Temporal::BeatTime);
|
||||
|
||||
for (Selection::const_iterator s = _selection.begin(); s != _selection.end(); ++s) {
|
||||
dup_pos = std::max (dup_pos, _region->source_beats_to_absolute_time ((*s)->note()->end_time()));
|
||||
}
|
||||
|
||||
PublicEditor& editor (trackview.editor());
|
||||
|
||||
/* Use a local Selection object that will not affect the global
|
||||
* selection. Possible ::paste() should accept a different kind of
|
||||
* object but that would conflict with the Editor API.
|
||||
*/
|
||||
|
||||
::Selection local_selection (&editor, false);
|
||||
MidiNoteSelection note_selection;
|
||||
|
||||
note_selection.push_back (selection_as_cut_buffer());
|
||||
|
||||
local_selection.set (note_selection);
|
||||
|
||||
PasteContext ctxt (0, 1, ItemCounts(), false);
|
||||
paste (dup_pos, local_selection, ctxt);
|
||||
}
|
||||
|
||||
/** This method handles undo */
|
||||
bool
|
||||
MidiRegionView::paste (timepos_t const & pos, const ::Selection& selection, PasteContext& ctx)
|
||||
{
|
||||
bool commit = false;
|
||||
|
||||
// Paste notes, if available
|
||||
MidiNoteSelection::const_iterator m = selection.midi_notes.get_nth(ctx.counts.n_notes());
|
||||
|
||||
if (m != selection.midi_notes.end()) {
|
||||
|
||||
ctx.counts.increase_n_notes();
|
||||
|
||||
if (!(*m)->empty()) {
|
||||
commit = true;
|
||||
}
|
||||
paste_internal(pos, ctx.count, ctx.times, **m);
|
||||
|
||||
/* clear any current selection because we're going to select the duplicated ones */
|
||||
clear_note_selection ();
|
||||
|
||||
paste_internal (pos, ctx.count, ctx.times, **m);
|
||||
}
|
||||
|
||||
// Paste control points to automation children, if available
|
||||
|
@ -3842,6 +3886,8 @@ MidiRegionView::paste_internal (timepos_t const & pos, unsigned paste_count, flo
|
|||
return;
|
||||
}
|
||||
|
||||
PBD::Unwinder<bool> puw (_pasting, true);
|
||||
|
||||
start_note_diff_command (_("paste"));
|
||||
|
||||
const Temporal::Beats snap_beats = get_grid_beats(pos);
|
||||
|
@ -3889,6 +3935,9 @@ MidiRegionView::paste_internal (timepos_t const & pos, unsigned paste_count, flo
|
|||
trackview.session()->add_command (new StatefulDiffCommand (_region));
|
||||
}
|
||||
|
||||
_marked_for_selection.clear ();
|
||||
_pending_note_selection.clear ();
|
||||
|
||||
apply_diff (true);
|
||||
}
|
||||
|
||||
|
|
|
@ -208,6 +208,7 @@ public:
|
|||
void select_range(Temporal::timepos_t const & start, Temporal::timepos_t const & end);
|
||||
void invert_selection ();
|
||||
void extend_selection ();
|
||||
void duplicate_selection ();
|
||||
|
||||
Temporal::Beats earliest_in_selection ();
|
||||
void move_selection(Temporal::timecnt_t const & dx, double dy, double cumulative_dy);
|
||||
|
@ -545,6 +546,7 @@ public:
|
|||
double _last_event_y;
|
||||
bool _entered;
|
||||
NoteBase* _entered_note;
|
||||
bool _pasting;
|
||||
|
||||
bool _mouse_changed_selection;
|
||||
|
||||
|
|
Loading…
Reference in New Issue