experiment with making MIDI region boxes vanish when in note/internal edit mode ...
[ardour.git] / gtk2_ardour / midi_region_view.cc
index af79a4f2b8f892b9d29121f7ab1b24357bff992e..4ef7c014bb82c53e8b6fe2984c8cd61765053f48 100644 (file)
@@ -49,6 +49,7 @@
 #include "canvas-hit.h"
 #include "canvas-note.h"
 #include "canvas_patch_change.h"
+#include "debug.h"
 #include "editor.h"
 #include "ghostregion.h"
 #include "gui_thread.h"
@@ -293,10 +294,6 @@ MidiRegionView::canvas_event(GdkEvent* ev)
                return false;
        }
 
-       /* XXX: note that until version 2.30, the GnomeCanvas did not propagate scroll events
-          to its items, which means that ev->type == GDK_SCROLL will never be seen
-       */
-
        switch (ev->type) {
        case GDK_SCROLL:
                 return scroll (&ev->scroll);
@@ -924,7 +921,7 @@ MidiRegionView::note_diff_add_change (ArdourCanvas::CanvasNoteEvent* ev,
 }
 
 void
-MidiRegionView::apply_diff ()
+MidiRegionView::apply_diff (bool as_subcommand)
 {
         bool add_or_remove;
 
@@ -939,7 +936,12 @@ MidiRegionView::apply_diff ()
                 }
         }
 
-       _model->apply_command(*trackview.session(), _note_diff_command);
+       if (as_subcommand) {
+               _model->apply_command_as_subcommand (*trackview.session(), _note_diff_command);
+       } else {
+               _model->apply_command (*trackview.session(), _note_diff_command);
+       }
+       
        _note_diff_command = 0;
        midi_view()->midi_track()->playlist_modified();
         
@@ -950,33 +952,6 @@ MidiRegionView::apply_diff ()
        _marked_for_velocity.clear();
 }
 
-void
-MidiRegionView::apply_diff_as_subcommand ()
-{
-        bool add_or_remove;
-
-       if (!_note_diff_command) {
-               return;
-       }
-
-        if ((add_or_remove = _note_diff_command->adds_or_removes())) {
-                // Mark all selected notes for selection when model reloads
-                for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
-                        _marked_for_selection.insert((*i)->note());
-                }
-        }
-
-       _model->apply_command_as_subcommand(*trackview.session(), _note_diff_command);
-       _note_diff_command = 0;
-       midi_view()->midi_track()->playlist_modified();
-
-        if (add_or_remove) {
-                _marked_for_selection.clear();
-        }
-       _marked_for_velocity.clear();
-}
-
-
 void
 MidiRegionView::abort_command()
 {
@@ -1327,16 +1302,16 @@ MidiRegionView::add_ghost (TimeAxisView& tv)
                ghost = new MidiGhostRegion (tv, trackview, unit_position);
        }
 
-       ghost->set_height ();
-       ghost->set_duration (_region->length() / samples_per_unit);
-       ghosts.push_back (ghost);
-
        for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
                if ((note = dynamic_cast<CanvasNote*>(*i)) != 0) {
                        ghost->add_note(note);
                }
        }
 
+       ghost->set_height ();
+       ghost->set_duration (_region->length() / samples_per_unit);
+       ghosts.push_back (ghost);
+
        GhostRegion::CatchDeletion.connect (*this, invalidator (*this), ui_bind (&RegionView::remove_ghost, this, _1), gui_context());
 
        return ghost;
@@ -1460,8 +1435,12 @@ MidiRegionView::note_in_region_range(const boost::shared_ptr<NoteType> note, boo
        return !outside;
 }
 
+/** Update a canvas note's size from its model note.
+ *  @param ev Canvas note to update.
+ *  @param update_ghost_regions true to update the note in any ghost regions that we have, otherwise false.
+ */
 void
-MidiRegionView::update_note (CanvasNote* ev)
+MidiRegionView::update_note (CanvasNote* ev, bool update_ghost_regions)
 {
        boost::shared_ptr<NoteType> note = ev->note();
 
@@ -1504,6 +1483,15 @@ MidiRegionView::update_note (CanvasNote* ev)
                /* outline all edges */
                ev->property_outline_what() = (guint32) 0xF;
        }
+
+       if (update_ghost_regions) {
+               for (std::vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+                       MidiGhostRegion* gr = dynamic_cast<MidiGhostRegion*> (*i);
+                       if (gr) {
+                               gr->update_note (ev);
+                       }
+               }
+       }
 }
 
 double
@@ -2868,13 +2856,33 @@ MidiRegionView::note_mouse_position (float x_fraction, float /*y_fraction*/, boo
 void
 MidiRegionView::set_frame_color()
 {
-       if (frame) {
-               if (_selected && should_show_selection) {
-                       frame->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_SelectedFrameBase.get();
-               } else {
-                       frame->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiFrameBase.get();
-               }
+        uint32_t f;
+
+       if (!frame) {
+               return;
+       }
+
+       if (_selected) {
+               f = ARDOUR_UI::config()->canvasvar_SelectedFrameBase.get();
+       } else if (high_enough_for_name) {
+               f= ARDOUR_UI::config()->canvasvar_MidiFrameBase.get();
+       } else {
+               f = fill_color;
        }
+        
+        if (!rect_visible) {
+                f = UINT_RGBA_CHANGE_A (f, 0);
+        }
+
+        frame->property_fill_color_rgba() = f;
+
+        f = ARDOUR_UI::config()->canvasvar_TimeAxisFrame.get();
+
+        if (!rect_visible) {
+                f = UINT_RGBA_CHANGE_A (f, 0);
+        }
+
+        frame->property_outline_color_rgba() = f;
 }
 
 void
@@ -2962,6 +2970,7 @@ MidiRegionView::selection_as_cut_buffer () const
        return cb;
 }
 
+/** This method handles undo */
 void
 MidiRegionView::paste (framepos_t pos, float times, const MidiCutBuffer& mcb)
 {
@@ -2969,6 +2978,10 @@ MidiRegionView::paste (framepos_t pos, float times, const MidiCutBuffer& mcb)
                return;
        }
 
+        DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("MIDI paste @ %1 times %2\n", pos, times));
+
+       trackview.session()->begin_reversible_command (_("paste"));
+
        start_note_diff_command (_("paste"));
 
        Evoral::MusicalTime beat_delta;
@@ -2981,6 +2994,12 @@ MidiRegionView::paste (framepos_t pos, float times, const MidiCutBuffer& mcb)
        beat_delta = (*mcb.notes().begin())->time() - paste_pos_beats;
        paste_pos_beats = 0;
 
+        DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste data spans from %1 to %2 (%3) ; paste pos beats = %4 (based on %5 - %6 ; beat delta = %7\n",
+                                                       (*mcb.notes().begin())->time(),
+                                                       (*mcb.notes().rbegin())->end_time(),
+                                                       duration, pos, _region->position(),
+                                                       paste_pos_beats, beat_delta));
+                                                       
         clear_selection ();
 
        for (int n = 0; n < (int) times; ++n) {
@@ -3006,14 +3025,16 @@ MidiRegionView::paste (framepos_t pos, float times, const MidiCutBuffer& mcb)
 
        if (end_frame > region_end) {
 
-               trackview.session()->begin_reversible_command (_("paste"));
+                DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste extended region from %1 to %2\n", region_end, end_frame));
 
                 _region->clear_changes ();
                _region->set_length (end_frame, this);
                trackview.session()->add_command (new StatefulDiffCommand (_region));
        }
 
-       apply_diff ();
+       apply_diff (true);
+       
+       trackview.session()->commit_reversible_command ();
 }
 
 struct EventNoteTimeEarlyFirstComparator {
@@ -3137,7 +3158,8 @@ MidiRegionView::update_ghost_note (double x, double y)
        _ghost_note->note()->set_length (length);
        _ghost_note->note()->set_note (midi_stream_view()->y_to_note (y));
 
-       update_note (_ghost_note);
+       /* the ghost note does not appear in ghost regions, so pass false in here */
+       update_note (_ghost_note, false);
 
        show_verbose_canvas_cursor (_ghost_note->note ());
 }