Fix note resize double undo bug.
[ardour.git] / gtk2_ardour / editor_drag.cc
index b86c265610583d8ac28dc0125ac001fbea639eca..34e169b133c2de77e7e962609454c5fdbf80661c 100644 (file)
@@ -47,6 +47,7 @@
 #include "i18n.h"
 #include "keyboard.h"
 #include "audio_region_view.h"
+#include "automation_region_view.h"
 #include "midi_region_view.h"
 #include "ardour_ui.h"
 #include "gui_thread.h"
@@ -1962,6 +1963,8 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
        */
        region->note_selected (cnote, cnote->selected ());
 
+       _editor->begin_reversible_command (_("resize notes"));
+
        for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ) {
                MidiRegionSelection::iterator next;
                next = r;
@@ -2000,6 +2003,8 @@ NoteResizeDrag::finished (GdkEvent*, bool /*movement_occurred*/)
                        mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative);
                }
        }
+
+       _editor->commit_reversible_command ();
 }
 
 void
@@ -4379,6 +4384,7 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
 {
        Session* s = _editor->session();
 
+       _editor->begin_reversible_selection_op (_("Change Time Selection"));
        if (movement_occurred) {
                motion (event, false);
                /* XXX this is not object-oriented programming at all. ick */
@@ -4435,6 +4441,7 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
 
        _editor->stop_canvas_autoscroll ();
        _editor->clicked_selection = 0;
+       _editor->commit_reversible_selection_op ();
 }
 
 void
@@ -4716,6 +4723,9 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
                        } else {
                                _region->unique_select (_primary);
                        }
+
+                       _editor->begin_reversible_selection_op(_("Select Note Press"));
+                       _editor->commit_reversible_selection_op();
                }
        }
 }
@@ -4797,14 +4807,17 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
 {
        if (!moved) {
                /* no motion - select note */
-               
+
                if (_editor->current_mouse_mode() == Editing::MouseObject ||
                    _editor->current_mouse_mode() == Editing::MouseDraw) {
-                       
+
+                       bool changed = false;
+
                        if (_was_selected) {
                                bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
                                if (add) {
                                        _region->note_deselected (_primary);
+                                       changed = true;
                                }
                        } else {
                                bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
@@ -4812,12 +4825,19 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
 
                                if (!extend && !add && _region->selection_size() > 1) {
                                        _region->unique_select (_primary);
+                                       changed = true;
                                } else if (extend) {
                                        _region->note_selected (_primary, true, true);
+                                       changed = true;
                                } else {
                                        /* it was added during button press */
                                }
                        }
+
+                       if (changed) {
+                               _editor->begin_reversible_selection_op(_("Select Note Release"));
+                               _editor->commit_reversible_selection_op();
+                       }
                }
        } else {
                _region->note_dropped (_primary, total_dx(), total_dy());
@@ -4834,24 +4854,36 @@ NoteDrag::aborted (bool)
 AutomationRangeDrag::AutomationRangeDrag (Editor* editor, AutomationTimeAxisView* atv, list<AudioRange> const & r)
        : Drag (editor, atv->base_item ())
        , _ranges (r)
+       , _y_origin (atv->y_position())
        , _nothing_to_drag (false)
 {
        DEBUG_TRACE (DEBUG::Drags, "New AutomationRangeDrag\n");
-       y_origin = atv->y_position();
        setup (atv->lines ());
 }
 
-/** Make an AutomationRangeDrag for region gain lines */
-AutomationRangeDrag::AutomationRangeDrag (Editor* editor, AudioRegionView* rv, list<AudioRange> const & r)
+/** Make an AutomationRangeDrag for region gain lines or MIDI controller regions */
+AutomationRangeDrag::AutomationRangeDrag (Editor* editor, RegionView* rv, list<AudioRange> const & r)
        : Drag (editor, rv->get_canvas_group ())
        , _ranges (r)
+       , _y_origin (rv->get_time_axis_view().y_position())
        , _nothing_to_drag (false)
+       , _integral (false)
 {
        DEBUG_TRACE (DEBUG::Drags, "New AutomationRangeDrag\n");
 
        list<boost::shared_ptr<AutomationLine> > lines;
-       lines.push_back (rv->get_gain_line ());
-       y_origin = rv->get_time_axis_view().y_position();
+
+       AudioRegionView*      audio_view;
+       AutomationRegionView* automation_view;
+       if ((audio_view = dynamic_cast<AudioRegionView*>(rv))) {
+               lines.push_back (audio_view->get_gain_line ());
+       } else if ((automation_view = dynamic_cast<AutomationRegionView*>(rv))) {
+               lines.push_back (automation_view->line ());
+               _integral = true;
+       } else {
+               error << _("Automation range drag created for invalid region type") << endmsg;
+       }
+
        setup (lines);
 }
 
@@ -4896,7 +4928,14 @@ AutomationRangeDrag::setup (list<boost::shared_ptr<AutomationLine> > const & lin
 double
 AutomationRangeDrag::y_fraction (boost::shared_ptr<AutomationLine> line, double global_y) const
 {
-       return 1.0 - ((global_y - y_origin) / line->height());
+       return 1.0 - ((global_y - _y_origin) / line->height());
+}
+
+double
+AutomationRangeDrag::value (boost::shared_ptr<AutomationList> list, double x) const
+{
+       const double v = list->eval(x);
+       return _integral ? rint(v) : v;
 }
 
 void
@@ -4947,8 +4986,8 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
                                double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ());
                                double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ());
 
-                               the_list->editor_add (p, the_list->eval (p));
-                               the_list->editor_add (q, the_list->eval (q));
+                               the_list->editor_add (p, value (the_list, p));
+                               the_list->editor_add (q, value (the_list, q));
                        }
 
                        /* same thing for the end */
@@ -4973,8 +5012,8 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
                                double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ());
                                double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ());
 
-                               the_list->editor_add (p, the_list->eval (p));
-                               the_list->editor_add (q, the_list->eval (q));
+                               the_list->editor_add (p, value (the_list, p));
+                               the_list->editor_add (q, value (the_list, q));
                        }
                }
 
@@ -5192,22 +5231,25 @@ EditorRubberbandSelectDrag::select_things (int button_state, framepos_t x1, fram
        
        Selection::Operation op = ArdourKeyboard::selection_type (button_state);
 
-       _editor->begin_reversible_command (_("rubberband selection"));
+       _editor->begin_reversible_selection_op (_("rubberband selection"));
 
        _editor->select_all_within (x1, x2 - 1, y1, y2, _editor->track_views, op, false);
 
-       _editor->commit_reversible_command ();
+       _editor->commit_reversible_selection_op ();
 }
 
 void
 EditorRubberbandSelectDrag::deselect_things ()
 {
-       if (!getenv("ARDOUR_SAE")) {
-               _editor->selection->clear_tracks();
-       }
+       _editor->begin_reversible_selection_op (_("Clear Selection (rubberband)"));
+
+       _editor->selection->clear_tracks();
        _editor->selection->clear_regions();
        _editor->selection->clear_points ();
        _editor->selection->clear_lines ();
+       _editor->selection->clear_midi_notes ();
+
+       _editor->commit_reversible_selection_op();
 }
 
 NoteCreateDrag::NoteCreateDrag (Editor* e, ArdourCanvas::Item* i, MidiRegionView* rv)
@@ -5227,9 +5269,9 @@ framecnt_t
 NoteCreateDrag::grid_frames (framepos_t t) const
 {
        bool success;
-       Evoral::MusicalTime grid_beats = _editor->get_grid_type_as_beats (success, t);
+       Evoral::Beats grid_beats = _editor->get_grid_type_as_beats (success, t);
        if (!success) {
-               grid_beats = Evoral::MusicalTime(1);
+               grid_beats = Evoral::Beats(1);
        }
 
        return _region_view->region_beats_to_region_frames (grid_beats);
@@ -5286,13 +5328,13 @@ NoteCreateDrag::finished (GdkEvent*, bool had_movement)
        framecnt_t length = (framecnt_t) fabs ((double)(_note[0] - _note[1]));
 
        framecnt_t const g = grid_frames (start);
-       Evoral::MusicalTime const one_tick = Evoral::MusicalTime::ticks(1);
+       Evoral::Beats const one_tick = Evoral::Beats::ticks(1);
        
        if (_editor->snap_mode() == SnapNormal && length < g) {
                length = g;
        }
 
-       Evoral::MusicalTime length_beats = max (
+       Evoral::Beats length_beats = max (
                one_tick, _region_view->region_frames_to_region_beats (length) - one_tick);
 
        _region_view->create_note_at (start, _drag_rect->y0(), length_beats, false);