From 907fbdd19e99ede9f6e5d11c3726ac9e950c7960 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 2 Apr 2017 22:20:12 +0200 Subject: Minitimeline: show markers immediately left/right of viewpoint --- gtk2_ardour/mini_timeline.cc | 144 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 115 insertions(+), 29 deletions(-) (limited to 'gtk2_ardour/mini_timeline.cc') diff --git a/gtk2_ardour/mini_timeline.cc b/gtk2_ardour/mini_timeline.cc index 28fbe0f4a5..c349724ac0 100644 --- a/gtk2_ardour/mini_timeline.cc +++ b/gtk2_ardour/mini_timeline.cc @@ -348,7 +348,7 @@ MiniTimeline::draw_mark (cairo_t* cr, int x0, int x1, const std::string& label, _layout->get_pixel_size (lw, lh); int rw = std::min (x1, x0 + w2 + lw + 2); - if (_pointer_y >= 0 && _pointer_y <= y + h && _pointer_x >= x0 && _pointer_x <= rw) { + if (_pointer_y >= 0 && _pointer_y <= y + h && _pointer_x >= x0 - w2 && _pointer_x <= rw) { prelight = true; } @@ -377,7 +377,7 @@ MiniTimeline::draw_mark (cairo_t* cr, int x0, int x1, const std::string& label, // draw marker on top cairo_move_to (cr, x0 - .5, y + .5); - cairo_rel_line_to (cr, -w2 , 0 ); + cairo_rel_line_to (cr, -w2 , 0); cairo_rel_line_to (cr, 0, h0); cairo_rel_line_to (cr, w2, h1); cairo_rel_line_to (cr, w2, -h1); @@ -391,6 +391,55 @@ MiniTimeline::draw_mark (cairo_t* cr, int x0, int x1, const std::string& label, return rw; } +int +MiniTimeline::draw_edge (cairo_t* cr, int x0, int x1, bool left, const std::string&, bool& prelight) +{ + int h = _marker_height; + int w2 = (h - 1) / 4; + + const int y = PADDING; + const double yc = rint (h * .5); + const double dy = h * .4; + + double px, dx; + if (left) { + x1 = std::min (x1, x0 + 2 * w2); + px = x0; + dx = 2 * w2; + } else { + x0 = std::max (x0, x1 - 2 * w2); + px = x1; + dx = -2 * w2; + } + if (x1 - x0 < 2 * w2) { + return left ? x0 : x1; + } + + if (_pointer_y >= 0 && _pointer_y <= y + h && _pointer_x >= x0 && _pointer_x <= x1) { + prelight = true; + } + + // TODO cache in set_colors() + uint32_t color = UIConfiguration::instance().color ( + prelight ? "entered marker" : "location marker"); + + double r, g, b, a; + ArdourCanvas::color_to_rgba (color, r, g, b, a); + + // draw arrow + cairo_move_to (cr, px - .5, PADDING + yc - .5); + cairo_rel_line_to (cr, dx , dy); + cairo_rel_line_to (cr, 0, -2. * dy); + cairo_close_path (cr); + cairo_set_source_rgba (cr, r, g, b, 1.0); + cairo_set_line_width (cr, 1.0); + cairo_stroke_preserve (cr); + cairo_fill (cr); + + return left ? x1 : x0; +} + + struct LocationMarker { LocationMarker (const std::string& l, framepos_t w) : label (l), when (w) {} @@ -416,26 +465,28 @@ MiniTimeline::render (Cairo::RefPtr const& ctx, cairo_rectangle_ return; } - Gtkmm2ext::rounded_rectangle (cr, 0, 0, get_width(), get_height(), 4); + const int width = get_width (); + const int height = get_height (); + + Gtkmm2ext::rounded_rectangle (cr, 0, 0, width, height, 4); ArdourCanvas::set_source_rgba(cr, base); cairo_fill (cr); - Gtkmm2ext::rounded_rectangle (cr, PADDING, PADDING, get_width() - PADDING - PADDING, get_height() - PADDING - PADDING, 4); + Gtkmm2ext::rounded_rectangle (cr, PADDING, PADDING, width - PADDING - PADDING, height - PADDING - PADDING, 4); cairo_clip (cr); if (_session == 0) { return; } - /* time */ const framepos_t p = _last_update_frame; const framepos_t lower = (std::max ((framepos_t)0, (p - _time_span_samples)) / _time_granularity) * _time_granularity; - int dot_left = get_width() * .5 + (lower - p) * _px_per_sample; + int dot_left = width * .5 + (lower - p) * _px_per_sample; for (int i = 0; i < 2 + _n_labels; ++i) { framepos_t when = lower + i * _time_granularity; - double xpos = get_width() * .5 + (when - p) * _px_per_sample; + double xpos = width * .5 + (when - p) * _px_per_sample; // TODO round to nearest display TC in +/- 1px // prefer to display BBT |0 or .0 @@ -445,7 +496,7 @@ MiniTimeline::render (Cairo::RefPtr const& ctx, cairo_rectangle_ _layout->get_pixel_size (lw, lh); int x0 = xpos - lw / 2.0; - int y0 = get_height() - PADDING - _time_height; + int y0 = height - PADDING - _time_height; draw_dots (cr, dot_left, x0, y0 + _time_height * .5, text); @@ -454,7 +505,7 @@ MiniTimeline::render (Cairo::RefPtr const& ctx, cairo_rectangle_ pango_cairo_show_layout (cr, _layout->gobj()); dot_left = x0 + lw; } - draw_dots (cr, dot_left, get_width(), get_height() - PADDING - _time_height * .5, text); + draw_dots (cr, dot_left, width, height - PADDING - _time_height * .5, text); /* locations */ framepos_t lmin = std::max ((framepos_t)0, (p - _time_span_samples)); @@ -476,14 +527,8 @@ MiniTimeline::render (Cairo::RefPtr const& ctx, cairo_rectangle_ const Locations::LocationList& ll (_session->locations ()->list ()); for (Locations::LocationList::const_iterator l = ll.begin(); l != ll.end(); ++l) { if ((*l)->is_session_range ()) { - framepos_t when = (*l)->start (); - if (when >= lmin && when <= lmax) { - lm.push_back (LocationMarker(_("start"), when)); - } - when = (*l)->end (); - if (when >= lmin && when <= lmax) { - lm.push_back (LocationMarker(_("end"), when)); - } + lm.push_back (LocationMarker(_("start"), (*l)->start ())); + lm.push_back (LocationMarker(_("end"), (*l)->end ())); continue; } @@ -491,11 +536,7 @@ MiniTimeline::render (Cairo::RefPtr const& ctx, cairo_rectangle_ continue; } - framepos_t when = (*l)->start (); - if (when < lmin || when > lmax) { - continue; - } - lm.push_back (LocationMarker((*l)->name(), when)); + lm.push_back (LocationMarker((*l)->name(), (*l)->start ())); } _jumplist.clear (); @@ -503,28 +544,73 @@ MiniTimeline::render (Cairo::RefPtr const& ctx, cairo_rectangle_ LocationMarkerSort location_marker_sort; std::sort (lm.begin(), lm.end(), location_marker_sort); + std::vector::const_iterator outside_left = lm.end(); + std::vector::const_iterator outside_right = lm.end(); + int left_limit = 0; + int right_limit = 0; int id = 0; + for (std::vector::const_iterator l = lm.begin(); l != lm.end(); ++id) { framepos_t when = (*l).when; - int x0 = floor (get_width() * .5 + (when - p) * _px_per_sample); - int x1 = get_width(); + if (when < lmin) { + outside_left = l; + if (++l != lm.end()) { + left_limit = floor (width * .5 + ((*l).when - p) * _px_per_sample) - 1 - mw; + } else { + left_limit = width; + } + continue; + } + if (when > lmax) { + outside_right = l; + break; + } + int x0 = floor (width * .5 + (when - p) * _px_per_sample); + int x1 = width; const std::string& label = (*l).label; if (++l != lm.end()) { - x1 = floor (get_width() * .5 + ((*l).when - p) * _px_per_sample) - 1 - mw; + x1 = floor (width * .5 + ((*l).when - p) * _px_per_sample) - 1 - mw; } bool prelight = false; x1 = draw_mark (cr, x0, x1, label, prelight); _jumplist.push_back (JumpRange (x0 - mw, x1, when, prelight)); + right_limit = x1; + } + + if (outside_left != lm.end ()) { + if (left_limit > 3 * mw + PADDING) { + int x0 = PADDING + 1; + int x1 = left_limit; + bool prelight = false; + x1 = draw_edge (cr, x0, x1, true, (*outside_left).label, prelight); + if (x0 != x1) { + _jumplist.push_back (JumpRange (x0, x1, (*outside_left).when, prelight)); + right_limit = std::max (x1, right_limit); + } + } + } + + if (outside_right != lm.end ()) { + if (right_limit + PADDING < width - 3 * mw) { + int x0 = right_limit; + int x1 = width - PADDING; + bool prelight = false; + x0 = draw_edge (cr, x0, x1, false, (*outside_right).label, prelight); + if (x0 != x1) { + _jumplist.push_back (JumpRange (x0, x1, (*outside_right).when, prelight)); + } + } } + /* playhead on top */ - int xc = get_width () * 0.5f; + int xc = width * 0.5f; cairo_set_line_width (cr, 1.0); cairo_set_source_rgb (cr, 1, 0, 0); // playhead color cairo_move_to (cr, xc - .5, 0); - cairo_rel_line_to (cr, 0, get_height ()); + cairo_rel_line_to (cr, 0, height); cairo_stroke (cr); - cairo_move_to (cr, xc - .5, get_height ()); + cairo_move_to (cr, xc - .5, height); cairo_rel_line_to (cr, -3, 0); cairo_rel_line_to (cr, 3, -4); cairo_rel_line_to (cr, 3, 4); @@ -589,7 +675,7 @@ MiniTimeline::on_button_release_event (GdkEventButton *ev) if (ev->y <= PADDING + _marker_height) { for (JumpList::const_iterator i = _jumplist.begin (); i != _jumplist.end(); ++i) { - if (i->left < ev->x && ev->x < i->right) { + if (i->left <= ev->x && ev->x <= i->right) { _session->request_locate (i->to, _session->transport_rolling ()); return true; } -- cgit v1.2.3