summaryrefslogtreecommitdiff
path: root/gtk2_ardour/midi_region_view.cc
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2015-01-11 04:07:31 +1100
committernick_m <mainsbridge@gmail.com>2015-01-11 04:07:31 +1100
commit44203ce955f33135065456f55f1f685131174ba6 (patch)
tree623864e0e94e7d1fb59c5ee24bdbd16f551aee4b /gtk2_ardour/midi_region_view.cc
parent9e873acedb35ee0077f128a2da1648b65c78eeeb (diff)
Fix AutomationTrackItem rubberband click thinking it was unhandled.
Fix several other cases where a single mouse click could cause several (not nested) selection ops. Fix missing selection memento for midi notes and midi commands. Rename some variables. Fix random style issues.
Diffstat (limited to 'gtk2_ardour/midi_region_view.cc')
-rw-r--r--gtk2_ardour/midi_region_view.cc102
1 files changed, 96 insertions, 6 deletions
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 97cb11529e..6e257cc0ee 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -123,6 +123,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
+ , _mouse_changed_selection (false)
{
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
_note_group->raise_to_top();
@@ -169,6 +170,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
+ , _mouse_changed_selection (false)
{
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
_note_group->raise_to_top();
@@ -220,6 +222,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
+ , _mouse_changed_selection (false)
{
init (false);
}
@@ -250,6 +253,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
+ , _mouse_changed_selection (false)
{
init (true);
}
@@ -502,6 +506,7 @@ MidiRegionView::button_press (GdkEventButton* ev)
}
_pressed_button = ev->button;
+ _mouse_changed_selection = false;
return true;
}
@@ -532,12 +537,14 @@ MidiRegionView::button_release (GdkEventButton* ev)
case MouseRange:
/* no motion occured - simple click */
clear_selection ();
+ _mouse_changed_selection = true;
break;
case MouseContent:
case MouseTimeFX:
{
clear_selection();
+ _mouse_changed_selection = true;
if (Keyboard::is_insert_note_event(ev)) {
@@ -591,6 +598,11 @@ MidiRegionView::button_release (GdkEventButton* ev)
break;
}
+ if(_mouse_changed_selection) {
+ trackview.editor().begin_reversible_selection_op (_("Mouse Selection Change"));
+ trackview.editor().commit_reversible_selection_op ();
+ }
+
return false;
}
@@ -643,6 +655,7 @@ MidiRegionView::motion (GdkEventMotion* ev)
editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast<Editor *> (&editor), this), (GdkEvent *) ev);
if (!Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
clear_selection ();
+ _mouse_changed_selection = true;
}
_mouse_state = SelectRectDragging;
return true;
@@ -747,22 +760,32 @@ MidiRegionView::key_press (GdkEventKey* ev)
} else if (ev->keyval == GDK_Tab) {
+ trackview.editor().begin_reversible_selection_op (_("Select Adjacent Note"));
+
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
} else {
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
}
+
+ trackview.editor().commit_reversible_selection_op();
+
return true;
} else if (ev->keyval == GDK_ISO_Left_Tab) {
/* Shift-TAB generates ISO Left Tab, for some reason */
+ trackview.editor().begin_reversible_selection_op (_("Select Adjacent Note"));
+
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
} else {
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
}
+
+ trackview.editor().commit_reversible_selection_op();
+
return true;
@@ -946,9 +969,11 @@ MidiRegionView::create_note_at (framepos_t t, double y, Evoral::Beats length, bo
view->update_note_range(new_note->note());
+ trackview.editor().begin_reversible_command(_("add note"));
MidiModel::NoteDiffCommand* cmd = _model->new_note_diff_command(_("add note"));
cmd->add (new_note);
_model->apply_command(*trackview.session(), cmd);
+ trackview.editor().commit_reversible_command();
play_midi_note (new_note);
}
@@ -982,8 +1007,8 @@ MidiRegionView::display_model(boost::shared_ptr<MidiModel> model)
content_connection.disconnect ();
_model->ContentsChanged.connect (content_connection, invalidator (*this), boost::bind (&MidiRegionView::redisplay_model, this), gui_context());
-
- clear_events ();
+ /* Don't signal as nobody else needs to know until selection has been altered.*/
+ clear_events (false);
if (_enable_display) {
redisplay_model();
@@ -994,6 +1019,7 @@ void
MidiRegionView::start_note_diff_command (string name)
{
if (!_note_diff_command) {
+ trackview.editor().begin_reversible_command (name);
_note_diff_command = _model->new_note_diff_command (name);
}
}
@@ -1044,6 +1070,7 @@ void
MidiRegionView::apply_diff (bool as_subcommand)
{
bool add_or_remove;
+ bool commit = false;
if (!_note_diff_command) {
return;
@@ -1060,6 +1087,7 @@ MidiRegionView::apply_diff (bool as_subcommand)
_model->apply_command_as_subcommand (*trackview.session(), _note_diff_command);
} else {
_model->apply_command (*trackview.session(), _note_diff_command);
+ commit = true;
}
_note_diff_command = 0;
@@ -1070,6 +1098,9 @@ MidiRegionView::apply_diff (bool as_subcommand)
}
_marked_for_velocity.clear();
+ if (commit) {
+ trackview.editor().commit_reversible_command ();
+ }
}
void
@@ -1100,6 +1131,27 @@ MidiRegionView::find_canvas_note (boost::shared_ptr<NoteType> note)
return 0;
}
+/** This version finds any canvas note matching the supplied note.*/
+NoteBase*
+MidiRegionView::find_canvas_note (NoteType note)
+{
+ if (_optimization_iterator != _events.end()) {
+ ++_optimization_iterator;
+ }
+
+ if (_optimization_iterator != _events.end() && (*(*_optimization_iterator)->note()) == note) {
+ return *_optimization_iterator;
+ }
+
+ for (_optimization_iterator = _events.begin(); _optimization_iterator != _events.end(); ++_optimization_iterator) {
+ if (*((*_optimization_iterator)->note()) == note) {
+ return *_optimization_iterator;
+ }
+ }
+
+ return 0;
+}
+
void
MidiRegionView::get_events (Events& e, Evoral::Sequence<Evoral::Beats>::NoteOperator op, uint8_t val, int chan_mask)
{
@@ -1173,6 +1225,13 @@ MidiRegionView::redisplay_model()
add_note (note, visible);
}
+ set<boost::shared_ptr<NoteType> >::iterator it;
+ for (it = _pending_note_selection.begin(); it != _pending_note_selection.end(); ++it) {
+ if (*(*it) == *note) {
+ add_to_selection (cne);
+ }
+ }
+
} else {
if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) {
@@ -1182,7 +1241,6 @@ MidiRegionView::redisplay_model()
}
}
-
/* remove note items that are no longer valid */
if (!empty_when_starting) {
@@ -1213,6 +1271,7 @@ MidiRegionView::redisplay_model()
_marked_for_selection.clear ();
_marked_for_velocity.clear ();
+ _pending_note_selection.clear ();
/* we may have caused _events to contain things out of order (e.g. if a note
moved earlier or later). we don't generally need them in time order, but
@@ -1909,7 +1968,9 @@ MidiRegionView::get_patch_key_at (Evoral::Beats time, uint8_t channel, MIDI::Nam
void
MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPrimaryKey& new_patch)
{
- MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("alter patch change"));
+ string name = _("alter patch change");
+ trackview.editor().begin_reversible_command (name);
+ MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
if (pc.patch()->program() != new_patch.program()) {
c->change_program (pc.patch (), new_patch.program());
@@ -1921,6 +1982,7 @@ MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPri
}
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -1929,7 +1991,9 @@ MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPri
void
MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const Evoral::PatchChange<Evoral::Beats> & new_change)
{
- MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("alter patch change"));
+ string name = _("alter patch change");
+ trackview.editor().begin_reversible_command (name);
+ MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
if (old_change->time() != new_change.time()) {
c->change_time (old_change, new_change.time());
@@ -1948,6 +2012,7 @@ MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const
}
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -1962,8 +2027,10 @@ void
MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beats> const & patch)
{
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
+ string name = _("add patch change");
- MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("add patch change"));
+ trackview.editor().begin_reversible_command (name);
+ MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
c->add (MidiModel::PatchChangePtr (
new Evoral::PatchChange<Evoral::Beats> (
absolute_frames_to_source_beats (_region->position() + t),
@@ -1973,6 +2040,7 @@ MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beat
);
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -1981,9 +2049,11 @@ MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beat
void
MidiRegionView::move_patch_change (PatchChange& pc, Evoral::Beats t)
{
+ trackview.editor().begin_reversible_command (_("move patch change"));
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("move patch change"));
c->change_time (pc.patch (), t);
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -1992,9 +2062,11 @@ MidiRegionView::move_patch_change (PatchChange& pc, Evoral::Beats t)
void
MidiRegionView::delete_patch_change (PatchChange* pc)
{
+ trackview.editor().begin_reversible_command (_("delete patch change"));
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("delete patch change"));
c->remove (pc->patch ());
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -2143,6 +2215,24 @@ MidiRegionView::invert_selection ()
}
}
+/** Used for selection undo/redo.
+ The requested notes most likely won't exist in the view until the next model redisplay.
+*/
+void
+MidiRegionView::select_notes (list<boost::shared_ptr<NoteType> > notes)
+{
+ NoteBase* cne;
+ list<boost::shared_ptr<NoteType> >::iterator n;
+
+ for (n = notes.begin(); n != notes.end(); ++n) {
+ if ((cne = find_canvas_note(*(*n))) != 0) {
+ add_to_selection (cne);
+ } else {
+ _pending_note_selection.insert(*n);
+ }
+ }
+}
+
void
MidiRegionView::select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend)
{