label various spinners in the step editor
[ardour.git] / gtk2_ardour / editor_mouse.cc
index f1640538f6f64732f9eca3aba25ad83de0960dfb..6a3eaa9084cc65b436dc963ce1c31a8887fd5a2a 100644 (file)
@@ -53,6 +53,7 @@
 #include "rgb_macros.h"
 #include "control_point_dialog.h"
 #include "editor_drag.h"
+#include "automation_region_view.h"
 
 #include "ardour/types.h"
 #include "ardour/profile.h"
@@ -177,7 +178,7 @@ Editor::which_grabber_cursor ()
                        break;
 
                case MouseObject:
-                       c = grabber_cursor;
+                       c = grabber_note_cursor;
                        break;
 
                case MouseTimeFX:
@@ -325,6 +326,8 @@ Editor::mouse_mode_toggled (MouseMode m)
 
        instant_save ();
         
+        cerr << "Mouse mode toggled to " << m << endl;
+
         if (!internal_editing()) {
                 if (mouse_mode != MouseRange && _join_object_range_state == JOIN_OBJECT_RANGE_NONE) {
                         
@@ -425,6 +428,10 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
           region alignment.
 
           note: not dbl-click or triple-click
+
+          Also note that there is no region selection in internal edit mode, otherwise
+          for operations operating on the selection (e.g. cut) it is not obvious whether
+          to cut notes or regions.
        */
 
        if (((mouse_mode != MouseObject) &&
@@ -433,8 +440,8 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
             (mouse_mode != MouseTimeFX || item_type != RegionItem) &&
             (mouse_mode != MouseGain) &&
             (mouse_mode != MouseRange)) ||
-
-           ((event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) || event->button.button > 3)) {
+           ((event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) || event->button.button > 3) ||
+           internal_editing()) {
 
                return;
        }
@@ -467,11 +474,12 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
                if (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT && !selection->regions.empty()) {
                        clicked_selection = select_range_around_region (selection->regions.front());
                }
-                       
                break;
 
        case RegionViewNameHighlight:
        case RegionViewName:
+        case LeftFrameHandle:
+        case RightFrameHandle:
                if (mouse_mode != MouseRange || _join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) {
                        set_selected_regionview_from_click (press, op, true);
                } else if (event->type == GDK_BUTTON_PRESS) {
@@ -492,7 +500,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
                break;
 
        case ControlPointItem:
-               set_selected_track_as_side_effect ();
+               set_selected_track_as_side_effect (true);
                if (mouse_mode != MouseRange || _join_object_range_state == JOIN_OBJECT_RANGE_OBJECT) {
                        set_selected_control_point_from_click (op, false);
                }
@@ -518,10 +526,6 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
 bool
 Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
 {
-       if (_drags->active ()) {
-               _drags->abort ();
-       }
-
        /* single mouse clicks on any of these item types operate
           independent of mouse mode, mostly because they are
           not on the main track canvas or because we want
@@ -661,6 +665,33 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        }
                        break;
 
+                case NoteItem:
+                        if (internal_editing()) {
+                                /* trim notes if we're in internal edit mode and near the ends of the note */
+                                _drags->set (new NoteResizeDrag (this, item), event);
+                        }
+                       return true;
+
+                case StreamItem:
+                        if (internal_editing()) {
+                                _drags->set (new RegionCreateDrag (this, item, clicked_axisview), event);
+                                return true;
+                        } else {
+                               _drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event);
+                               return true;
+                       }
+                        break;
+
+                case RegionViewNameHighlight:
+                case LeftFrameHandle:
+                case RightFrameHandle:
+                {
+                        RegionSelection s = get_equivalent_regions (selection->regions, Properties::edit.property_id);
+                        _drags->set (new TrimDrag (this, item, clicked_regionview, s.by_layer()), event);
+                        return true;
+                        break;
+                }
+
                default:
                         if (!internal_editing()) {
                                 _drags->set (new SelectionDrag (this, item, SelectionDrag::CreateSelection), event);
@@ -704,15 +735,36 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                return true;
                        }
 
+                       case FeatureLineItem:
+                       {                       
+                               if (Keyboard::modifier_state_contains (event->button.state, Keyboard::TertiaryModifier)) {
+                                       remove_transient(item);
+                                       return true;
+                               }
+                               
+                               _drags->set (new FeatureLineDrag (this, item), event);
+                               return true;
+                               break;
+                       }
+
                        case RegionItem:
+                               if (dynamic_cast<AutomationRegionView*> (clicked_regionview)) {
+                                       /* click on an automation region view; do nothing here and let the ARV's signal handler
+                                          sort it out.
+                                       */
+                                       break;
+                               }
+                               
+                               /* click on a normal region view */
                                if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
                                        add_region_copy_drag (item, event, clicked_regionview);
-                               } else if (Keyboard::the_keyboard().key_is_down (GDK_b)) {
+                               } 
+                               else if (Keyboard::the_keyboard().key_is_down (GDK_b)) {
                                        add_region_brush_drag (item, event, clicked_regionview);
                                } else {
                                        add_region_drag (item, event, clicked_regionview);
                                }
-
+                               
                                if (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT && !selection->regions.empty()) {
                                        _drags->add (new SelectionDrag (this, clicked_axisview->get_selection_rect (clicked_selection)->rect, SelectionDrag::SelectionMove));
                                }
@@ -721,12 +773,14 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                break;
 
                        case RegionViewNameHighlight:
-                       {
-                               RegionSelection s = get_equivalent_regions (selection->regions, Properties::edit.property_id);
-                               _drags->set (new TrimDrag (this, item, clicked_regionview, s.by_layer()), event);
-                               return true;
+                       case LeftFrameHandle:
+                        case RightFrameHandle:
+                               if (!internal_editing ()) {
+                                       RegionSelection s = get_equivalent_regions (selection->regions, Properties::edit.property_id);
+                                       _drags->set (new TrimDrag (this, item, clicked_regionview, s.by_layer()), event);
+                                       return true;
+                               }
                                break;
-                       }
 
                        case RegionViewName:
                        {
@@ -947,7 +1001,11 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
 
                switch (item_type) {
                case RegionViewNameHighlight:
-                       _drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer()), event);
+                case LeftFrameHandle:
+                case RightFrameHandle:
+                       if (!internal_editing ()) {
+                               _drags->set (new TrimDrag (this, item, clicked_regionview, selection->regions.by_layer()), event);
+                       }
                        return true;
                        break;
 
@@ -1003,9 +1061,6 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
 
                if (pointer_window == track_canvas->get_bin_window()) {
                        track_canvas->window_to_world (x, y, wx, wy);
-                       allow_vertical_scroll = true;
-               } else {
-                       allow_vertical_scroll = false;
                }
        }
 
@@ -1058,7 +1113,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                return true;
        }
 
-       /* first, see if we're finishing a drag ... */
+       /* see if we're finishing a drag */
 
        bool were_dragging = false;
        if (_drags->active ()) {
@@ -1071,8 +1126,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                were_dragging = true;
        }
 
-       button_selection (item, event, item_type);
-
        /* edit events get handled here */
 
        if (!_drags->active () && Keyboard::is_edit_event (&event->button)) {
@@ -1129,6 +1182,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
 
                        case RegionItem:
                        case RegionViewNameHighlight:
+                       case LeftFrameHandle:
+                       case RightFrameHandle:
                        case RegionViewName:
                                popup_track_context_menu (1, event->button.time, item_type, false, where);
                                break;
@@ -1222,6 +1277,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        }
                        break;
 
+               case NoteItem:
+                       remove_midi_note (item, event);
+                       break;
+
                default:
                        break;
                }
@@ -1291,23 +1350,20 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        break;
 
                case MouseGain:
-                       // Gain only makes sense for audio regions
-
-                       if (!dynamic_cast<AudioRegionView*>(clicked_regionview)) {
-                               break;
-                       }
-
                        switch (item_type) {
                        case RegionItem:
+                       {
                                /* check that we didn't drag before releasing, since
                                   its really annoying to create new control
                                   points when doing this.
                                */
-                               if (were_dragging) {
-                                       dynamic_cast<AudioRegionView*>(clicked_regionview)->add_gain_point_event (item, event);
+                               AudioRegionView* arv = dynamic_cast<AudioRegionView*> (clicked_regionview);
+                               if (were_dragging && arv) {
+                                       arv->add_gain_point_event (item, event);
                                }
                                return true;
                                break;
+                       }
 
                        case AutomationTrackItem:
                                dynamic_cast<AutomationTimeAxisView*>(clicked_axisview)->
@@ -1394,6 +1450,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        ControlPoint* cp;
        Marker * marker;
        double fraction;
+        bool ret = true;
 
        if (last_item_entered != item) {
                last_item_entered = item;
@@ -1452,11 +1509,23 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                break;
 
        case RegionViewNameHighlight:
-               if (is_drawable() && mouse_mode == MouseObject) {
+               if (is_drawable() && mouse_mode == MouseObject && !internal_editing()) {
                        track_canvas->get_window()->set_cursor (*trimmer_cursor);
                }
                break;
 
+       case LeftFrameHandle:
+               if (is_drawable() && mouse_mode == MouseObject && !internal_editing()) {
+                       track_canvas->get_window()->set_cursor (*left_side_trim_cursor);
+               }
+                break;
+
+       case RightFrameHandle:
+               if (is_drawable() && mouse_mode == MouseObject && !internal_editing()) {
+                       track_canvas->get_window()->set_cursor (*right_side_trim_cursor);
+               }
+                break;
+
        case StartSelectionTrimItem:
        case EndSelectionTrimItem:
 
@@ -1546,18 +1615,34 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                        track_canvas->get_window()->set_cursor (*timebar_cursor);
                }
                break;
+
        case FadeInHandleItem:
+               if (mouse_mode == MouseObject && !internal_editing()) {
+                       ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
+                       if (rect) {
+                               rect->property_fill_color_rgba() = 0;
+                               rect->property_outline_pixels() = 1;
+                       }
+                       track_canvas->get_window()->set_cursor (*fade_in_cursor);
+               }
+                break;
+
        case FadeOutHandleItem:
-               if (mouse_mode == MouseObject) {
+               if (mouse_mode == MouseObject && !internal_editing()) {
                        ArdourCanvas::SimpleRect *rect = dynamic_cast<ArdourCanvas::SimpleRect *> (item);
                        if (rect) {
                                rect->property_fill_color_rgba() = 0;
                                rect->property_outline_pixels() = 1;
                        }
-                       track_canvas->get_window()->set_cursor (*grabber_cursor);
+                       track_canvas->get_window()->set_cursor (*fade_out_cursor);
+               }
+               break;
+       case FeatureLineItem:
+               {
+                       ArdourCanvas::SimpleLine *line = dynamic_cast<ArdourCanvas::SimpleLine *> (item);
+                       line->property_color_rgba() = 0xFF0000FF;
                }
                break;
-
        default:
                break;
        }
@@ -1582,7 +1667,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                break;
        }
 
-       return false;
+       return ret;
 }
 
 bool
@@ -1594,6 +1679,7 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
        Location *loc;
        RegionView* rv;
        bool is_start;
+        bool ret = true;
 
        switch (item_type) {
        case ControlPointItem:
@@ -1612,6 +1698,8 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                break;
 
        case RegionViewNameHighlight:
+       case LeftFrameHandle:
+       case RightFrameHandle:
        case StartSelectionTrimItem:
        case EndSelectionTrimItem:
        case PlayheadCursorItem:
@@ -1699,12 +1787,18 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                        Glib::signal_idle().connect (sigc::mem_fun(*this, &Editor::left_automation_track));
                }
                break;
+       case FeatureLineItem:
+               {
+                       ArdourCanvas::SimpleLine *line = dynamic_cast<ArdourCanvas::SimpleLine *> (item);
+                       line->property_color_rgba() = (guint) ARDOUR_UI::config()->canvasvar_ZeroLine.get();;
+               }
+               break;
 
        default:
                break;
        }
 
-       return false;
+       return ret;
 }
 
 gint
@@ -1835,7 +1929,7 @@ Editor::motion_handler (ArdourCanvas::Item* /*item*/, GdkEvent* event, bool from
        if (_drags->active ()) {
                handled = _drags->motion_handler (event, from_autoscroll);
        }
-
+       
        if (!handled) {
                return false;
        }
@@ -1997,7 +2091,7 @@ Editor::show_verbose_time_cursor (nframes64_t frame, double offset, double xpos,
                mins = frame / (frame_rate * 60);
                frame = frame % (frame_rate * 60);
                secs = (float) frame / (float) frame_rate;
-               snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", hours, mins, secs);
+               snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%07.4f", hours, mins, secs);
                break;
 
        default:
@@ -2078,7 +2172,7 @@ Editor::show_verbose_duration_cursor (nframes64_t start, nframes64_t end, double
                mins = distance / (frame_rate * 60);
                distance = distance % (frame_rate * 60);
                secs = (float) distance / (float) frame_rate;
-               snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", hours, mins, secs);
+               snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%07.4f", hours, mins, secs);
                break;
 
        default:
@@ -2569,36 +2663,19 @@ Editor::set_internal_edit (bool yn)
                mouse_select_button.set_image (*(manage (new Image (::get_icon("midi_tool_pencil")))));
                mouse_select_button.get_image ()->show ();
                 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Draw/Edit MIDI Notes"));
-
-               for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-                       MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
-                       if (mtv) {
-                               mtv->start_step_editing ();
-                       }
-               }
-
-               for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
-                       (*i)->hide_selection ();
-               }
-
-               start_step_editing ();
                 set_canvas_cursor ();
 
+               /* deselect everything to avoid confusion when e.g. we can't now cut a previously selected
+                  region because cut means "cut note" rather than "cut region".
+               */
+               selection->clear ();
+
        } else {
 
                mouse_select_button.set_image (*(manage (new Image (::get_icon("tool_range")))));
                mouse_select_button.get_image ()->show ();
                 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges"));
-               stop_step_editing ();
-
-               for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-                       MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
-                       if (mtv) {
-                               mtv->stop_step_editing ();
-                       }
-               }
-
-                mouse_mode_toggled (mouse_mode);
+                mouse_mode_toggled (mouse_mode); // sets cursor
        }
 }
 
@@ -2654,3 +2731,12 @@ Editor::effective_mouse_mode () const
 
        return mouse_mode;
 }
+
+void
+Editor::remove_midi_note (ArdourCanvas::Item* item, GdkEvent *)
+{
+       ArdourCanvas::CanvasNoteEvent* e = dynamic_cast<ArdourCanvas::CanvasNoteEvent*> (item);
+       assert (e);
+
+       e->region_view().delete_note (e->note ());
+}