remove all MIDI-specific editing modes by making standard work either at object level...
[ardour.git] / gtk2_ardour / editor_canvas.cc
index 428334dfc6a3645075b3be54c467ac2eeedb65e1..b99189218a0fcd362a3e7b8ed0abc6b48f97b709 100644 (file)
@@ -22,7 +22,6 @@
 #include <jack/types.h>
 #include <gtkmm2ext/utils.h>
 
-#include "ardour/audioregion.h"
 #include "ardour/profile.h"
 
 #include "ardour_ui.h"
 #include "editing.h"
 #include "rgb_macros.h"
 #include "utils.h"
-#include "time_axis_view.h"
 #include "audio_time_axis.h"
+#include "editor_drag.h"
+#include "region_view.h"
+#include "editor_group_tabs.h"
+#include "editor_routes.h"
 
 #include "i18n.h"
 
@@ -152,9 +154,6 @@ Editor::initialize_canvas ()
        _background_group = new ArdourCanvas::Group (*track_canvas->root());
        _master_group = new ArdourCanvas::Group (*track_canvas->root());
 
-       range_marker_drag_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, physical_screen_height);
-       range_marker_drag_rect->hide ();
-
        _trackview_group = new ArdourCanvas::Group (*_master_group);
        _region_motion_group = new ArdourCanvas::Group (*_trackview_group);
 
@@ -228,14 +227,6 @@ Editor::initialize_canvas ()
        marker_group = new ArdourCanvas::Group (*timebar_group, 0.0, timebar_height);
        cd_marker_group = new ArdourCanvas::Group (*timebar_group, 0.0, 0.0);
 
-       marker_drag_line_points.push_back(Gnome::Art::Point(0.0, 0.0));
-       marker_drag_line_points.push_back(Gnome::Art::Point(0.0, physical_screen_height));
-
-       marker_drag_line = new ArdourCanvas::Line (*timebar_group);
-       marker_drag_line->property_width_pixels() = 1;
-       marker_drag_line->property_points() = marker_drag_line_points;
-       marker_drag_line->hide();
-
        cd_marker_bar_drag_rect = new ArdourCanvas::SimpleRect (*cd_marker_group, 0.0, 0.0, 100, timebar_height);
        cd_marker_bar_drag_rect->property_outline_pixels() = 0;
        cd_marker_bar_drag_rect->hide ();
@@ -282,7 +273,7 @@ Editor::initialize_canvas ()
        range_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_range_marker_bar_event), range_marker_bar));
        transport_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_transport_marker_bar_event), transport_marker_bar));
 
-       playhead_cursor = new Cursor (*this, &Editor::canvas_playhead_cursor_event);
+       playhead_cursor = new EditorCursor (*this, &Editor::canvas_playhead_cursor_event);
 
        if (logo_item) {
                logo_item->lower_to_bottom ();
@@ -293,6 +284,7 @@ Editor::initialize_canvas ()
        track_canvas->signal_motion_notify_event().connect (mem_fun (*this, &Editor::track_canvas_motion_notify_event));
        track_canvas->signal_button_press_event().connect (mem_fun (*this, &Editor::track_canvas_button_press_event));
        track_canvas->signal_button_release_event().connect (mem_fun (*this, &Editor::track_canvas_button_release_event));
+       track_canvas->signal_drag_motion().connect (mem_fun (*this, &Editor::track_canvas_drag_motion));
 
        track_canvas->set_name ("EditorMainCanvas");
        track_canvas->add_events (Gdk::POINTER_MOTION_HINT_MASK|Gdk::SCROLL_MASK);
@@ -331,10 +323,10 @@ Editor::track_canvas_allocate (Gtk::Allocation alloc)
 bool
 Editor::track_canvas_size_allocated ()
 {
-       bool height_changed = canvas_height != canvas_allocation.get_height();
+       bool height_changed = _canvas_height != canvas_allocation.get_height();
 
-       canvas_width = canvas_allocation.get_width();
-       canvas_height = canvas_allocation.get_height();
+       _canvas_width = canvas_allocation.get_width();
+       _canvas_height = canvas_allocation.get_height();
 
        if (session) {
                TrackViewList::iterator i;
@@ -350,21 +342,21 @@ Editor::track_canvas_size_allocated ()
 
        if (height_changed) {
                if (playhead_cursor) {
-                       playhead_cursor->set_length (canvas_height);
+                       playhead_cursor->set_length (_canvas_height);
                }
        
                for (MarkerSelection::iterator x = selection->markers.begin(); x != selection->markers.end(); ++x) {
-                       (*x)->set_line_vpos (0, canvas_height);
+                       (*x)->set_line_vpos (0, _canvas_height);
                }
 
-               vertical_adjustment.set_page_size (canvas_height);
+               vertical_adjustment.set_page_size (_canvas_height);
                last_trackview_group_vertical_offset = get_trackview_group_vertical_offset ();
-               if ((vertical_adjustment.get_value() + canvas_height) >= vertical_adjustment.get_upper()) {
+               if ((vertical_adjustment.get_value() + _canvas_height) >= vertical_adjustment.get_upper()) {
                        /* 
                           We're increasing the size of the canvas while the bottom is visible.
                           We scroll down to keep in step with the controls layout.
                        */
-                       vertical_adjustment.set_value (full_canvas_height - canvas_height);
+                       vertical_adjustment.set_value (full_canvas_height - _canvas_height);
                }
        }
 
@@ -372,6 +364,7 @@ Editor::track_canvas_size_allocated ()
        reset_hscrollbar_stepping ();
        update_fixed_rulers();
        redisplay_tempo (false);
+       _summary->set_overlays_dirty ();
 
        Resized (); /* EMIT_SIGNAL */
 
@@ -381,21 +374,22 @@ Editor::track_canvas_size_allocated ()
 void
 Editor::controls_layout_size_request (Requisition* req)
 {
-       TreeModel::Children rows = route_display_model->children();
-       TreeModel::Children::iterator i;
-       double pos;
-       bool changed = false;
-
-       for (pos = 0, i = rows.begin(); i != rows.end(); ++i) {
-               TimeAxisView *tv = (*i)[route_display_columns.tv];
-               if (tv != 0) {
-                       pos += tv->effective_height ();
-                       tv->clip_to_viewport ();
-               }
+       double pos = 0;
+       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               pos += (*i)->effective_height ();
+               (*i)->clip_to_viewport ();
        }
 
        gint height = min ((gint) pos, (gint) (physical_screen_height - 600));
-       gint width = max (edit_controls_vbox.get_width(),  controls_layout.get_width());
+       
+       bool changed = false;
+
+       gint w = edit_controls_vbox.get_width();
+       if (_group_tabs->is_mapped()) {
+               w += _group_tabs->get_width ();
+       }
+               
+       gint width = max (w, controls_layout.get_width());
 
        /* don't get too big. the fudge factors here are just guesses */
 
@@ -408,6 +402,9 @@ Editor::controls_layout_size_request (Requisition* req)
 
        if (req->width != width) {
                gint vbox_width = edit_controls_vbox.get_width();
+               if (_group_tabs->is_mapped()) {
+                       vbox_width += _group_tabs->get_width();
+               }
                req->width = width;
 
                /* this one is important: it determines how big the layout thinks it really is, as 
@@ -416,8 +413,8 @@ Editor::controls_layout_size_request (Requisition* req)
                controls_layout.property_width () = vbox_width;
                controls_layout.property_width_request () = vbox_width;
 
-               time_button_event_box.property_width_request () = vbox_width;
-               zoom_box.property_width_request () = vbox_width;
+               // time_button_event_box.property_width_request () = vbox_width;
+               // zoom_box.property_width_request () = vbox_width;
        }
 
        if (req->height != height) {
@@ -433,9 +430,11 @@ Editor::controls_layout_size_request (Requisition* req)
 }
 
 bool
-Editor::track_canvas_map_handler (GdkEventAny* ev)
+Editor::track_canvas_map_handler (GdkEventAny* /*ev*/)
 {
-       track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+       if (current_canvas_cursor) {
+               track_canvas->get_window()->set_cursor (*current_canvas_cursor);
+       }
        return false;
 }
 
@@ -537,41 +536,30 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
 }
 
 void
-Editor::drop_regions (const RefPtr<Gdk::DragContext>& context,
-                     int x, int y
-                     const SelectionData& data,
-                     guint info, guint time)
+Editor::drop_regions (const RefPtr<Gdk::DragContext>& /*context*/,
+                     int /*x*/, int /*y*/
+                     const SelectionData& /*data*/,
+                     guint /*info*/, guint /*time*/)
 {
-       std::list<boost::shared_ptr<Region> > regions;
-       Gtk::TreeView* source;
-       region_list_display.get_object_drag_data (regions, &source);
-
-       for (list<boost::shared_ptr<Region> >::iterator r = regions.begin(); r != regions.end(); ++r) {
-
-               boost::shared_ptr<AudioRegion> ar;
-
-               if ((ar = boost::dynamic_pointer_cast<AudioRegion>(*r)) != 0) {
-                       insert_region_list_drag (ar, x, y);
-               }
-       }
-
-       context->drag_finish (true, false, time);
+       assert (_drag);
+       _drag->end_grab (0);
+       delete _drag;
+       _drag = 0;
 }
 
 void
-Editor::maybe_autoscroll (GdkEventMotion* event)
+Editor::maybe_autoscroll (GdkEventMotion* event, bool allow_vert)
 {
-
        nframes64_t rightmost_frame = leftmost_frame + current_page_frames();
-       nframes64_t frame = drag_info.current_pointer_frame;
+       nframes64_t frame = _drag->current_pointer_frame();
        bool startit = false;
 
        autoscroll_y = 0;
        autoscroll_x = 0;
-       if (event->y < canvas_timebars_vsize) {
+       if (event->y < canvas_timebars_vsize && allow_vert) {
                autoscroll_y = -1;
                startit = true;
-       } else if (event->y > canvas_height) {
+       } else if (event->y > _canvas_height) {
                autoscroll_y = 1;
                startit = true;
        }
@@ -607,43 +595,6 @@ Editor::maybe_autoscroll (GdkEventMotion* event)
        last_autoscroll_y = autoscroll_y;
 }
 
-void
-Editor::maybe_autoscroll_horizontally (GdkEventMotion* event)
-{
-       nframes64_t rightmost_frame = leftmost_frame + current_page_frames();
-       nframes64_t frame = drag_info.current_pointer_frame;
-       bool startit = false;
-
-       autoscroll_y = 0;
-       autoscroll_x = 0;
-
-       if (frame > rightmost_frame) {
-
-               if (rightmost_frame < max_frames) {
-                       autoscroll_x = 1;
-                       startit = true;
-               }
-
-       } else if (frame < leftmost_frame) {
-               if (leftmost_frame > 0) {
-                       autoscroll_x = -1;
-                       startit = true;
-               }
-
-       }
-
-       if ((autoscroll_x != last_autoscroll_x) || (autoscroll_y != last_autoscroll_y) || (autoscroll_x == 0 && autoscroll_y == 0)) {
-               stop_canvas_autoscroll ();
-       }
-       
-       if (startit && autoscroll_timeout_tag < 0) {
-               start_canvas_autoscroll (autoscroll_x, autoscroll_y);
-       }
-
-       last_autoscroll_x = autoscroll_x;
-       last_autoscroll_y = autoscroll_y;
-}
-
 gint
 Editor::_autoscroll_canvas (void *arg)
 {
@@ -659,21 +610,23 @@ Editor::autoscroll_canvas ()
        double new_pixel;
        double target_pixel;
 
+       assert (_drag);
+
        if (autoscroll_x_distance != 0) {
                if (autoscroll_x > 0) {
-                       autoscroll_x_distance = (unit_to_frame (drag_info.current_pointer_x) - (leftmost_frame + current_page_frames())) / 3;
+                       autoscroll_x_distance = (unit_to_frame (_drag->current_pointer_x()) - (leftmost_frame + current_page_frames())) / 3;
                } else if (autoscroll_x < 0) {
-                       autoscroll_x_distance = (leftmost_frame - unit_to_frame (drag_info.current_pointer_x)) / 3;
+                       autoscroll_x_distance = (leftmost_frame - unit_to_frame (_drag->current_pointer_x())) / 3;
 
                }
        }
 
        if (autoscroll_y_distance != 0) {
                if (autoscroll_y > 0) {
-                       autoscroll_y_distance = (drag_info.current_pointer_y - (get_trackview_group_vertical_offset() + canvas_height)) / 3;
+                       autoscroll_y_distance = (_drag->current_pointer_y() - (get_trackview_group_vertical_offset() + _canvas_height)) / 3;
                } else if (autoscroll_y < 0) {
 
-                       autoscroll_y_distance = (vertical_adjustment.get_value () - drag_info.current_pointer_y) / 3;
+                       autoscroll_y_distance = (vertical_adjustment.get_value () - _drag->current_pointer_y()) / 3;
                }
        }
 
@@ -703,12 +656,12 @@ Editor::autoscroll_canvas ()
                        new_pixel = vertical_pos - autoscroll_y_distance;
                }
 
-               target_pixel = drag_info.current_pointer_y - autoscroll_y_distance;
+               target_pixel = _drag->current_pointer_y() - autoscroll_y_distance;
                target_pixel = max (target_pixel, 0.0);
 
        } else if (autoscroll_y > 0) {
 
-               double top_of_bottom_of_canvas = full_canvas_height - canvas_height;
+               double top_of_bottom_of_canvas = full_canvas_height - _canvas_height;
 
                if (vertical_pos > full_canvas_height - autoscroll_y_distance) {
                        new_pixel = full_canvas_height;
@@ -718,7 +671,7 @@ Editor::autoscroll_canvas ()
 
                new_pixel = min (top_of_bottom_of_canvas, new_pixel);
 
-               target_pixel = drag_info.current_pointer_y + autoscroll_y_distance;
+               target_pixel = _drag->current_pointer_y() + autoscroll_y_distance;
                
                /* don't move to the full canvas height because the item will be invisible
                   (its top edge will line up with the bottom of the visible canvas.
@@ -727,7 +680,7 @@ Editor::autoscroll_canvas ()
                target_pixel = min (target_pixel, full_canvas_height - 10);
                
        } else {
-               target_pixel = drag_info.current_pointer_y;
+               target_pixel = _drag->current_pointer_y();
                new_pixel = vertical_pos;
        }
 
@@ -753,7 +706,7 @@ Editor::autoscroll_canvas ()
        ev.x = x;
        ev.y = y;
 
-       motion_handler (drag_info.item, (GdkEvent*) &ev, drag_info.item_type, true);
+       motion_handler (_drag->item(), (GdkEvent*) &ev, true);
 
        autoscroll_cnt++;
 
@@ -803,7 +756,7 @@ Editor::stop_canvas_autoscroll ()
 }
 
 bool
-Editor::left_track_canvas (GdkEventCrossing *ev)
+Editor::left_track_canvas (GdkEventCrossing */*ev*/)
 {
        set_entered_track (0);
        set_entered_regionview (0);
@@ -812,7 +765,7 @@ Editor::left_track_canvas (GdkEventCrossing *ev)
 }
 
 bool
-Editor::entered_track_canvas (GdkEventCrossing *ev)
+Editor::entered_track_canvas (GdkEventCrossing */*ev*/)
 {
        reset_canvas_action_sensitivity (true);
        return FALSE;
@@ -826,31 +779,35 @@ Editor::tie_vertical_scrolling ()
        /* this will do an immediate redraw */
 
        controls_layout.get_vadjustment()->set_value (vertical_adjustment.get_value());
+
+       if (pending_visual_change.idle_handler_id < 0) {
+               _summary->set_overlays_dirty ();
+       }
 }
 
 void
 Editor::scroll_canvas_horizontally ()
 {
-       nframes64_t time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
-
-       if (time_origin != leftmost_frame) {
-               canvas_scroll_to (time_origin);
-       }
-
        /* horizontal scrolling only */
-       double x1, x2, y1, y2, x_delta;
+       double x1, y1, x2, y2, x_delta;
+       _master_group->get_bounds (x1, y1, x2, y2);
+
+       x_delta = - (x1 +  horizontal_adjustment.get_value());
 
-       _master_group->get_bounds(x1, y1, x2, y2);
-       x_delta = x1 + horizontal_adjustment.get_value();
+       _master_group->move (x_delta, 0);
+       timebar_group->move (x_delta, 0);
+       time_line_group->move (x_delta, 0);
+       cursor_group->move (x_delta, 0);
 
-       _master_group->move (-x_delta, 0);
-       timebar_group->move (-x_delta, 0);
-       time_line_group->move (-x_delta, 0);
-       cursor_group->move (-x_delta, 0);
+       leftmost_frame = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
 
        update_fixed_rulers ();
        redisplay_tempo (true);
 
+       if (pending_visual_change.idle_handler_id < 0) {
+               _summary->set_overlays_dirty ();
+       }
+
 #ifndef GTKOSX
        if (!autoscroll_active) {
                /* force rulers and canvas to move in lock step */
@@ -878,24 +835,7 @@ Editor::scroll_canvas_vertically ()
        }
        last_trackview_group_vertical_offset = get_trackview_group_vertical_offset ();
        /* required to keep the controls_layout in lock step with the canvas group */
-       track_canvas->update_now ();
-}
-
-void 
-Editor::canvas_horizontally_scrolled ()
-{
-       nframes64_t time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
-
-       if (time_origin != leftmost_frame) {
-               canvas_scroll_to (time_origin);
-       }
-       redisplay_tempo (true);
-}
-
-void
-Editor::canvas_scroll_to (nframes64_t time_origin)
-{
-       leftmost_frame = time_origin;
+       update_canvas_now ();
 }
 
 void
@@ -931,11 +871,6 @@ Editor::color_handler()
        transport_bar_drag_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TransportDragRect.get();
        transport_bar_drag_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TransportDragRect.get();
 
-       marker_drag_line->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MarkerDragLine.get();
-
-       range_marker_drag_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeDragRect.get();
-       range_marker_drag_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_RangeDragRect.get();
-
        transport_loop_range_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_TransportLoopRect.get();
        transport_loop_range_rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_TransportLoopRect.get();
 
@@ -970,8 +905,25 @@ void
 Editor::flush_canvas ()
 {
        if (is_mapped()) {
-               track_canvas->update_now ();
+               update_canvas_now ();
                // gdk_window_process_updates (GTK_LAYOUT(track_canvas->gobj())->bin_window, true);
        }
 }
 
+void
+Editor::update_canvas_now ()
+{
+       /* GnomeCanvas has a bug whereby if its idle handler is not scheduled between
+          two calls to update_now, an assert will trip.  This wrapper works around
+          that problem by only calling update_now if the assert will not trip.
+
+          I think the GC bug is due to the fact that its code will reset need_update
+          and need_redraw to FALSE without checking to see if an idle handler is scheduled.
+          If one is scheduled, GC should probably remove it.
+       */
+       
+       GnomeCanvas* c = track_canvas->gobj ();
+       if (c->need_update || c->need_redraw) {
+               track_canvas->update_now ();
+       }
+}