X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_summary.cc;h=0dc728d18e26e837e6b3e15ad87c63d63be5c85e;hb=3f56abe099cd6978fbf2e1778debd74e771c95cd;hp=e279da94d3f46c6b72960eefd61318ad99384b84;hpb=150d3fdfbfeabde96d528312aa22e839a5aa5f3e;p=ardour.git diff --git a/gtk2_ardour/editor_summary.cc b/gtk2_ardour/editor_summary.cc index e279da94d3..0dc728d18e 100644 --- a/gtk2_ardour/editor_summary.cc +++ b/gtk2_ardour/editor_summary.cc @@ -18,6 +18,7 @@ */ #include "ardour/session.h" + #include "time_axis_view.h" #include "streamview.h" #include "editor_summary.h" @@ -50,12 +51,15 @@ 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()); + Route::RemoteControlIDChange.connect (route_ctrl_id_connection, invalidator (*this), boost::bind (&CairoWidget::set_dirty, this), gui_context()); + _editor->playhead_cursor->PositionChanged.connect (position_connection, invalidator (*this), boost::bind (&EditorSummary::playhead_position_changed, this, _1), gui_context()); - add_events (Gdk::POINTER_MOTION_MASK); + add_events (Gdk::POINTER_MOTION_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK); + set_flags (get_flags() | Gtk::CAN_FOCUS); } /** Connect to a session. @@ -74,72 +78,21 @@ EditorSummary::set_session (Session* s) */ if (_session) { - _session->StartTimeChanged.connect (_session_connections, invalidator (*this), boost::bind (&EditorSummary::set_dirty, this), gui_context()); - _session->EndTimeChanged.connect (_session_connections, invalidator (*this), boost::bind (&EditorSummary::set_dirty, this), gui_context()); + _session->StartTimeChanged.connect (_session_connections, invalidator (*this), boost::bind (&CairoWidget::set_dirty, this), gui_context()); + _session->EndTimeChanged.connect (_session_connections, invalidator (*this), boost::bind (&CairoWidget::set_dirty, this), gui_context()); } } -/** Handle an expose event. - * @param event Event from GTK. - */ -bool -EditorSummary::on_expose_event (GdkEventExpose* event) -{ - CairoWidget::on_expose_event (event); - - if (_session == 0) { - return false; - } - - cairo_t* cr = gdk_cairo_create (get_window()->gobj()); - - /* 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. - */ - - if (_editor->pending_visual_change.idle_handler_id < 0) { - get_editor (&_view_rectangle_x, &_view_rectangle_y); - } - - cairo_move_to (cr, _view_rectangle_x.first, _view_rectangle_y.first); - cairo_line_to (cr, _view_rectangle_x.second, _view_rectangle_y.first); - cairo_line_to (cr, _view_rectangle_x.second, _view_rectangle_y.second); - cairo_line_to (cr, _view_rectangle_x.first, _view_rectangle_y.second); - cairo_line_to (cr, _view_rectangle_x.first, _view_rectangle_y.first); - cairo_set_source_rgba (cr, 1, 1, 1, 0.25); - cairo_fill_preserve (cr); - cairo_set_line_width (cr, 1); - cairo_set_source_rgba (cr, 1, 1, 1, 0.5); - cairo_stroke (cr); - - /* Playhead */ - - cairo_set_line_width (cr, 1); - /* XXX: colour should be set from configuration file */ - cairo_set_source_rgba (cr, 1, 0, 0, 1); - - double const p = (_editor->playhead_cursor->current_frame - _start) * _x_scale; - cairo_move_to (cr, p, 0); - cairo_line_to (cr, p, _height); - cairo_stroke (cr); - _last_playhead = p; - - cairo_destroy (cr); - - return true; -} - /** Render the required regions to a cairo context. * @param cr Context. */ void EditorSummary::render (cairo_t* cr) { - /* background */ + /* background (really just the dividing lines between tracks */ cairo_set_source_rgb (cr, 0, 0, 0); - cairo_rectangle (cr, 0, 0, _width, _height); + cairo_rectangle (cr, 0, 0, get_width(), get_height()); cairo_fill (cr); if (_session == 0) { @@ -147,7 +100,7 @@ EditorSummary::render (cairo_t* cr) } /* 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; _start = theoretical_start > 0 ? theoretical_start : 0; @@ -160,16 +113,16 @@ EditorSummary::render (cairo_t* cr) ++N; } } - + if (N == 0) { _track_height = 16; } else { - _track_height = (double) _height / N; + _track_height = (double) get_height() / N; } /* calculate x scale */ if (_end != _start) { - _x_scale = static_cast (_width) / (_end - _start); + _x_scale = static_cast (get_width()) / (_end - _start); } else { _x_scale = 1; } @@ -183,12 +136,14 @@ EditorSummary::render (cairo_t* cr) continue; } + /* 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 - 2); + cairo_set_line_width (cr, _track_height - 1); cairo_move_to (cr, 0, y + _track_height / 2); - cairo_line_to (cr, _width, y + _track_height / 2); + cairo_line_to (cr, get_width(), y + _track_height / 2); cairo_stroke (cr); - + StreamView* s = (*i)->view (); if (s) { @@ -200,7 +155,7 @@ EditorSummary::render (cairo_t* cr) y + _track_height / 2 )); } - + y += _track_height; } @@ -209,15 +164,48 @@ EditorSummary::render (cairo_t* cr) cairo_set_line_width (cr, 1); cairo_set_source_rgb (cr, 1, 1, 0); - double const p = (_session->current_start_frame() - _start) * _x_scale; + const double p = (_session->current_start_frame() - _start) * _x_scale; cairo_move_to (cr, p, 0); - cairo_line_to (cr, p, _height); + cairo_line_to (cr, p, get_height()); cairo_stroke (cr); double const q = (_session->current_end_frame() - _start) * _x_scale; cairo_move_to (cr, q, 0); - cairo_line_to (cr, q, _height); + cairo_line_to (cr, q, get_height()); cairo_stroke (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. + */ + + if (_editor->pending_visual_change.idle_handler_id < 0) { + get_editor (&_view_rectangle_x, &_view_rectangle_y); + } + + cairo_move_to (cr, _view_rectangle_x.first, _view_rectangle_y.first); + cairo_line_to (cr, _view_rectangle_x.second, _view_rectangle_y.first); + cairo_line_to (cr, _view_rectangle_x.second, _view_rectangle_y.second); + cairo_line_to (cr, _view_rectangle_x.first, _view_rectangle_y.second); + cairo_line_to (cr, _view_rectangle_x.first, _view_rectangle_y.first); + cairo_set_source_rgba (cr, 1, 1, 1, 0.25); + cairo_fill_preserve (cr); + cairo_set_line_width (cr, 1); + cairo_set_source_rgba (cr, 1, 1, 1, 0.5); + cairo_stroke (cr); + + /* Playhead */ + + cairo_set_line_width (cr, 1); + /* 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); + cairo_move_to (cr, ph, 0); + cairo_line_to (cr, ph, get_height()); + cairo_stroke (cr); + _last_playhead = ph; + } /** Render a region for the summary. @@ -250,10 +238,19 @@ EditorSummary::render_region (RegionView* r, cairo_t* cr, double y) const void EditorSummary::set_overlays_dirty () { - ENSURE_GUI_THREAD (*this, &EditorSummary::set_overlays_dirty) + ENSURE_GUI_THREAD (*this, &EditorSummary::set_overlays_dirty); queue_draw (); } +/** 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) +{ + ENSURE_GUI_THREAD (*this, &EditorSummary::set_overlays_dirty); + queue_draw_area (x, y, w, h); +} + + /** Handle a size request. * @param req GTK requisition */ @@ -274,25 +271,71 @@ 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) > get_width()) { + ex = get_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) > get_height()) { + ey = get_height() - h; } - - set_editor (xr, editor_y_to_summary (ey)); + + set_editor (ex, ey); +} + +bool +EditorSummary::on_enter_notify_event (GdkEventCrossing*) +{ + grab_focus (); + Keyboard::magic_widget_grab_focus (); + return false; +} + +bool +EditorSummary::on_leave_notify_event (GdkEventCrossing*) +{ + /* there are no inferior/child windows, so any leave event means that + we're gone. + */ + Keyboard::magic_widget_drop_focus (); + return false; +} + +bool +EditorSummary::on_key_press_event (GdkEventKey* key) +{ + gint x, y; + GtkAccelKey set_playhead_accel; + if (gtk_accel_map_lookup_entry ("/Editor/set-playhead", &set_playhead_accel)) { + 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()); + return true; + } + } + } + + return false; +} + +bool +EditorSummary::on_key_release_event (GdkEventKey* key) +{ + + GtkAccelKey set_playhead_accel; + if (gtk_accel_map_lookup_entry ("/Editor/set-playhead", &set_playhead_accel)) { + if (key->keyval == set_playhead_accel.accel_key && (int) key->state == set_playhead_accel.accel_mods) { + return true; + } + } + return false; } /** Handle a button press. @@ -301,6 +344,8 @@ EditorSummary::centre_on_click (GdkEventButton* ev) bool EditorSummary::on_button_press_event (GdkEventButton* ev) { + _old_follow_playhead = _editor->follow_playhead (); + if (ev->button == 1) { pair xr; @@ -322,7 +367,13 @@ EditorSummary::on_button_press_event (GdkEventButton* ev) _zoom_position = get_position (ev->x, ev->y); _zoom_dragging = true; _editor->_dragging_playhead = true; + _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 */ @@ -338,27 +389,55 @@ 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; + _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 */ @@ -375,7 +454,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); @@ -458,6 +537,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) { @@ -466,8 +546,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 */ @@ -475,17 +554,16 @@ 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_cursor (_start_position); + set_editor (x, y); + // set_cursor (_start_position); } else if (_zoom_dragging) { @@ -520,9 +598,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; } @@ -534,53 +620,71 @@ 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; - - if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) { - amount = 64; - } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) { - amount = 1; - } - - if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - - /* primary-wheel == left-right scrolling */ - - if (ev->direction == GDK_SCROLL_UP) { - xr.first += amount; - xr.second += amount; - } else if (ev->direction == GDK_SCROLL_DOWN) { - xr.first -= amount; - xr.second -= amount; - } - - } else { - - if (ev->direction == GDK_SCROLL_DOWN) { - y += amount; - } else if (ev->direction == GDK_SCROLL_UP) { - y -= amount; - } else if (ev->direction == GDK_SCROLL_LEFT) { - xr.first -= amount; - xr.second -= amount; - } else if (ev->direction == GDK_SCROLL_RIGHT) { - xr.first += amount; - xr.second += amount; - } + switch (ev->direction) { + case GDK_SCROLL_UP: + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ScrollHorizontalModifier)) { + x -= 64; + } 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)) { + x += 64; + } 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_LEFT: + if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) { + x -= 64; + } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) { + x -= 1; + } else { + x -= 8; + } + break; + case GDK_SCROLL_RIGHT: + if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) { + x += 64; + } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier)) { + x += 1; + } else { + x += 8; + } + break; + default: + break; } - 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,10 +698,26 @@ EditorSummary::set_editor (pair const & x, double const y) as it also means that we won't change these variables if an idle handler is merely pending but not executing. But c'est la vie. */ + + 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); } @@ -607,7 +727,7 @@ 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 () */ @@ -618,23 +738,59 @@ EditorSummary::set_editor (pair const & x, pair c 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. @@ -647,18 +803,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, @@ -667,8 +831,15 @@ 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'. @@ -682,7 +853,7 @@ EditorSummary::set_editor_y (pair const & y) 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) { @@ -690,7 +861,7 @@ EditorSummary::set_editor_y (pair const & y) if ((*i)->hidden()) { continue; } - + double const h = (*i)->effective_height (); total_height += h; @@ -711,7 +882,7 @@ EditorSummary::set_editor_y (pair const & y) 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. */ @@ -720,7 +891,7 @@ EditorSummary::set_editor_y (pair const & y) 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()) { @@ -736,15 +907,19 @@ EditorSummary::set_editor_y (pair const & y) } _editor->_routes->resume_redisplay (); - + set_editor_y (y.first); } void EditorSummary::playhead_position_changed (framepos_t p) { - if (_session && int (p * _x_scale) != int (_last_playhead)) { - set_overlays_dirty (); + int const o = int (_last_playhead); + int const n = int (playhead_frame_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 ()); } } @@ -753,11 +928,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 */ @@ -776,7 +951,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; } @@ -797,9 +972,13 @@ EditorSummary::editor_y_to_summary (double y) const 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 ()); + /* Connect to gui_changed() on the route so that we know when their colour has changed */ + (*i)->route()->gui_changed.connect (*this, invalidator (*this), boost::bind (&EditorSummary::route_gui_changed, this, _1), gui_context ()); + boost::shared_ptr tr = boost::dynamic_pointer_cast ((*i)->route ()); + if (tr) { + tr->PlaylistChanged.connect (*this, invalidator (*this), boost::bind (&CairoWidget::set_dirty, this), gui_context ()); + } } set_dirty (); @@ -812,3 +991,15 @@ EditorSummary::route_gui_changed (string c) set_dirty (); } } + +double +EditorSummary::playhead_frame_to_position (framepos_t t) const +{ + return (t - _start) * _x_scale; +} + +framepos_t +EditorSummary::position_to_playhead_frame_to_position (double pos) const +{ + return _start + (pos * _x_scale); +}