lollis: make a single drag be represented by a single Command object (for undo/redo)

This commit is contained in:
Paul Davis 2023-06-24 12:42:30 -06:00
parent 006779d4c3
commit 60256282e3
4 changed files with 64 additions and 10 deletions

View file

@ -3384,15 +3384,62 @@ MidiRegionView::change_note_length (NoteBase* event, Temporal::Beats t)
{ {
note_diff_add_change (event, MidiModel::NoteDiffCommand::Length, t); note_diff_add_change (event, MidiModel::NoteDiffCommand::Length, t);
} }
void void
MidiRegionView::begin_drag_edit (std::string const & why)
{
start_note_diff_command (why);
}
void
MidiRegionView::drag_apply ()
{
if (!_note_diff_command) {
return;
}
bool add_or_remove = _note_diff_command->adds_or_removes();
if (add_or_remove) {
// Mark all selected notes for selection when model reloads
for (auto const & sel : _selection) {
_marked_for_selection.insert (sel->note());
}
}
{
PBD::Unwinder<bool> puw (_select_all_notes_after_add, true);
/*note that we don't use as_commit here, because that would BEGIN a new undo record; we already have one underway*/
_model->apply_diff_command_as_subcommand (*trackview.session(), _note_diff_command);
}
}
void
MidiRegionView::mid_drag_edit ()
{
drag_apply ();
_note_diff_command = _model->new_note_diff_command ();
}
void
MidiRegionView::end_drag_edit (bool apply)
{
if (apply) {
drag_apply ();
trackview.editor().commit_reversible_command ();
_note_diff_command = nullptr;
} else {
abort_note_diff ();
}
}
bool
MidiRegionView::set_velocity_for_notes (std::vector<NoteBase*> notes, int velocity) MidiRegionView::set_velocity_for_notes (std::vector<NoteBase*> notes, int velocity)
{ {
/* Does not use selection, used when drawing/dragging in velocity lane */ /* Does not use selection, used when drawing/dragging in velocity lane */
bool changed = false; bool changed = false;
start_note_diff_command (_("set velocities"));
for (auto & note : notes) { for (auto & note : notes) {
int delta = velocity - note->note()->velocity(); int delta = velocity - note->note()->velocity();
@ -3405,11 +3452,7 @@ MidiRegionView::set_velocity_for_notes (std::vector<NoteBase*> notes, int veloci
change_note_velocity (note, delta, true); change_note_velocity (note, delta, true);
} }
if (changed) { return changed;
apply_note_diff ();
} else {
abort_note_diff ();
}
} }
void void

View file

@ -180,6 +180,10 @@ public:
void end_write(); void end_write();
void extend_active_notes(); void extend_active_notes();
void begin_drag_edit (std::string const & why);
void mid_drag_edit ();
void end_drag_edit (bool apply);
void display_model(std::shared_ptr<ARDOUR::MidiModel> model); void display_model(std::shared_ptr<ARDOUR::MidiModel> model);
/* note_diff commands should start here; this initiates an undo record */ /* note_diff commands should start here; this initiates an undo record */
@ -288,7 +292,7 @@ public:
void change_note_lengths (bool, bool, Temporal::Beats beats, bool start, bool end); void change_note_lengths (bool, bool, Temporal::Beats beats, bool start, bool end);
void change_velocities (bool up, bool fine, bool allow_smush, bool all_together); void change_velocities (bool up, bool fine, bool allow_smush, bool all_together);
void set_velocity (NoteBase* primary, int velocity); void set_velocity (NoteBase* primary, int velocity);
void set_velocity_for_notes (std::vector<NoteBase*> notes, int velocity); bool set_velocity_for_notes (std::vector<NoteBase*> notes, int velocity);
void transpose (bool up, bool fine, bool allow_smush); void transpose (bool up, bool fine, bool allow_smush);
void nudge_notes (bool forward, bool fine); void nudge_notes (bool forward, bool fine);
void channel_edit (); void channel_edit ();
@ -583,6 +587,7 @@ public:
void model_changed (); void model_changed ();
void sync_ghost_selection (NoteBase*); void sync_ghost_selection (NoteBase*);
void drag_apply ();
}; };

View file

@ -55,6 +55,7 @@ VelocityGhostRegion::VelocityGhostRegion (MidiRegionView& mrv, TimeAxisView& tv,
, dragging (false) , dragging (false)
, dragging_line (nullptr) , dragging_line (nullptr)
, last_drag_x (-1) , last_drag_x (-1)
, drag_did_change (false)
{ {
base_rect->Event.connect (sigc::mem_fun (*this, &VelocityGhostRegion::base_event)); base_rect->Event.connect (sigc::mem_fun (*this, &VelocityGhostRegion::base_event));
} }
@ -79,13 +80,14 @@ VelocityGhostRegion::base_event (GdkEvent* ev)
} else if (last_drag_x < ev->motion.x) { } else if (last_drag_x < ev->motion.x) {
/* rightward, "later" motion */ /* rightward, "later" motion */
lollis_between (last_drag_x, ev->motion.x, affected_lollis); lollis_between (last_drag_x, ev->motion.x, affected_lollis);
} else { } else {
/* leftward, "earlier" motion */ /* leftward, "earlier" motion */
lollis_between (ev->motion.x, last_drag_x, affected_lollis); lollis_between (ev->motion.x, last_drag_x, affected_lollis);
} }
if (!affected_lollis.empty()) { if (!affected_lollis.empty()) {
int velocity = y_position_to_velocity (r.height() - (r.y1 - ev->motion.y)); int velocity = y_position_to_velocity (r.height() - (r.y1 - ev->motion.y));
mrv->set_velocity_for_notes (affected_lollis, velocity); drag_did_change |= mrv->set_velocity_for_notes (affected_lollis, velocity);
mrv->mid_drag_edit ();
} }
if (dragging) { if (dragging) {
dragging_line->add_point (ArdourCanvas::Duple (ev->motion.x - r.x0, ev->motion.y - r.y0)); dragging_line->add_point (ArdourCanvas::Duple (ev->motion.x - r.x0, ev->motion.y - r.y0));
@ -97,6 +99,7 @@ VelocityGhostRegion::base_event (GdkEvent* ev)
if (ev->button.button == 1) { if (ev->button.button == 1) {
desensitize_lollis (); desensitize_lollis ();
dragging = true; dragging = true;
drag_did_change = false;
last_drag_x = -1; last_drag_x = -1;
if (!dragging_line) { if (!dragging_line) {
dragging_line = new ArdourCanvas::PolyLine (_note_group); dragging_line = new ArdourCanvas::PolyLine (_note_group);
@ -107,10 +110,12 @@ VelocityGhostRegion::base_event (GdkEvent* ev)
dragging_line->show(); dragging_line->show();
dragging_line->raise_to_top(); dragging_line->raise_to_top();
base_rect->grab(); base_rect->grab();
mrv->begin_drag_edit (_("draw velocities"));
} }
break; break;
case GDK_BUTTON_RELEASE: case GDK_BUTTON_RELEASE:
if (ev->button.button == 1) { if (ev->button.button == 1) {
mrv->end_drag_edit (drag_did_change);
base_rect->ungrab(); base_rect->ungrab();
dragging_line->hide (); dragging_line->hide ();
dragging = false; dragging = false;

View file

@ -51,6 +51,7 @@ private:
bool dragging; bool dragging;
ArdourCanvas::PolyLine* dragging_line; ArdourCanvas::PolyLine* dragging_line;
int last_drag_x; int last_drag_x;
bool drag_did_change;
bool base_event (GdkEvent*); bool base_event (GdkEvent*);
bool lollevent (GdkEvent*, MidiGhostRegion::GhostEvent*); bool lollevent (GdkEvent*, MidiGhostRegion::GhostEvent*);