click (no drag) on automation line now adds a new control point on the line (not...
[ardour.git] / gtk2_ardour / editor_drag.cc
index 2419169c7fb23f7d301ece441c762e7aaced59fc..cff5a233e33c11cc189f890421d1bd2677035e36 100644 (file)
@@ -160,6 +160,14 @@ DragManager::end_grab (GdkEvent* e)
        return r;
 }
 
+void
+DragManager::mark_double_click ()
+{
+       for (list<Drag*>::const_iterator i = _drags.begin(); i != _drags.end(); ++i) {
+               (*i)->set_double_click (true);
+       }
+}
+
 bool
 DragManager::motion_handler (GdkEvent* e, bool from_autoscroll)
 {
@@ -183,7 +191,7 @@ DragManager::window_motion_handler (GdkEvent* e, bool from_autoscroll)
 {
        bool r = false;
 
-       _current_pointer_frame = _editor->window_event_frame (e, &_current_pointer_x, &_current_pointer_y);
+       _current_pointer_frame = _editor->canvas_event_frame (e, &_current_pointer_x, &_current_pointer_y);
 
        for (list<Drag*>::iterator i = _drags.begin(); i != _drags.end(); ++i) {
                bool const t = (*i)->motion_handler (e, from_autoscroll);
@@ -212,6 +220,7 @@ Drag::Drag (Editor* e, ArdourCanvas::Item* i)
        , _item (i)
        , _pointer_frame_offset (0)
        , _move_threshold_passed (false)
+       , _was_double_click (false)
        , _raw_grab_frame (0)
        , _grab_frame (0)
        , _last_pointer_frame (0)
@@ -388,8 +397,8 @@ Drag::show_verbose_cursor_time (framepos_t frame)
 {
        _editor->verbose_cursor()->set_time (
                frame,
-               _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
-               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value()
+               _drags->current_pointer_x() + 10,
+               _drags->current_pointer_y() + 10
                );
 
        _editor->verbose_cursor()->show ();
@@ -402,8 +411,8 @@ Drag::show_verbose_cursor_duration (framepos_t start, framepos_t end, double xof
 
        _editor->verbose_cursor()->set_duration (
                start, end,
-               _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
-               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value()
+               _drags->current_pointer_x() + 10,
+               _drags->current_pointer_y() + 10
                );
 }
 
@@ -414,8 +423,8 @@ Drag::show_verbose_cursor_text (string const & text)
 
        _editor->verbose_cursor()->set (
                text,
-               _drags->current_pointer_x() + 10 - _editor->horizontal_position(),
-               _drags->current_pointer_y() + 10 - _editor->vertical_adjustment.get_value()
+               _drags->current_pointer_x() + 10,
+               _drags->current_pointer_y() + 10
                );
 }
 
@@ -441,7 +450,7 @@ struct EditorOrderTimeAxisViewSorter {
            RouteTimeAxisView* ra = dynamic_cast<RouteTimeAxisView*> (a);
            RouteTimeAxisView* rb = dynamic_cast<RouteTimeAxisView*> (b);
            assert (ra && rb);
-           return ra->route()->order_key (EditorSort) < rb->route()->order_key (EditorSort);
+           return ra->route()->order_key () < rb->route()->order_key ();
     }
 };
 
@@ -510,9 +519,11 @@ RegionDrag::find_time_axis_view (TimeAxisView* t) const
 }
 
 RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b)
-       : RegionDrag (e, i, p, v),
-         _brushing (b),
-         _total_x_delta (0)
+       : RegionDrag (e, i, p, v)
+       , _brushing (b)
+       , _total_x_delta (0)
+       , _last_pointer_time_axis_view (0)
+       , _last_pointer_layer (0)
 {
        DEBUG_TRACE (DEBUG::Drags, "New RegionMotionDrag\n");
 }
@@ -525,8 +536,10 @@ RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
        show_verbose_cursor_time (_last_frame_position);
 
        pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (_drags->current_pointer_y ());
-       _last_pointer_time_axis_view = find_time_axis_view (tv.first);
-       _last_pointer_layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
+       if (tv.first) {
+               _last_pointer_time_axis_view = find_time_axis_view (tv.first);
+               _last_pointer_layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
+       }
 }
 
 double
@@ -633,17 +646,18 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
        /* Find the TimeAxisView that the pointer is now over */
        pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (_drags->current_pointer_y ());
 
-       if (first_move && tv.first->view()->layer_display() == Stacked) {
-               tv.first->view()->set_layer_display (Expanded);
-       }
-
        /* Bail early if we're not over a track */
        RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv.first);
+
        if (!rtv || !rtv->is_track()) {
                _editor->verbose_cursor()->hide ();
                return;
        }
 
+       if (first_move && tv.first->view()->layer_display() == Stacked) {
+               tv.first->view()->set_layer_display (Expanded);
+       }
+
        /* Note: time axis views in this method are often expressed as an index into the _time_axis_views vector */
 
        /* Here's the current pointer position in terms of time axis view and layer */
@@ -858,7 +872,15 @@ RegionMoveDrag::finished (GdkEvent* ev, bool movement_occurred)
        RegionMotionDrag::finished (ev, movement_occurred);
        
        if (!movement_occurred) {
+               
                /* just a click */
+
+               if (was_double_click() && !_views.empty()) {
+                       DraggingView dv = _views.front();
+                       dv.view->show_region_editor ();
+                       
+               }
+
                return;
        }
 
@@ -1267,8 +1289,13 @@ void
 RegionMotionDrag::aborted (bool)
 {
        for (vector<TimeAxisView*>::iterator i = _time_axis_views.begin(); i != _time_axis_views.end(); ++i) {
-               if ((*i)->view()->layer_display() == Expanded) {
-                       (*i)->view()->set_layer_display (Stacked);
+
+               StreamView* sview = (*i)->view();
+
+               if (sview) {
+                       if (sview->layer_display() == Expanded) {
+                               sview->set_layer_display (Stacked);
+                       }
                }
        }
        
@@ -1479,7 +1506,7 @@ RegionCreateDrag::motion (GdkEvent* event, bool first_move)
                           place snapped notes at the start of the region.
                        */
 
-                       framecnt_t const len = (framecnt_t) fabs (f - grab_frame () - 1);
+                       framecnt_t const len = (framecnt_t) fabs ((double)(f - grab_frame () - 1));
                        _region->set_length (len < 1 ? 1 : len);
                }
        }
@@ -1668,7 +1695,7 @@ VideoTimeLineDrag::motion (GdkEvent* event, bool first_move)
        }
 
        framecnt_t dt = adjusted_current_frame (event) - raw_grab_frame() + _pointer_frame_offset;
-       dt = ARDOUR_UI::instance()->video_timeline->quantify_frames_to_apv(dt);
+       dt = ARDOUR_UI::instance()->video_timeline->quantify_frames_to_apv(_startdrag_video_offset+dt) - _startdrag_video_offset;
 
        if (_max_backwards_drag >= 0 && dt <= - _max_backwards_drag) {
                dt = - _max_backwards_drag;
@@ -2127,6 +2154,10 @@ MeterMarkerDrag::setup_pointer_frame_offset ()
 void
 MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
 {
+       if (!_marker->meter().movable()) {
+               return;
+       }
+
        if (first_move) {
 
                // create a dummy marker for visual representation of moving the
@@ -2172,6 +2203,13 @@ void
 MeterMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 {
        if (!movement_occurred) {
+               if (was_double_click()) {
+                       _editor->edit_meter_marker (*_marker);
+               }
+               return;
+       }
+
+       if (!_marker->meter().movable()) {
                return;
        }
 
@@ -2247,6 +2285,10 @@ TempoMarkerDrag::setup_pointer_frame_offset ()
 void
 TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
 {
+       if (!_marker->tempo().movable()) {
+               return;
+       }
+
        if (first_move) {
 
                // create a dummy marker for visual representation of moving the
@@ -2291,6 +2333,13 @@ void
 TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 {
        if (!movement_occurred) {
+               if (was_double_click()) {
+                       _editor->edit_tempo_marker (*_marker);
+               }
+               return;
+       }
+
+       if (!_marker->tempo().movable()) {
                return;
        }
 
@@ -2358,8 +2407,14 @@ CursorDrag::fake_locate (framepos_t t)
        Session* s = _editor->session ();
        if (s->timecode_transmission_suspended ()) {
                framepos_t const f = _editor->playhead_cursor->current_frame ();
+               /* This is asynchronous so it will be sent "now"
+                */
                s->send_mmc_locate (f);
-               s->send_full_time_code (f);
+               /* These are synchronous and will be sent during the next
+                  process cycle
+               */
+               s->queue_full_time_code ();
+               s->queue_song_position_pointer ();
        }
 
        show_verbose_cursor_time (t);
@@ -2373,7 +2428,7 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
 
        _grab_zoom = _editor->samples_per_pixel;
 
-       framepos_t where = _editor->canvas_event_frame (event, 0, 0);
+       framepos_t where = _editor->canvas_event_frame (event);
 
        _editor->snap_to_with_modifier (where, event);
 
@@ -2974,6 +3029,11 @@ void
 MarkerDrag::finished (GdkEvent* event, bool movement_occurred)
 {
        if (!movement_occurred) {
+               
+               if (was_double_click()) {
+                       _editor->rename_marker (_marker);
+                       return;
+               }
 
                /* just a click, do nothing but finish
                   off the selection process
@@ -3258,10 +3318,24 @@ LineDrag::motion (GdkEvent* event, bool)
 }
 
 void
-LineDrag::finished (GdkEvent* event, bool)
+LineDrag::finished (GdkEvent* event, bool movement_occured)
 {
-       motion (event, false);
-       _line->end_drag (false, 0);
+       if (movement_occured) {
+               motion (event, false);
+               _line->end_drag (false, 0);
+       } else {
+               /* add a new control point on the line */
+
+               AutomationTimeAxisView* atv;
+
+               _line->end_drag (false, 0);
+
+               if ((atv = dynamic_cast<AutomationTimeAxisView*>(_editor->clicked_axisview)) != 0) {
+                       framepos_t where = _editor->event_frame (event, 0, 0);
+                       atv->add_automation_event (event, where, event->button.y, false);
+               }
+       }
+
        _editor->session()->commit_reversible_command ();
 }
 
@@ -3399,16 +3473,28 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool)
 
                double x1 = _editor->sample_to_pixel (start);
                double x2 = _editor->sample_to_pixel (end);
+               const double min_dimension = 2.0;
 
                _editor->rubberband_rect->set_x0 (x1);
                if (_vertical_only) {
                        /* fixed 10 pixel width */
                        _editor->rubberband_rect->set_x1 (x1 + 10);
                } else {
+                       if (x2 < x1) {
+                               x2 = min (x1 - min_dimension, x2);
+                       } else {
+                               x2 = max (x1 + min_dimension, x2);
+                       }
                        _editor->rubberband_rect->set_x1 (x2);
                } 
 
                _editor->rubberband_rect->set_y0 (y1);
+               if (y2 < y1) {
+                       y2 = min (y1 - min_dimension, y2);
+               } else {
+                       y2 = max (y1 + min_dimension, y2);
+               }
+
                _editor->rubberband_rect->set_y1 (y2);
                
                _editor->rubberband_rect->show();
@@ -4087,10 +4173,24 @@ RangeMarkerBarDrag::finished (GdkEvent* event, bool movement_occurred)
                        _editor->new_transport_marker_context_menu (&event->button, _item);
                        break;
                }
+
        } else {
+
                /* just a click, no pointer movement. remember that context menu stuff was handled elsewhere */
 
-               if (Keyboard::no_modifier_keys_pressed (&event->button) && _operation != CreateCDMarker) {
+               if (_operation == CreateTransportMarker) {
+
+                       /* didn't drag, so just locate */
+
+                       _editor->session()->request_locate (grab_frame(), _editor->session()->transport_rolling());
+
+               } else if (_operation == CreateCDMarker) {
+
+                       /* didn't drag, but mark is already created so do
+                        * nothing */
+
+               } else { /* operation == CreateRangeMarker */
+                       
 
                        framepos_t start;
                        framepos_t end;
@@ -4328,7 +4428,7 @@ NoteDrag::motion (GdkEvent *, bool)
                uint8_t new_note = min (max (_primary->note()->note() + note_delta, 0), 127);
                
                snprintf (buf, sizeof (buf), "%s (%d)", Evoral::midi_note_name (new_note).c_str(),
-                         (int) floor (new_note));
+                         (int) floor ((double)new_note));
 
                show_verbose_cursor_text (buf);
        }
@@ -4832,7 +4932,7 @@ NoteCreateDrag::finished (GdkEvent*, bool had_movement)
        }
        
        framepos_t const start = min (_note[0], _note[1]);
-       framecnt_t length = (framecnt_t) fabs (_note[0] - _note[1]);
+       framecnt_t length = (framecnt_t) fabs ((double)(_note[0] - _note[1]));
 
        framecnt_t const g = grid_frames (start);
        double const one_tick = 1 / Timecode::BBT_Time::ticks_per_beat;