X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_summary.cc;h=e7355b577c97d57b807bbb71ad5e8eac003ff3d7;hb=69777d600fe2e1e034d24551ac9faec2c2481584;hp=4a238259efce0a711da272f5c489e2f526df71af;hpb=d06de26a4fd828b6a0a9da8718e3b0c829a4d162;p=ardour.git diff --git a/gtk2_ardour/editor_summary.cc b/gtk2_ardour/editor_summary.cc index 4a238259ef..e7355b577c 100644 --- a/gtk2_ardour/editor_summary.cc +++ b/gtk2_ardour/editor_summary.cc @@ -21,6 +21,9 @@ #include "canvas/debug.h" +#include +#include + #include "time_axis_view.h" #include "streamview.h" #include "editor_summary.h" @@ -35,6 +38,8 @@ #include "route_time_axis.h" #include "ui_config.h" +#include "pbd/i18n.h" + using namespace std; using namespace ARDOUR; using Gtkmm2ext::Keyboard; @@ -46,15 +51,13 @@ EditorSummary::EditorSummary (Editor* e) : EditorComponent (e), _start (0), _end (1), - _overhang_fraction (0.1), _x_scale (1), _track_height (16), _last_playhead (-1), _move_dragging (false), - _moved (false), _view_rectangle_x (0, 0), _view_rectangle_y (0, 0), - _zoom_dragging (false), + _zoom_trim_dragging (false), _old_follow_playhead (false), _image (0), _background_dirty (true) @@ -114,6 +117,9 @@ EditorSummary::set_session (Session* s) _session->EndTimeChanged.connect (_session_connections, invalidator (*this), boost::bind (&EditorSummary::set_background_dirty, this), gui_context()); _editor->selection->RegionsChanged.connect (sigc::mem_fun(*this, &EditorSummary::set_background_dirty)); } + + _leftmost = max_samplepos; + _rightmost = 0; } void @@ -124,7 +130,7 @@ EditorSummary::render_background_image () cairo_t* cr = cairo_create (_image); - /* background (really just the dividing lines between tracks */ + /* background (really just the dividing lines between tracks */ cairo_set_source_rgb (cr, 0, 0, 0); cairo_rectangle (cr, 0, 0, get_width(), get_height()); @@ -132,10 +138,26 @@ EditorSummary::render_background_image () /* compute start and end points for the summary */ - framecnt_t const session_length = _session->current_end_frame() - _session->current_start_frame (); - double const theoretical_start = _session->current_start_frame() - session_length * _overhang_fraction; + std::pair ext = _editor->session_gui_extents(); + double theoretical_start = ext.first; + double theoretical_end = ext.second; + + /* the summary should encompass the full extent of everywhere we've visited since the session was opened */ + if (_leftmost < theoretical_start) + theoretical_start = _leftmost; + if (_rightmost > theoretical_end) + theoretical_end = _rightmost; + + /* range-check */ _start = theoretical_start > 0 ? theoretical_start : 0; - _end = _session->current_end_frame() + session_length * _overhang_fraction; + _end = theoretical_end < max_samplepos ? theoretical_end : max_samplepos; + + /* calculate x scale */ + if (_end != _start) { + _x_scale = static_cast (get_width()) / (_end - _start); + } else { + _x_scale = 1; + } /* compute track height */ int N = 0; @@ -151,13 +173,6 @@ EditorSummary::render_background_image () _track_height = (double) get_height() / N; } - /* calculate x scale */ - if (_end != _start) { - _x_scale = static_cast (get_width()) / (_end - _start); - } else { - _x_scale = 1; - } - /* render tracks and regions */ double y = 0; @@ -169,11 +184,13 @@ EditorSummary::render_background_image () /* paint a non-bg colored strip to represent the track itself */ - cairo_set_source_rgb (cr, 0.2, 0.2, 0.2); - cairo_set_line_width (cr, _track_height - 1); - cairo_move_to (cr, 0, y + _track_height / 2); - cairo_line_to (cr, get_width(), y + _track_height / 2); - cairo_stroke (cr); + if (_track_height > 4) { + cairo_set_source_rgb (cr, 0.2, 0.2, 0.2); + cairo_set_line_width (cr, _track_height - 1); + cairo_move_to (cr, 0, y + _track_height / 2); + cairo_line_to (cr, get_width(), y + _track_height / 2); + cairo_stroke (cr); + } StreamView* s = (*i)->view (); @@ -181,10 +198,10 @@ EditorSummary::render_background_image () cairo_set_line_width (cr, _track_height * 0.8); s->foreach_regionview (sigc::bind ( - sigc::mem_fun (*this, &EditorSummary::render_region), - cr, - y + _track_height / 2 - )); + sigc::mem_fun (*this, &EditorSummary::render_region), + cr, + y + _track_height / 2 + )); } y += _track_height; @@ -195,11 +212,11 @@ EditorSummary::render_background_image () cairo_set_line_width (cr, 1); cairo_set_source_rgb (cr, 1, 1, 0); - const double p = (_session->current_start_frame() - _start) * _x_scale; + const double p = (_session->current_start_sample() - _start) * _x_scale; cairo_move_to (cr, p, 0); cairo_line_to (cr, p, get_height()); - double const q = (_session->current_end_frame() - _start) * _x_scale; + double const q = (_session->current_end_sample() - _start) * _x_scale; cairo_move_to (cr, q, 0); cairo_line_to (cr, q, get_height()); cairo_stroke (cr); @@ -219,6 +236,19 @@ EditorSummary::render (Cairo::RefPtr const& ctx, cairo_rectangle return; } + /* maintain the leftmost and rightmost locations that we've ever reached */ + samplecnt_t const leftmost = _editor->leftmost_sample (); + if (leftmost < _leftmost) { + _leftmost = leftmost; + _background_dirty = true; + } + samplecnt_t const rightmost = leftmost + _editor->current_page_samples(); + if (rightmost > _rightmost) { + _rightmost = rightmost; + _background_dirty = true; + } + + /* draw the background (regions, markers, etc) if they've changed */ if (!_image || _background_dirty) { render_background_image (); _background_dirty = false; @@ -233,21 +263,24 @@ EditorSummary::render (Cairo::RefPtr const& ctx, cairo_rectangle cairo_fill (cr); /* Render the view rectangle. If there is an editor visual pending, don't update - the view rectangle now --- wait until the expose event that we'll get after - the visual change. This prevents a flicker. - */ + * the view rectangle now --- wait until the expose event that we'll get after + * the visual change. This prevents a flicker. + */ if (_editor->pending_visual_change.idle_handler_id < 0) { get_editor (&_view_rectangle_x, &_view_rectangle_y); } int32_t width = _view_rectangle_x.second - _view_rectangle_x.first; - int32_t height = _view_rectangle_y.second - _view_rectangle_y.first; - cairo_rectangle (cr, _view_rectangle_x.first, _view_rectangle_y.first, width, height); - cairo_set_source_rgba (cr, 1, 1, 1, 0.1); - cairo_fill_preserve (cr); + std::min(8, width); + cairo_rectangle (cr, _view_rectangle_x.first, 0, width, get_height ()); + cairo_set_source_rgba (cr, 1, 1, 1, 0.15); + cairo_fill (cr); + + /* horiz zoom */ + cairo_rectangle (cr, _view_rectangle_x.first, 0, width, get_height ()); cairo_set_line_width (cr, 1); - cairo_set_source_rgba (cr, 1, 1, 1, 0.4); + cairo_set_source_rgba (cr, 1, 1, 1, 0.9); cairo_stroke (cr); /* Playhead */ @@ -256,7 +289,7 @@ EditorSummary::render (Cairo::RefPtr const& ctx, cairo_rectangle /* XXX: colour should be set from configuration file */ cairo_set_source_rgba (cr, 1, 0, 0, 1); - const double ph= playhead_frame_to_position (_editor->playhead_cursor->current_frame()); + const double ph= playhead_sample_to_position (_editor->playhead_cursor->current_sample()); cairo_move_to (cr, ph, 0); cairo_line_to (cr, ph, get_height()); cairo_stroke (cr); @@ -274,6 +307,13 @@ EditorSummary::render (Cairo::RefPtr const& ctx, cairo_rectangle void EditorSummary::render_region (RegionView* r, cairo_t* cr, double y) const { + /*NOTE: you can optimize this operation by coalescing adjacent regions into a single line stroke. + * In a session with a single track ~1,000 regions, this reduced render time from 14ms to 11 ms. + * However, you lose a lot of visual information. The current method preserves a sense of separation between regions. + * The current method shows the current selection (red regions), which needs to be preserved if this is optimized. + * I think it's not worth it for now, but we might choose to revisit this someday. + */ + uint32_t const c = r->get_fill_color (); cairo_set_source_rgb (cr, UINT_RGBA_R (c) / 255.0, UINT_RGBA_G (c) / 255.0, UINT_RGBA_B (c) / 255.0); @@ -311,9 +351,9 @@ EditorSummary::set_overlays_dirty () /** Set the summary so that just the overlays (viewbox, playhead etc.) in a given area will be re-rendered */ void -EditorSummary::set_overlays_dirty (int x, int y, int w, int h) +EditorSummary::set_overlays_dirty_rect (int x, int y, int w, int h) { - ENSURE_GUI_THREAD (*this, &EditorSummary::set_overlays_dirty); + ENSURE_GUI_THREAD (*this, &EditorSummary::set_overlays_dirty_rect); queue_draw_area (x, y, w, h); } @@ -324,9 +364,9 @@ EditorSummary::set_overlays_dirty (int x, int y, int w, int h) void EditorSummary::on_size_request (Gtk::Requisition *req) { - /* Use a dummy, small width and the actual height that we want */ - req->width = 64; - req->height = 32; + /* The left/right buttons will determine our height */ + req->width = -1; + req->height = -1; } @@ -334,8 +374,7 @@ void EditorSummary::centre_on_click (GdkEventButton* ev) { pair xr; - pair yr; - get_editor (&xr, &yr); + get_editor (&xr); double const w = xr.second - xr.first; double ex = ev->x - w / 2; @@ -345,15 +384,7 @@ EditorSummary::centre_on_click (GdkEventButton* ev) ex = get_width() - w; } - double const h = yr.second - yr.first; - double ey = ev->y - h / 2; - if (ey < 0) { - ey = 0; - } else if ((ey + h) > get_height()) { - ey = get_height() - h; - } - - set_editor (ex, ey); + set_editor (ex); } bool @@ -383,7 +414,7 @@ EditorSummary::on_key_press_event (GdkEventKey* key) if (key->keyval == set_playhead_accel.accel_key && (int) key->state == set_playhead_accel.accel_mods) { if (_session) { get_pointer (x, y); - _session->request_locate (_start + (framepos_t) x / _x_scale, _session->transport_rolling()); + _session->request_locate (_start + (samplepos_t) x / _x_scale, _session->transport_rolling()); return true; } } @@ -405,6 +436,8 @@ EditorSummary::on_key_release_event (GdkEventKey* key) return false; } +#include "gtkmm2ext/utils.h" + /** Handle a button press. * @param ev GTK event. */ @@ -413,60 +446,71 @@ EditorSummary::on_button_press_event (GdkEventButton* ev) { _old_follow_playhead = _editor->follow_playhead (); - if (ev->button == 1) { + if (ev->button == 3) { // right-click: show the reset menu action + using namespace Gtk::Menu_Helpers; + Gtk::Menu* m = manage (new Gtk::Menu); + MenuList& items = m->items (); + items.push_back(MenuElem(_("Reset Summary to Extents"), + sigc::mem_fun(*this, &EditorSummary::reset_to_extents))); + m->popup (ev->button, ev->time); + return true; + } - pair xr; - pair yr; - get_editor (&xr, &yr); + if (ev->button != 1) { + return true; + } - _start_editor_x = xr; - _start_editor_y = yr; - _start_mouse_x = ev->x; - _start_mouse_y = ev->y; - _start_position = get_position (ev->x, ev->y); + pair xr; + get_editor (&xr); - if (_start_position != INSIDE && _start_position != BELOW_OR_ABOVE && - _start_position != TO_LEFT_OR_RIGHT && _start_position != OTHERWISE_OUTSIDE - ) { + _start_editor_x = xr; + _start_mouse_x = ev->x; + _start_mouse_y = ev->y; + _start_position = get_position (ev->x, ev->y); - /* start a zoom drag */ + if (_start_position != INSIDE && _start_position != TO_LEFT_OR_RIGHT) { - _zoom_position = get_position (ev->x, ev->y); - _zoom_dragging = true; - _editor->_dragging_playhead = true; - _editor->set_follow_playhead (false); + /* start a zoom_trim drag */ - if (suspending_editor_updates ()) { - get_editor (&_pending_editor_x, &_pending_editor_y); - _pending_editor_changed = false; - } + _zoom_trim_position = get_position (ev->x, ev->y); + _zoom_trim_dragging = true; + _editor->_dragging_playhead = true; + _editor->set_follow_playhead (false); - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { + if (suspending_editor_updates ()) { + get_editor (&_pending_editor_x, &_pending_editor_y); + _pending_editor_changed = false; + } - /* secondary-modifier-click: locate playhead */ - if (_session) { - _session->request_locate (ev->x / _x_scale + _start); - } + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { + /* secondary-modifier-click: locate playhead */ + if (_session) { + _session->request_locate (ev->x / _x_scale + _start); + } - centre_on_click (ev); + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { - } else { + centre_on_click (ev); - /* start a move drag */ + } else { - /* get the editor's state in case we are suspending updates */ - get_editor (&_pending_editor_x, &_pending_editor_y); - _pending_editor_changed = false; + /* start a move+zoom drag */ + get_editor (&_pending_editor_x, &_pending_editor_y); + _pending_editor_changed = false; + _editor->_dragging_playhead = true; + _editor->set_follow_playhead (false); - _move_dragging = true; - _moved = false; - _editor->_dragging_playhead = true; - _editor->set_follow_playhead (false); + _move_dragging = true; + + _last_mx = ev->x; + _last_my = ev->y; + _last_dx = 0; + _last_dy = 0; + _last_y_delta = 0; + + get_window()->set_cursor (*_editor->_cursors->expand_left_right); - ArdourCanvas::checkpoint ("sum", "------------------ summary move drag starts.\n"); - } } return true; @@ -478,7 +522,7 @@ EditorSummary::on_button_press_event (GdkEventButton* ev) bool EditorSummary::suspending_editor_updates () const { - return (!UIConfiguration::instance().get_update_editor_during_summary_drag () && (_zoom_dragging || _move_dragging)); + return (!UIConfiguration::instance().get_update_editor_during_summary_drag () && (_zoom_trim_dragging || _move_dragging)); } /** Fill in x and y with the editor's current viewable area in summary coordinates */ @@ -486,24 +530,25 @@ void EditorSummary::get_editor (pair* x, pair* y) const { assert (x); - assert (y); - if (suspending_editor_updates ()) { /* We are dragging, and configured not to update the editor window during drags, - so just return where the editor will be when the drag finishes. + * so just return where the editor will be when the drag finishes. */ *x = _pending_editor_x; - *y = _pending_editor_y; - - } else { + if (y) { + *y = _pending_editor_y; + } + return; + } - /* Otherwise query the editor for its actual position */ + /* Otherwise query the editor for its actual position */ - x->first = (_editor->leftmost_sample () - _start) * _x_scale; - x->second = x->first + _editor->current_page_samples() * _x_scale; + x->first = (_editor->leftmost_sample () - _start) * _x_scale; + x->second = x->first + _editor->current_page_samples() * _x_scale; + if (y) { y->first = editor_y_to_summary (_editor->vertical_adjustment.get_value ()); y->second = editor_y_to_summary (_editor->vertical_adjustment.get_value () + _editor->visible_canvas_height() - _editor->get_trackview_group()->canvas_origin().y); } @@ -520,44 +565,33 @@ EditorSummary::get_position (double x, double y) const x_edge_size = min (x_edge_size, 8); x_edge_size = max (x_edge_size, 1); - int y_edge_size = (_view_rectangle_y.second - _view_rectangle_y.first) / 4; - y_edge_size = min (y_edge_size, 8); - y_edge_size = max (y_edge_size, 1); - bool const near_left = (std::abs (x - _view_rectangle_x.first) < x_edge_size); bool const near_right = (std::abs (x - _view_rectangle_x.second) < x_edge_size); - bool const near_top = (std::abs (y - _view_rectangle_y.first) < y_edge_size); - bool const near_bottom = (std::abs (y - _view_rectangle_y.second) < y_edge_size); bool const within_x = _view_rectangle_x.first < x && x < _view_rectangle_x.second; - bool const within_y = _view_rectangle_y.first < y && y < _view_rectangle_y.second; - - if (near_left && near_top) { - return LEFT_TOP; - } else if (near_left && near_bottom) { - return LEFT_BOTTOM; - } else if (near_right && near_top) { - return RIGHT_TOP; - } else if (near_right && near_bottom) { - return RIGHT_BOTTOM; - } else if (near_left && within_y) { + + if (near_left) { return LEFT; - } else if (near_right && within_y) { + } else if (near_right) { return RIGHT; - } else if (near_top && within_x) { - return TOP; - } else if (near_bottom && within_x) { - return BOTTOM; - } else if (within_x && within_y) { - return INSIDE; } else if (within_x) { - return BELOW_OR_ABOVE; - } else if (within_y) { - return TO_LEFT_OR_RIGHT; + return INSIDE; } else { - return OTHERWISE_OUTSIDE; + return TO_LEFT_OR_RIGHT; } } +void +EditorSummary::reset_to_extents() +{ + /* reset as if the user never went anywhere outside the extents */ + _leftmost = max_samplepos; + _rightmost = 0; + + _editor->temporal_zoom_extents (); + set_background_dirty (); +} + + void EditorSummary::set_cursor (Position p) { @@ -565,104 +599,128 @@ EditorSummary::set_cursor (Position p) case LEFT: get_window()->set_cursor (*_editor->_cursors->resize_left); break; - case LEFT_TOP: - get_window()->set_cursor (*_editor->_cursors->resize_top_left); - break; - case TOP: - get_window()->set_cursor (*_editor->_cursors->resize_top); - break; - case RIGHT_TOP: - get_window()->set_cursor (*_editor->_cursors->resize_top_right); - break; case RIGHT: get_window()->set_cursor (*_editor->_cursors->resize_right); break; - case RIGHT_BOTTOM: - get_window()->set_cursor (*_editor->_cursors->resize_bottom_right); - break; - case BOTTOM: - get_window()->set_cursor (*_editor->_cursors->resize_bottom); - break; - case LEFT_BOTTOM: - get_window()->set_cursor (*_editor->_cursors->resize_bottom_left); - break; case INSIDE: get_window()->set_cursor (*_editor->_cursors->move); break; case TO_LEFT_OR_RIGHT: - get_window()->set_cursor (*_editor->_cursors->expand_left_right); - break; - case BELOW_OR_ABOVE: - get_window()->set_cursor (*_editor->_cursors->expand_up_down); + get_window()->set_cursor (*_editor->_cursors->move); break; default: + assert (0); get_window()->set_cursor (); break; } } +void +EditorSummary::summary_zoom_step (int steps /* positive steps to zoom "out" , negative steps to zoom "in" */ ) +{ + pair xn; + + get_editor (&xn); + + xn.first -= steps; + xn.second += steps; + + /* for now, disallow really close zooming-in from the scroomer. (Currently it + * causes the start-offset to 'walk' because of integer limitations. + * To fix this, probably need to maintain float throught the get/set_editor() path.) + */ + if (steps<0) { + if ((xn.second - xn.first) < 2) + return; + } + + set_overlays_dirty (); + set_editor_x (xn); +} + + bool EditorSummary::on_motion_notify_event (GdkEventMotion* ev) { - pair xr = _start_editor_x; - pair yr = _start_editor_y; - double x = _start_editor_x.first; - double y = _start_editor_y.first; - if (_move_dragging) { - _moved = true; + /* To avoid accidental zooming, the mouse must move exactly vertical, not diagonal, to trigger a zoom step + * we use screen coordinates for this, not canvas-based grab_x */ + double mx = ev->x; + double dx = mx - _last_mx; + double my = ev->y; + double dy = my - _last_my; - /* don't alter x if we clicked outside and above or below the viewbox */ - if (_start_position == INSIDE || _start_position == TO_LEFT_OR_RIGHT || _start_position == OTHERWISE_OUTSIDE) { - x += ev->x - _start_mouse_x; - } + /* do zooming in windowed "steps" so it feels more reversible ? */ + const int stepsize = 2; + int y_delta = _start_mouse_y - my; + y_delta = y_delta / stepsize; - /* don't alter y if we clicked outside and to the left or right of the viewbox */ - if (_start_position == INSIDE || _start_position == BELOW_OR_ABOVE) { - y += ev->y - _start_mouse_y; - } + /* do the zoom? */ + const float zscale = 3; + if ((dx == 0) && (_last_dx == 0) && (y_delta != _last_y_delta)) { + + summary_zoom_step (dy * zscale); + + /* after the zoom we must re-calculate x-pos grabs */ + pair xr; + get_editor (&xr); + _start_editor_x = xr; + _start_mouse_x = ev->x; - if (x < 0) { - x = 0; + _last_y_delta = y_delta; } - if (y < 0) { - y = 0; + /* always track horizontal movement, if any */ + if (dx != 0) { + + double x = _start_editor_x.first; + x += ev->x - _start_mouse_x; + + if (x < 0) { + x = 0; + } + + /* zoom-behavior-tweaks: protect the right edge from expanding beyond the end */ + pair xr; + get_editor (&xr); + double w = xr.second - xr.first; + if (x + w < get_width()) { + set_editor (x); + } } - set_editor (x, y); - // set_cursor (_start_position); + _last_my = my; + _last_mx = mx; + _last_dx = dx; + _last_dy = dy; + + } else if (_zoom_trim_dragging) { - } else if (_zoom_dragging) { + pair xr = _start_editor_x; double const dx = ev->x - _start_mouse_x; - double const dy = ev->y - _start_mouse_y; - if (_zoom_position == LEFT || _zoom_position == LEFT_TOP || _zoom_position == LEFT_BOTTOM) { + if (_zoom_trim_position == LEFT) { xr.first += dx; - } else if (_zoom_position == RIGHT || _zoom_position == RIGHT_TOP || _zoom_position == RIGHT_BOTTOM) { - xr.second += dx; - } else { - xr.first = -1; /* do not change */ - } + } else if (_zoom_trim_position == RIGHT) { + + /* zoom-behavior-tweaks: protect the right edge from expanding beyond the edge */ + if ((xr.second + dx) < get_width()) { + xr.second += dx; + } - if (_zoom_position == TOP || _zoom_position == LEFT_TOP || _zoom_position == RIGHT_TOP) { - yr.first += dy; - } else if (_zoom_position == BOTTOM || _zoom_position == LEFT_BOTTOM || _zoom_position == RIGHT_BOTTOM) { - yr.second += dy; } else { - yr.first = -1; /* do not change y */ + assert (0); + xr.first = -1; /* do not change */ } set_overlays_dirty (); - set_cursor (_zoom_position); - set_editor (xr, yr); + set_cursor (_zoom_trim_position); + set_editor (xr); } else { - set_cursor (get_position (ev->x, ev->y)); - } return true; @@ -674,12 +732,12 @@ EditorSummary::on_button_release_event (GdkEventButton*) bool const was_suspended = suspending_editor_updates (); _move_dragging = false; - _zoom_dragging = false; + _zoom_trim_dragging = false; _editor->_dragging_playhead = false; _editor->set_follow_playhead (_old_follow_playhead, false); if (was_suspended && _pending_editor_changed) { - set_editor (_pending_editor_x, _pending_editor_y); + set_editor (_pending_editor_x); } return true; @@ -689,46 +747,29 @@ bool EditorSummary::on_scroll_event (GdkEventScroll* ev) { /* mouse wheel */ - pair xr; - pair yr; - get_editor (&xr, &yr); + get_editor (&xr); double x = xr.first; - double y = yr.first; switch (ev->direction) { - case GDK_SCROLL_UP: - if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) { - _editor->scroll_left_half_page (); - return true; - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) { - _editor->temporal_zoom_step (false); - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) { - yr.first += 4; - yr.second -= 4; - set_editor (xr, yr); - return true; - } else { - y -= 8; - } - break; - case GDK_SCROLL_DOWN: - if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) { - _editor->scroll_right_half_page (); - return true; - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) { - _editor->temporal_zoom_step (true); - } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomVerticalModifier)) { - yr.first -= 4; - yr.second += 4; - set_editor (xr, yr); - return true; - } else { - y += 8; - } - break; + case GDK_SCROLL_UP: { + + summary_zoom_step (-4); + + return true; + } break; + + case GDK_SCROLL_DOWN: { + + summary_zoom_step (4); + + return true; + } break; + case GDK_SCROLL_LEFT: - if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) { + _editor->temporal_zoom_step (false); + } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) { x -= 64; } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) { x -= 1; @@ -738,7 +779,9 @@ EditorSummary::on_scroll_event (GdkEventScroll* ev) } break; case GDK_SCROLL_RIGHT: - if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollZoomHorizontalModifier)) { + _editor->temporal_zoom_step (true); + } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) { x += 64; } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) { x += 1; @@ -751,7 +794,7 @@ EditorSummary::on_scroll_event (GdkEventScroll* ev) break; } - set_editor (x, y); + set_editor (x); return true; } @@ -761,7 +804,7 @@ EditorSummary::on_scroll_event (GdkEventScroll* ev) * Zoom is not changed in either direction. */ void -EditorSummary::set_editor (double const x, double const y) +EditorSummary::set_editor (double const x) { if (_editor->pending_visual_change.idle_handler_id >= 0 && _editor->pending_visual_change.being_handled == true) { @@ -780,7 +823,6 @@ EditorSummary::set_editor (double const x, double const y) } set_editor_x (x); - set_editor_y (y); } /** Set the editor to display a given x range and a y range with the top at a given position. @@ -788,23 +830,7 @@ EditorSummary::set_editor (double const x, double const y) * x and y parameters are specified in summary coordinates. */ void -EditorSummary::set_editor (pair const x, double const y) -{ - if (_editor->pending_visual_change.idle_handler_id >= 0) { - /* see comment in other set_editor () */ - return; - } - - set_editor_x (x); - set_editor_y (y); -} - -/** Set the editor to display given x and y ranges. x zoom and track heights are - * adjusted if necessary. - * x and y parameters are specified in summary coordinates. - */ -void -EditorSummary::set_editor (pair const x, pair const y) +EditorSummary::set_editor (pair const x) { if (_editor->pending_visual_change.idle_handler_id >= 0) { /* see comment in other set_editor () */ @@ -814,9 +840,6 @@ EditorSummary::set_editor (pair const x, pair con if (x.first >= 0) { set_editor_x (x); } - if (y.first >= 0) { - set_editor_y (y); - } } /** Set the left of the x range visible in the editor. @@ -874,157 +897,16 @@ EditorSummary::set_editor_x (pair x) } } -/** Set the top of the y range visible in the editor. - * Caller should have checked that Editor::pending_visual_change.idle_handler_id is < 0 - * @param y new editor top in summary coodinates. - */ -void -EditorSummary::set_editor_y (double const y) -{ - double y1 = summary_y_to_editor (y); - double const eh = _editor->visible_canvas_height() - _editor->get_trackview_group()->canvas_origin().y; - double y2 = y1 + eh; - - double const full_editor_height = _editor->_full_canvas_height; - - if (y2 > full_editor_height) { - y1 -= y2 - full_editor_height; - } - - if (y1 < 0) { - y1 = 0; - } - - if (suspending_editor_updates ()) { - double const h = _pending_editor_y.second - _pending_editor_y.first; - _pending_editor_y.first = y; - _pending_editor_y.second = y + h; - _pending_editor_changed = true; - set_dirty (); - } else { - _editor->reset_y_origin (y1); - } -} - -/** Set the y range visible in the editor. This is achieved by scaling track heights, - * if necessary. - * Caller should have checked that Editor::pending_visual_change.idle_handler_id is < 0 - * @param y new editor range in summary coodinates. - */ -void -EditorSummary::set_editor_y (pair const y) -{ - if (suspending_editor_updates ()) { - _pending_editor_y = y; - _pending_editor_changed = true; - set_dirty (); - return; - } - - /* Compute current height of tracks between y.first and y.second. We add up - the total height into `total_height' and the height of complete tracks into - `scale height'. - */ - - /* Copy of target range for use below */ - pair yc = y; - /* Total height of all tracks */ - double total_height = 0; - /* Height of any parts of tracks that aren't fully in the desired range */ - double partial_height = 0; - /* Height of any tracks that are fully in the desired range */ - double scale_height = 0; - - _editor->_routes->suspend_redisplay (); - - for (TrackViewList::const_iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) { - - if ((*i)->hidden()) { - continue; - } - - double const h = (*i)->effective_height (); - total_height += h; - - if (yc.first > 0 && yc.first < _track_height) { - partial_height += (_track_height - yc.first) * h / _track_height; - } else if (yc.first <= 0 && yc.second >= _track_height) { - scale_height += h; - } else if (yc.second > 0 && yc.second < _track_height) { - partial_height += yc.second * h / _track_height; - break; - } - - yc.first -= _track_height; - yc.second -= _track_height; - } - - /* Height that we will use for scaling; use the whole editor height unless there are not - enough tracks to fill it. - */ - double const ch = min (total_height, (_editor->visible_canvas_height() - _editor->get_trackview_group()->canvas_origin().y)); - - /* hence required scale factor of the complete tracks to fit the required y range; - the amount of space they should take up divided by the amount they currently take up. - */ - double const scale = (ch - partial_height) / scale_height; - - yc = y; - - /* Scale complete tracks within the range to make it fit */ - - for (TrackViewList::const_iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) { - - if ((*i)->hidden()) { - continue; - } - - if (yc.first <= 0 && yc.second >= _track_height) { - (*i)->set_height (max (TimeAxisView::preset_height (HeightSmall), (uint32_t) ((*i)->effective_height() * scale)), TimeAxisView::TotalHeight); - } - - yc.first -= _track_height; - yc.second -= _track_height; - } - - _editor->_routes->resume_redisplay (); - - set_editor_y (y.first); -} - void -EditorSummary::playhead_position_changed (framepos_t p) +EditorSummary::playhead_position_changed (samplepos_t p) { int const o = int (_last_playhead); - int const n = int (playhead_frame_to_position (p)); + int const n = int (playhead_sample_to_position (p)); if (_session && o != n) { int a = max(2, min (o, n)); int b = max (o, n); - set_overlays_dirty (a - 2, 0, b + 2, get_height ()); - } -} - -double -EditorSummary::summary_y_to_editor (double y) const -{ - double ey = 0; - for (TrackViewList::const_iterator i = _editor->track_views.begin (); i != _editor->track_views.end(); ++i) { - - if ((*i)->hidden()) { - continue; - } - - double const h = (*i)->effective_height (); - if (y < _track_height) { - /* in this track */ - return ey + y * h / _track_height; - } - - ey += h; - y -= _track_height; + set_overlays_dirty_rect (a - 2, 0, b + 2, get_height ()); } - - return ey; } double @@ -1074,13 +956,13 @@ EditorSummary::route_gui_changed (PBD::PropertyChange const& what_changed) } double -EditorSummary::playhead_frame_to_position (framepos_t t) const +EditorSummary::playhead_sample_to_position (samplepos_t t) const { return (t - _start) * _x_scale; } -framepos_t -EditorSummary::position_to_playhead_frame_to_position (double pos) const +samplepos_t +EditorSummary::position_to_playhead_sample_to_position (double pos) const { return _start + (pos * _x_scale); }