X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_summary.cc;h=dfbeccabfca0e09b85290890d0c75cbe7e47a664;hb=b998b8f761aaf1b8e61633f6054a6e9aa5d6c204;hp=dc25824a02ad5d3badb21bcc57ff51aa6efb4d71;hpb=ba649118f2b2142a592c6b8592c479f328c4babf;p=ardour.git diff --git a/gtk2_ardour/editor_summary.cc b/gtk2_ardour/editor_summary.cc index dc25824a02..dfbeccabfc 100644 --- a/gtk2_ardour/editor_summary.cc +++ b/gtk2_ardour/editor_summary.cc @@ -27,6 +27,9 @@ #include "rgb_macros.h" #include "keyboard.h" #include "editor_routes.h" +#include "editor_cursors.h" +#include "mouse_cursors.h" +#include "route_time_axis.h" using namespace std; using namespace ARDOUR; @@ -47,12 +50,13 @@ EditorSummary::EditorSummary (Editor* e) _moved (false), _view_rectangle_x (0, 0), _view_rectangle_y (0, 0), - _zoom_dragging (false) + _zoom_dragging (false), + _old_follow_playhead (false) { Region::RegionPropertyChanged.connect (region_property_connection, invalidator (*this), boost::bind (&CairoWidget::set_dirty, this), gui_context()); _editor->playhead_cursor->PositionChanged.connect (position_connection, invalidator (*this), ui_bind (&EditorSummary::playhead_position_changed, this, _1), gui_context()); - add_events (Gdk::POINTER_MOTION_MASK); + add_events (Gdk::POINTER_MOTION_MASK); } /** Connect to a session. @@ -144,8 +148,8 @@ EditorSummary::render (cairo_t* cr) } /* compute start and end points for the summary */ - - nframes_t const session_length = _session->current_end_frame() - _session->current_start_frame (); + + 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; _start = theoretical_start > 0 ? theoretical_start : 0; _end = _session->current_end_frame() + session_length * _overhang_fraction; @@ -157,7 +161,7 @@ EditorSummary::render (cairo_t* cr) ++N; } } - + if (N == 0) { _track_height = 16; } else { @@ -185,7 +189,7 @@ EditorSummary::render (cairo_t* cr) cairo_move_to (cr, 0, y + _track_height / 2); cairo_line_to (cr, _width, y + _track_height / 2); cairo_stroke (cr); - + StreamView* s = (*i)->view (); if (s) { @@ -197,7 +201,7 @@ EditorSummary::render (cairo_t* cr) y + _track_height / 2 )); } - + y += _track_height; } @@ -271,25 +275,22 @@ EditorSummary::centre_on_click (GdkEventButton* ev) get_editor (&xr, &yr); double const w = xr.second - xr.first; - - xr.first = ev->x - w / 2; - xr.second = ev->x + w / 2; - - if (xr.first < 0) { - xr.first = 0; - xr.second = w; - } else if (xr.second > _width) { - xr.second = _width; - xr.first = _width - w; + double ex = ev->x - w / 2; + if (ex < 0) { + ex = 0; + } else if ((ex + w) > _width) { + ex = _width - w; } - double ey = summary_y_to_editor (ev->y); - ey -= (_editor->canvas_height() - _editor->get_canvas_timebars_vsize ()) / 2; + double const h = yr.second - yr.first; + double ey = ev->y - h / 2; if (ey < 0) { ey = 0; + } else if ((ey + h) > _height) { + ey = _height - h; } - - set_editor (xr, editor_y_to_summary (ey)); + + set_editor (ex, ey); } /** Handle a button press. @@ -319,7 +320,14 @@ EditorSummary::on_button_press_event (GdkEventButton* ev) _zoom_position = get_position (ev->x, ev->y); _zoom_dragging = true; _editor->_dragging_playhead = true; + _old_follow_playhead = _editor->follow_playhead (); + _editor->set_follow_playhead (false); + if (suspending_editor_updates ()) { + get_editor (&_pending_editor_x, &_pending_editor_y); + _pending_editor_changed = false; + } + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { /* secondary-modifier-click: locate playhead */ @@ -335,27 +343,56 @@ EditorSummary::on_button_press_event (GdkEventButton* ev) /* start a move drag */ + /* get the editor's state in case we are suspending updates */ + get_editor (&_pending_editor_x, &_pending_editor_y); + _pending_editor_changed = false; + _move_dragging = true; _moved = false; _editor->_dragging_playhead = true; + _old_follow_playhead = _editor->follow_playhead (); + _editor->set_follow_playhead (false); } } return true; } +/** @return true if we are currently suspending updates to the editor's viewport, + * which we do if configured to do so, and if in a drag of some kind. + */ +bool +EditorSummary::suspending_editor_updates () const +{ + return (!Config->get_update_editor_during_summary_drag () && (_zoom_dragging || _move_dragging)); +} + /** Fill in x and y with the editor's current viewable area in summary coordinates */ void EditorSummary::get_editor (pair* x, pair* y) const { assert (x); assert (y); - - x->first = (_editor->leftmost_position () - _start) * _x_scale; - x->second = x->first + _editor->current_page_frames() * _x_scale; - y->first = editor_y_to_summary (_editor->vertical_adjustment.get_value ()); - y->second = editor_y_to_summary (_editor->vertical_adjustment.get_value () + _editor->canvas_height() - _editor->get_canvas_timebars_vsize()); + 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. + */ + + *x = _pending_editor_x; + *y = _pending_editor_y; + + } else { + + /* Otherwise query the editor for its actual position */ + + x->first = (_editor->leftmost_position () - _start) * _x_scale; + x->second = x->first + _editor->current_page_frames() * _x_scale; + + y->first = editor_y_to_summary (_editor->vertical_adjustment.get_value ()); + y->second = editor_y_to_summary (_editor->vertical_adjustment.get_value () + _editor->canvas_height() - _editor->get_canvas_timebars_vsize()); + } } /** Get an expression of the position of a point with respect to the view rectangle */ @@ -372,7 +409,7 @@ EditorSummary::get_position (double x, double y) const 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); @@ -412,37 +449,37 @@ EditorSummary::set_cursor (Position p) { switch (p) { case LEFT: - get_window()->set_cursor (*_editor->resize_left_cursor); + get_window()->set_cursor (*_editor->_cursors->resize_left); break; case LEFT_TOP: - get_window()->set_cursor (*_editor->resize_top_left_cursor); + get_window()->set_cursor (*_editor->_cursors->resize_top_left); break; case TOP: - get_window()->set_cursor (*_editor->resize_top_cursor); + get_window()->set_cursor (*_editor->_cursors->resize_top); break; case RIGHT_TOP: - get_window()->set_cursor (*_editor->resize_top_right_cursor); + get_window()->set_cursor (*_editor->_cursors->resize_top_right); break; case RIGHT: - get_window()->set_cursor (*_editor->resize_right_cursor); + get_window()->set_cursor (*_editor->_cursors->resize_right); break; case RIGHT_BOTTOM: - get_window()->set_cursor (*_editor->resize_bottom_right_cursor); + get_window()->set_cursor (*_editor->_cursors->resize_bottom_right); break; case BOTTOM: - get_window()->set_cursor (*_editor->resize_bottom_cursor); + get_window()->set_cursor (*_editor->_cursors->resize_bottom); break; case LEFT_BOTTOM: - get_window()->set_cursor (*_editor->resize_bottom_left_cursor); + get_window()->set_cursor (*_editor->_cursors->resize_bottom_left); break; case INSIDE: - get_window()->set_cursor (*_editor->move_cursor); + get_window()->set_cursor (*_editor->_cursors->move); break; case TO_LEFT_OR_RIGHT: - get_window()->set_cursor (*_editor->expand_left_right_cursor); + get_window()->set_cursor (*_editor->_cursors->expand_left_right); break; case BELOW_OR_ABOVE: - get_window()->set_cursor (*_editor->expand_up_down_cursor); + get_window()->set_cursor (*_editor->_cursors->expand_up_down); break; default: get_window()->set_cursor (); @@ -455,6 +492,7 @@ 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) { @@ -463,8 +501,7 @@ EditorSummary::on_motion_notify_event (GdkEventMotion* ev) /* 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) { - xr.first += ev->x - _start_mouse_x; - xr.second += ev->x - _start_mouse_x; + x += ev->x - _start_mouse_x; } /* don't alter y if we clicked outside and to the left or right of the viewbox */ @@ -472,16 +509,15 @@ EditorSummary::on_motion_notify_event (GdkEventMotion* ev) y += ev->y - _start_mouse_y; } - if (xr.first < 0) { - xr.second -= xr.first; - xr.first = 0; + if (x < 0) { + x = 0; } if (y < 0) { y = 0; } - set_editor (xr, y); + set_editor (x, y); set_cursor (_start_position); } else if (_zoom_dragging) { @@ -517,9 +553,17 @@ EditorSummary::on_motion_notify_event (GdkEventMotion* ev) bool EditorSummary::on_button_release_event (GdkEventButton*) { + bool const was_suspended = suspending_editor_updates (); + _move_dragging = false; _zoom_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); + } + return true; } @@ -531,6 +575,7 @@ EditorSummary::on_scroll_event (GdkEventScroll* ev) pair xr; pair yr; get_editor (&xr, &yr); + double x = xr.first; double y = yr.first; double amount = 8; @@ -546,11 +591,9 @@ EditorSummary::on_scroll_event (GdkEventScroll* ev) /* primary-wheel == left-right scrolling */ if (ev->direction == GDK_SCROLL_UP) { - xr.first += amount; - xr.second += amount; + x += amount; } else if (ev->direction == GDK_SCROLL_DOWN) { - xr.first -= amount; - xr.second -= amount; + x -= amount; } } else { @@ -560,24 +603,23 @@ EditorSummary::on_scroll_event (GdkEventScroll* ev) } else if (ev->direction == GDK_SCROLL_UP) { y -= amount; } else if (ev->direction == GDK_SCROLL_LEFT) { - xr.first -= amount; - xr.second -= amount; + x -= amount; } else if (ev->direction == GDK_SCROLL_RIGHT) { - xr.first += amount; - xr.second += amount; + x += amount; } } - set_editor (xr, y); + set_editor (x, y); return true; } -/** Set the editor to display a given x range and a y range with the top at a given position. - * The editor's x zoom is adjusted if necessary, but the y zoom is not changed. +/** Set the editor to display a x range with the left at a given position + * and a y range with the top at a given position. * x and y parameters are specified in summary coordinates. + * Zoom is not changed in either direction. */ void -EditorSummary::set_editor (pair const & x, double const y) +EditorSummary::set_editor (double const x, double const y) { if (_editor->pending_visual_change.idle_handler_id >= 0) { @@ -594,7 +636,23 @@ EditorSummary::set_editor (pair const & x, double const y) return; } - + + 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. + * The editor's x zoom is adjusted if necessary, but the y zoom is not changed. + * 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); } @@ -604,34 +662,70 @@ EditorSummary::set_editor (pair const & x, double const y) * 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, pair 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 left of the x range visible in the editor. + * Caller should have checked that Editor::pending_visual_change.idle_handler_id is < 0 + * @param x new x left position in summary coordinates. + */ +void +EditorSummary::set_editor_x (double x) +{ + if (x < 0) { + x = 0; + } + + if (suspending_editor_updates ()) { + double const w = _pending_editor_x.second - _pending_editor_x.first; + _pending_editor_x.first = x; + _pending_editor_x.second = x + w; + _pending_editor_changed = true; + set_dirty (); + } else { + _editor->reset_x_origin (x / _x_scale + _start); + } +} + /** Set the x range visible in the editor. * Caller should have checked that Editor::pending_visual_change.idle_handler_id is < 0 * @param x new x range in summary coordinates. */ void -EditorSummary::set_editor_x (pair const & x) +EditorSummary::set_editor_x (pair x) { - _editor->reset_x_origin (x.first / _x_scale + _start); + if (x.first < 0) { + x.first = 0; + } - double const nx = ( - ((x.second - x.first) / _x_scale) / - _editor->frame_to_unit (_editor->current_page_frames()) - ); - - if (nx != _editor->get_current_zoom ()) { - _editor->reset_zoom (nx); - } + if (x.second < 0) { + x.second = x.first + 1; + } + + if (suspending_editor_updates ()) { + _pending_editor_x = x; + _pending_editor_changed = true; + set_dirty (); + } else { + _editor->reset_x_origin (x.first / _x_scale + _start); + + double const nx = ( + ((x.second - x.first) / _x_scale) / + _editor->frame_to_unit (_editor->current_page_frames()) + ); + + if (nx != _editor->get_current_zoom ()) { + _editor->reset_zoom (nx); + } + } } /** Set the top of the y range visible in the editor. @@ -644,18 +738,26 @@ EditorSummary::set_editor_y (double const y) double y1 = summary_y_to_editor (y); double const eh = _editor->canvas_height() - _editor->get_canvas_timebars_vsize (); double y2 = y1 + eh; - + double const full_editor_height = _editor->full_canvas_height - _editor->get_canvas_timebars_vsize(); if (y2 > full_editor_height) { y1 -= y2 - full_editor_height; } - + if (y1 < 0) { y1 = 0; } - _editor->reset_y_origin (y1); + 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, @@ -664,16 +766,29 @@ EditorSummary::set_editor_y (double const y) * @param y new editor range in summary coodinates. */ void -EditorSummary::set_editor_y (pair const & y) +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) { @@ -681,37 +796,44 @@ EditorSummary::set_editor_y (pair const & y) if ((*i)->hidden()) { continue; } - + double const h = (*i)->effective_height (); + total_height += h; - if (yc.first >= 0 && yc.first < _track_height) { - total_height += (_track_height - yc.first) * h / _track_height; - } else if (yc.first < 0 && yc.second > _track_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) { - total_height += yc.second * h / _track_height; + } 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; } - - /* hence required scale factor of the complete tracks to fit the required y range */ - double const scale = ((_editor->canvas_height() - _editor->get_canvas_timebars_vsize()) - (total_height - scale_height)) / scale_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->canvas_height() - _editor->get_canvas_timebars_vsize()); + + /* 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) { + if (yc.first <= 0 && yc.second >= _track_height) { (*i)->set_height (max (TimeAxisView::preset_height (HeightSmall), (uint32_t) ((*i)->effective_height() * scale))); } @@ -720,7 +842,7 @@ EditorSummary::set_editor_y (pair const & y) } _editor->_routes->resume_redisplay (); - + set_editor_y (y.first); } @@ -737,11 +859,11 @@ 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 */ @@ -760,7 +882,7 @@ EditorSummary::editor_y_to_summary (double y) const { double sy = 0; for (TrackViewList::const_iterator i = _editor->track_views.begin (); i != _editor->track_views.end(); ++i) { - + if ((*i)->hidden()) { continue; } @@ -777,3 +899,22 @@ EditorSummary::editor_y_to_summary (double y) const return sy; } + +void +EditorSummary::routes_added (list const & r) +{ + /* Connect to gui_changed() on the routes so that we know when their colour has changed */ + for (list::const_iterator i = r.begin(); i != r.end(); ++i) { + (*i)->route()->gui_changed.connect (*this, invalidator (*this), ui_bind (&EditorSummary::route_gui_changed, this, _1), gui_context ()); + } + + set_dirty (); +} + +void +EditorSummary::route_gui_changed (string c) +{ + if (c == "color") { + set_dirty (); + } +}