fix a-eq grid layout
[ardour.git] / gtk2_ardour / editor_mouse.cc
index 094afc2692e1d8c30256f78641f170cc9730eb4b..01cb2175c16a056d0840048729f66b9a664f7bbf 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "gtkmm2ext/bindings.h"
 #include "gtkmm2ext/utils.h"
-#include "gtkmm2ext/tearoff.h"
 
 #include "canvas/canvas.h"
 
@@ -72,7 +71,7 @@
 #include "verbose_cursor.h"
 #include "note.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -333,12 +332,12 @@ Editor::update_time_selection_display ()
        switch (mouse_mode) {
        case MouseRange:
                selection->clear_objects ();
-               selection->ClearMidiNoteSelection ();  /* EMIT SIGNAL */
+               selection->clear_midi_notes ();
                break;
        case MouseObject:
                selection->clear_time ();
                selection->clear_tracks ();
-               selection->ClearMidiNoteSelection ();  /* EMIT SIGNAL */
+               selection->clear_midi_notes ();
                break;
        case MouseDraw:
                /* Clear regions, but not time or tracks, since that
@@ -399,8 +398,9 @@ Editor::step_mouse_mode (bool next)
 }
 
 void
-Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemType item_type)
+Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
 {
+
        /* in object/audition/timefx/gain-automation mode,
           any button press sets the selection if the object
           can be selected. this is a bit of hack, because
@@ -457,7 +457,9 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
 
                        /* almost no selection action on modified button-2 or button-3 events */
 
-                       if (item_type != RegionItem && event->button.button != 2) {
+                       if ((item_type != RegionItem && event->button.button != 2)
+                           /* for selection of control points prior to delete (shift-right click) */
+                           && !(item_type == ControlPointItem && event->button.button == 3 && event->type == GDK_BUTTON_PRESS)) {
                                return;
                        }
                }
@@ -472,6 +474,9 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
 
        switch (item_type) {
        case RegionItem:
+               if (eff_mouse_mode == MouseDraw) {
+                       break;
+               }
                if (press) {
                        if (eff_mouse_mode != MouseRange) {
                                _mouse_changed_selection = set_selected_regionview_from_click (press, op);
@@ -515,7 +520,94 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
                /* for object/track exclusivity, we don't call set_selected_track_as_side_effect (op); */
 
                if (eff_mouse_mode != MouseRange) {
-                       _mouse_changed_selection |= set_selected_control_point_from_click (press, op);
+                       if (event->button.button != 3) {
+                               _mouse_changed_selection |= set_selected_control_point_from_click (press, op);
+                       } else {
+                               _mouse_changed_selection |= set_selected_control_point_from_click (press, Selection::Set);
+                       }
+               }
+               break;
+
+       case GainLineItem:
+               if (eff_mouse_mode != MouseRange) {
+                       AutomationLine* argl = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
+
+                       std::list<Selectable*> selectables;
+                       uint32_t before, after;
+                       framecnt_t const  where = (framecnt_t) floor (event->button.x * samples_per_pixel) - clicked_regionview->region ()->position ();
+
+                       if (!argl || !argl->control_points_adjacent (where, before, after)) {
+                               break;
+                       }
+
+                       selectables.push_back (argl->nth (before));
+                       selectables.push_back (argl->nth (after));
+
+                       switch (op) {
+                       case Selection::Set:
+                               if (press) {
+                                       selection->set (selectables);
+                                       _mouse_changed_selection = true;
+                               }
+                               break;
+                       case Selection::Add:
+                               if (press) {
+                                       selection->add (selectables);
+                                       _mouse_changed_selection = true;
+                               }
+                               break;
+                       case Selection::Toggle:
+                               if (press) {
+                                       selection->toggle (selectables);
+                                       _mouse_changed_selection = true;
+                               }
+                               break;
+
+                       case Selection::Extend:
+                               /* XXX */
+                               break;
+                       }
+               }
+               break;
+
+       case AutomationLineItem:
+               if (eff_mouse_mode != MouseRange) {
+                       AutomationLine* al = reinterpret_cast<AutomationLine*> (item->get_data ("line"));
+                       std::list<Selectable*> selectables;
+                       uint32_t before, after;
+                       framecnt_t const  where = (framecnt_t) floor (event->button.x * samples_per_pixel);
+
+                       if (!al || !al->control_points_adjacent (where, before, after)) {
+                               break;
+                       }
+
+                       selectables.push_back (al->nth (before));
+                       selectables.push_back (al->nth (after));
+
+                       switch (op) {
+                       case Selection::Set:
+                               if (press) {
+                                       selection->set (selectables);
+                                       _mouse_changed_selection = true;
+                               }
+                               break;
+                       case Selection::Add:
+                               if (press) {
+                                       selection->add (selectables);
+                                       _mouse_changed_selection = true;
+                               }
+                               break;
+                       case Selection::Toggle:
+                               if (press) {
+                                       selection->toggle (selectables);
+                                       _mouse_changed_selection = true;
+                               }
+                               break;
+
+                       case Selection::Extend:
+                               /* XXX */
+                               break;
+                       }
                }
                break;
 
@@ -532,7 +624,23 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
                break;
 
        case AutomationTrackItem:
-               set_selected_track_as_side_effect (op);
+               if (eff_mouse_mode != MouseDraw && op == Selection::Set) {
+                       set_selected_track_as_side_effect (op);
+               }
+               break;
+
+       case NoteItem:
+               if (press && event->button.button == 3) {
+                       NoteBase* cnote = reinterpret_cast<NoteBase*> (item->get_data ("notebase"));
+                       assert (cnote);
+                       if (cnote->region_view().selection_size() == 0 || !cnote->selected()) {
+                               selection->clear_points();
+                               cnote->region_view().unique_select (cnote);
+                               /* we won't get the release, so store the selection change now */
+                               begin_reversible_selection_op (X_("Button 3 Note Selection"));
+                               commit_reversible_selection_op ();
+                       }
+               }
                break;
 
        default:
@@ -576,7 +684,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        new TempoMarkerDrag (
                                this,
                                item,
-                               Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
+                               ArdourKeyboard::indicates_copy (event->button.state)
                                ),
                        event
                        );
@@ -589,7 +697,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        new MeterMarkerDrag (
                                this,
                                item,
-                               Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)
+                               ArdourKeyboard::indicates_copy (event->button.state)
                                ),
                        event
                        );
@@ -603,13 +711,17 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
 
        case MarkerBarItem:
        case TempoBarItem:
+       case TempoCurveItem:
        case MeterBarItem:
        case TimecodeRulerItem:
        case SamplesRulerItem:
        case MinsecRulerItem:
        case BBTRulerItem:
-               if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
+               if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)
+                       && !ArdourKeyboard::indicates_constraint (event->button.state)) {
                        _drags->set (new CursorDrag (this, *playhead_cursor, false), event);
+               } else if (ArdourKeyboard::indicates_constraint (event->button.state)) {
+                       _drags->set (new BBTRulerDrag (this, item), event);
                }
                return true;
                break;
@@ -851,7 +963,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                }
 
                                /* click on a normal region view */
-                               if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
+                               if (ArdourKeyboard::indicates_copy (event->button.state)) {
                                        add_region_copy_drag (item, event, clicked_regionview);
                                } else if (Keyboard::the_keyboard().key_is_down (GDK_b)) {
                                        add_region_brush_drag (item, event, clicked_regionview);
@@ -925,7 +1037,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                                if (!prev) {
                                                        _drags->set (new RegionCreateDrag (this, item, parent), event);
                                                } else {
-                                                       prev->set_length (t - prev->position ());
+                                                       prev->set_length (t - prev->position (), get_grid_music_divisions (event->button.state));
                                                }
                                        }
                                } else {
@@ -1052,7 +1164,7 @@ Editor::button_press_handler_2 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
        case MouseObject:
                switch (item_type) {
                case RegionItem:
-                       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier)) {
+                       if (ArdourKeyboard::indicates_copy (event->button.state)) {
                                add_region_copy_drag (item, event, clicked_regionview);
                        } else {
                                add_region_drag (item, event, clicked_regionview);
@@ -1138,7 +1250,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
        }
 
        //not rolling, range mode click + join_play_range :  locate the PH here
-       if ( !_drags->active () && _session && !_session->transport_rolling() && ( effective_mouse_mode() == MouseRange ) && UIConfiguration::instance().get_follow_edits() ) {
+       if ( !_drags->active () && _session && !_session->transport_rolling() && ( effective_mouse_mode() == MouseRange ) && UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync() ) {
                framepos_t where = canvas_event_sample (event);
                snap_to(where);
                _session->request_locate (where, false);
@@ -1225,7 +1337,6 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                case RegionItem:
                        show_region_properties ();
                        break;
-
                case TempoMarkerItem: {
                        ArdourMarker* marker;
                        TempoMarker* tempo_marker;
@@ -1330,6 +1441,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                        case TransportMarkerBarItem:
                        case CdMarkerBarItem:
                        case TempoBarItem:
+                       case TempoCurveItem:
                        case MeterBarItem:
                        case VideoBarItem:
                        case TimecodeRulerItem:
@@ -1439,8 +1551,8 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
                                mouse_add_new_marker (where, true);
                        }
                        return true;
-
                case TempoBarItem:
+               case TempoCurveItem:
                        if (!_dragging_playhead) {
                                snap_to_with_modifier (where, event);
                                mouse_add_new_tempo_event (where);
@@ -1576,6 +1688,8 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 {
        ControlPoint* cp;
        ArdourMarker * marker;
+       MeterMarker* m_marker = 0;
+       TempoMarker* t_marker = 0;
        double fraction;
         bool ret = true;
 
@@ -1590,7 +1704,7 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
 
        switch (item_type) {
        case ControlPointItem:
-               if (mouse_mode == MouseDraw || mouse_mode == MouseObject) {
+               if (mouse_mode == MouseDraw || mouse_mode == MouseObject || mouse_mode == MouseContent) {
                        cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
                        cp->show ();
 
@@ -1633,9 +1747,30 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
                }
                entered_marker = marker;
                marker->set_color_rgba (UIConfiguration::instance().color ("entered marker"));
-               // fall through
+               break;
+
        case MeterMarkerItem:
+               if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
+                       break;
+               }
+               entered_marker = m_marker;
+               if (m_marker->meter().position_lock_style() == MusicTime) {
+                       m_marker->set_color_rgba (UIConfiguration::instance().color ("meter marker"));
+               } else {
+                       m_marker->set_color_rgba (UIConfiguration::instance().color ("meter marker music"));
+               }
+               break;
+
        case TempoMarkerItem:
+               if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
+                       break;
+               }
+               entered_marker = t_marker;
+               if (t_marker->tempo().position_lock_style() == MusicTime) {
+                       t_marker->set_color_rgba (UIConfiguration::instance().color ("tempo marker"));
+               } else {
+                       t_marker->set_color_rgba (UIConfiguration::instance().color ("tempo marker music"));
+               }
                break;
 
        case FadeInHandleItem:
@@ -1710,6 +1845,8 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
 {
        AutomationLine* al;
        ArdourMarker *marker;
+       TempoMarker *t_marker;
+       MeterMarker *m_marker;
        Location *loc;
        bool is_start;
        bool ret = true;
@@ -1742,9 +1879,30 @@ Editor::leave_handler (ArdourCanvas::Item* item, GdkEvent*, ItemType item_type)
                if ((loc = find_location_from_marker (marker, is_start)) != 0) {
                        location_flags_changed (loc);
                }
-               // fall through
+               break;
+
        case MeterMarkerItem:
+               if ((m_marker = static_cast<MeterMarker *> (item->get_data ("marker"))) == 0) {
+                       break;
+               }
+               entered_marker = 0;
+               if (m_marker->meter().position_lock_style() == MusicTime) {
+                       m_marker->set_color_rgba (UIConfiguration::instance().color ("meter marker music"));
+               } else {
+                       m_marker->set_color_rgba (UIConfiguration::instance().color ("meter marker"));
+               }
+               break;
+
        case TempoMarkerItem:
+               if ((t_marker = static_cast<TempoMarker *> (item->get_data ("marker"))) == 0) {
+                       break;
+               }
+               entered_marker = 0;
+               if (t_marker->tempo().position_lock_style() == MusicTime) {
+                       t_marker->set_color_rgba (UIConfiguration::instance().color ("tempo marker music"));
+               } else {
+                       t_marker->set_color_rgba (UIConfiguration::instance().color ("tempo marker"));
+               }
                break;
 
        case FadeInTrimHandleItem:
@@ -1970,8 +2128,12 @@ Editor::edit_notes (MidiRegionView* mrv)
 void
 Editor::note_edit_done (int r, EditNoteDialog* d)
 {
+       begin_reversible_command (_("edit note(s)"));
+
        d->done (r);
        delete d;
+
+       commit_reversible_command();
 }
 
 void
@@ -1984,7 +2146,7 @@ Editor::visible_order_range (int* low, int* high) const
 
                RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
 
-               if (!rtv->hidden()) {
+               if (rtv && !rtv->hidden()) {
 
                        if (*high < rtv->order()) {
                                *high = rtv->order ();
@@ -2099,7 +2261,7 @@ Editor::point_trim (GdkEvent* event, framepos_t new_bound)
 
                break;
        case 2:
-               begin_reversible_command (_("End point trim"));
+               begin_reversible_command (_("end point trim"));
 
                if (selection->selected (rv)) {
 
@@ -2197,7 +2359,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, framepos_t pos)
 
        RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&rv->get_time_axis_view());
 
-       if (rtv == 0 || !rtv->is_track()) {
+       if (!rtv || !rtv->is_track()) {
                return;
        }
 
@@ -2348,7 +2510,7 @@ Editor::escape ()
                selection->clear ();
        }
 
-       reset_focus ();
+       reset_focus (&contents());
 }
 
 /** Update _join_object_range_state which indicate whether we are over the top