Fix some capitalisation in the preferences dialog.
[ardour.git] / gtk2_ardour / editor_canvas.cc
index a4927192fe3bbd51fee830861fdb96a5ec16e511..3b9c5dea379608c88c022783ca97950ccb81372b 100644 (file)
@@ -21,8 +21,6 @@
 #include "gtk2ardour-config.h"
 #endif
 
-#include <jack/types.h>
-
 #include "gtkmm2ext/utils.h"
 
 #include "ardour/profile.h"
@@ -64,7 +62,7 @@ using namespace Editing;
 
 /* XXX this is a hack. it ought to be the maximum value of an framepos_t */
 
-const double max_canvas_coordinate = (double) JACK_MAX_FRAMES;
+const double max_canvas_coordinate = (double) UINT32_MAX;
 
 void
 Editor::initialize_canvas ()
@@ -86,7 +84,7 @@ Editor::initialize_canvas ()
                // logo_item->property_width_in_pixels() = true;
                // logo_item->property_height_set() = true;
                // logo_item->property_width_set() = true;
-               logo_item->show ();
+               // logo_item->show ();
        }
        
        /*a group to hold global rects like punch/loop indicators */
@@ -194,12 +192,10 @@ Editor::initialize_canvas ()
        // used to show zoom mode active zooming
        zoom_rect = new ArdourCanvas::Rectangle (_track_canvas->root(), ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
        zoom_rect->hide();
-
        zoom_rect->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0));
 
        // used as rubberband rect
        rubberband_rect = new ArdourCanvas::Rectangle (_trackview_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
-
        rubberband_rect->hide();
 
        tempo_bar->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_tempo_bar_event), tempo_bar));
@@ -215,7 +211,17 @@ Editor::initialize_canvas ()
        if (logo_item) {
                logo_item->lower_to_bottom ();
        }
-       /* need to handle 4 specific types of events as catch-alls */
+
+
+       _canvas_bottom_rect = new ArdourCanvas::Rectangle (_track_canvas->root(), ArdourCanvas::Rect (0.0, 0.0, max_canvas_coordinate, 20));
+       /* this thing is transparent */
+       _canvas_bottom_rect->set_fill (false);
+       _canvas_bottom_rect->set_outline (false);
+       _canvas_bottom_rect->Event.connect (sigc::mem_fun (*this, &Editor::canvas_bottom_rect_event));
+
+       /* these signals will initially be delivered to the canvas itself, but if they end up remaining unhandled, they are passed to Editor-level
+          handlers.
+       */
 
        _track_canvas->signal_scroll_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_scroll_event));
        _track_canvas->signal_motion_notify_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_motion_notify_event));
@@ -259,7 +265,7 @@ Editor::track_canvas_viewport_allocate (Gtk::Allocation alloc)
        track_canvas_viewport_size_allocated ();
 }
 
-bool
+void
 Editor::track_canvas_viewport_size_allocated ()
 {
        bool height_changed = _visible_canvas_height != _canvas_viewport_allocation.get_height();
@@ -283,13 +289,13 @@ Editor::track_canvas_viewport_size_allocated ()
                        */
                        vertical_adjustment.set_value (_full_canvas_height - _visible_canvas_height);
                }
+
+               set_visible_track_count (_visible_track_count);
        }
 
        update_fixed_rulers();
        redisplay_tempo (false);
        _summary->set_overlays_dirty ();
-
-       return false;
 }
 
 void
@@ -317,12 +323,24 @@ Editor::reset_controls_layout_width ()
 void
 Editor::reset_controls_layout_height (int32_t h)
 {
+       /* ensure that the rect that represents the "bottom" of the canvas
+        * (the drag-n-drop zone) is, in fact, at the bottom.
+        */
+
+       _canvas_bottom_rect->set_position (ArdourCanvas::Duple (0, h));
+
+       /* track controls layout must span the full height of "h" (all tracks)
+        * plus the bottom rect.
+        */
+
+       h += _canvas_bottom_rect->height ();
+
         /* set the height of the scrollable area (i.e. the sum of all contained widgets)
+        * for the controls layout. The size request is set elsewhere.
          */
 
         controls_layout.property_height() = h;
 
-        /* size request is set elsewhere, see ::track_canvas_allocate() */
 }
 
 bool
@@ -462,56 +480,42 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers)
                return;
        }
 
-       if (autoscroll_boundary.empty()) {
 
-               ArdourCanvas::Rect scrolling_boundary;
-               Gtk::Allocation alloc;
+       ArdourCanvas::Rect scrolling_boundary;
+       Gtk::Allocation alloc;
+       
+       if (from_headers) {
+               alloc = controls_layout.get_allocation ();
+       } else {
+               alloc = _track_canvas_viewport->get_allocation ();
                
-               if (from_headers) {
-                       alloc = controls_layout.get_allocation ();
-               } else {
-                       alloc = _track_canvas_viewport->get_allocation ();
-
-                       /* Increase the autoscroll area to include the rulers.
-                          
-                          XXX this can go away once the two canvases are
-                          unified.
-                       */
-                       
-                       Gdk::Rectangle timebars = time_canvas_event_box.get_allocation ();
-                       alloc.set_y (timebars.get_y());
-                       alloc.set_height (alloc.get_height() + timebars.get_height());
-                       
-                       /* if there is no other widget on the right side of
-                          the canvas, reduce the effective width of
-                          the autoscroll boundary so that we start scrolling
-                          before we hit the edge.
-
-                          this helps when the window is slammed up against
-                          the right edge of the screen, making it hard to 
-                          scroll effectively.
-                       */
-
-                       if (alloc.get_width() > 10) { 
-                               alloc.set_width (alloc.get_width() - 10);
-                       } 
-               }
+               /* the effective width of the autoscroll boundary so
+                  that we start scrolling before we hit the edge.
+                  
+                  this helps when the window is slammed up against the
+                  right edge of the screen, making it hard to scroll
+                  effectively.
+               */
                
-               autoscroll_boundary = ArdourCanvas::Rect (alloc.get_x(), alloc.get_y(), 
-                                                         alloc.get_x() + alloc.get_width(), 
-                                                         alloc.get_y() + alloc.get_height());
+               if (alloc.get_width() > 20) { 
+                       alloc.set_width (alloc.get_width() - 20);
+                       alloc.set_x (alloc.get_x() + 10);
+               } 
        }
-
+       
+       scrolling_boundary = ArdourCanvas::Rect (alloc.get_x(), alloc.get_y(), 
+                                                alloc.get_x() + alloc.get_width(), 
+                                                alloc.get_y() + alloc.get_height());
+       
        int x, y;
        Gdk::ModifierType mask;
 
        get_window()->get_pointer (x, y, mask);
 
-       if (!autoscroll_boundary.contains (ArdourCanvas::Duple (x, y))) {
-               if (!autoscroll_active()) {
-                       start_canvas_autoscroll (allow_horiz, allow_vert);
-               }
-       } 
+       if ((allow_horiz && (x < scrolling_boundary.x0 || x >= scrolling_boundary.x1)) ||
+           (allow_vert && (y < scrolling_boundary.y0 || y >= scrolling_boundary.y1))) {
+               start_canvas_autoscroll (allow_horiz, allow_vert, scrolling_boundary);
+       }
 }
 
 bool
@@ -526,8 +530,8 @@ Editor::autoscroll_canvas ()
        int x, y;
        Gdk::ModifierType mask;
        frameoffset_t dx = 0;
-       double dy = 0;
        bool no_stop = false;
+       bool y_motion = false;
 
        get_window()->get_pointer (x, y, mask);
 
@@ -581,57 +585,38 @@ Editor::autoscroll_canvas ()
                
                const double vertical_pos = vertical_adjustment.get_value();
                double new_pixel = vertical_pos;
+               const int speed_factor = 20;
 
                /* vertical */ 
                
                new_pixel = vertical_pos;
-               
+
                if (y < autoscroll_boundary.y0) {
 
                        /* scroll to make higher tracks visible */
 
-                       const int step_size = _visible_canvas_height / 100;
-
-                       dy = autoscroll_boundary.y0 - y;
-                       dy += step_size + (step_size * (autoscroll_cnt/10));
-
-                       if (vertical_pos > dy) {
-                               new_pixel = vertical_pos - dy;
-                       } else {
-                               new_pixel = 0;
+                       if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
+                               y_motion = scroll_up_one_track ();
                        }
 
-                       no_stop = true;
-
                } else if (y > autoscroll_boundary.y1) {
 
-                       /* scroll to make lower tracks visible */
-
-                       const int step_size = _visible_canvas_height / 100;
-
-                       dy = y - autoscroll_boundary.y1;
-                       dy +=  step_size + (step_size * (autoscroll_cnt/10));
-
-                       /* unlike horizontally, we never want to scroll past the lower edge of the full canvas as defined by all visible tracks
-                        */
-                       new_pixel = min (_full_canvas_height - _visible_canvas_height, min (_full_canvas_height, vertical_pos + dy));
-                       /* adjust dy to match */
-                       dy = vertical_pos - new_pixel; 
-
-                       no_stop = true;
-               }
-               
-               if (new_pixel != vertical_pos) {
-                       vc.add (VisualChange::YOrigin);
-                       vc.y_origin = new_pixel;
+                       if (autoscroll_cnt && (autoscroll_cnt % speed_factor == 0)) {
+                               y_motion = scroll_down_one_track ();
+                               
+                       }
                }
+
+               no_stop = true;
        }
 
        if (vc.pending) {
 
-               /* change horizontal & vertical position first */
+               /* change horizontal first */
 
-               visual_changer (vc);
+               if (vc.pending) {
+                       visual_changer (vc);
+               }
 
                /* now send a motion event to notify anyone who cares
                   that we have moved to a new location (because we scrolled)
@@ -684,9 +669,16 @@ Editor::autoscroll_canvas ()
                int cx;
                int cy;
 
-               /* clamp x and y to remain within the visible area */
+               /* clamp x and y to remain within the visible area. except
+                * .. if horizontal scrolling is allowed, always allow us to
+                * move back to zero
+                */
 
-               x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1);
+               if (autoscroll_horizontal_allowed) {
+                       x = min (max ((ArdourCanvas::Coord) x, 0.0), autoscroll_boundary.x1);
+               } else {
+                       x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1);
+               }
                y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1);
 
                translate_coordinates (*_track_canvas_viewport, x, y, cx, cy);
@@ -699,7 +691,6 @@ Editor::autoscroll_canvas ()
 
        } else {
                stop_canvas_autoscroll ();
-               autoscroll_boundary = ArdourCanvas::Rect();
                return false;
        }
 
@@ -709,7 +700,7 @@ Editor::autoscroll_canvas ()
 }      
 
 void
-Editor::start_canvas_autoscroll (bool allow_horiz, bool allow_vert)
+Editor::start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary)
 {
        if (!_session) {
                return;
@@ -720,6 +711,7 @@ Editor::start_canvas_autoscroll (bool allow_horiz, bool allow_vert)
        autoscroll_cnt = 0;
        autoscroll_horizontal_allowed = allow_horiz;
        autoscroll_vertical_allowed = allow_vert;
+       autoscroll_boundary = boundary;
 
        /* do the first scroll right now
        */
@@ -757,19 +749,26 @@ Editor::entered_track_canvas (GdkEventCrossing */*ev*/)
 }
 
 void
-Editor::ensure_time_axis_view_is_visible (const TimeAxisView& tav)
+Editor::_ensure_time_axis_view_is_visible (const TimeAxisView& tav, bool at_top)
 {
        double begin = tav.y_position();
-
        double v = vertical_adjustment.get_value ();
 
-       if (begin < v || begin + tav.current_height() > v + _visible_canvas_height) {
+       if (!at_top && (begin < v || begin + tav.current_height() > v + _visible_canvas_height)) {
                /* try to put the TimeAxisView roughly central */
                if (begin >= _visible_canvas_height/2.0) {
                        begin -= _visible_canvas_height/2.0;
                }
-               vertical_adjustment.set_value (begin);
        }
+
+       /* Clamp the y pos so that we do not extend beyond the canvas full
+        * height. 
+        */
+       if (_full_canvas_height - begin < _visible_canvas_height){
+               begin = _full_canvas_height - _visible_canvas_height;
+       }
+
+       vertical_adjustment.set_value (begin);
 }
 
 /** Called when the main vertical_adjustment has changed */