X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_canvas.cc;h=3b9c5dea379608c88c022783ca97950ccb81372b;hb=e36f74e071d4c14862d23da5ff0d49df0940d536;hp=a4927192fe3bbd51fee830861fdb96a5ec16e511;hpb=9df3157dfc59c596bf8f044fc4ab5445a12f02a1;p=ardour.git diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index a4927192fe..3b9c5dea37 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -21,8 +21,6 @@ #include "gtk2ardour-config.h" #endif -#include - #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 */