From c5e5d11ae5230d59bd1a356d54961c45460e06cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandru=20B=C4=83lu=C8=9B?= Date: Mon, 9 Nov 2015 22:25:41 +0100 Subject: [PATCH] ruler: Different tick patterns for different zoom levels Also change the display of the timestamps. When the timestamp has millis, for example .500, .100, etc. only the millis are displayed. Considering that they are displayed with a smaller font, it should make more visible the timestamp showing the relevant second. Reviewed-by: Thibault Saunier Differential Revision: https://phabricator.freedesktop.org/D561 --- pitivi/timeline/ruler.py | 88 ++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/pitivi/timeline/ruler.py b/pitivi/timeline/ruler.py index 41369c332..d91839488 100644 --- a/pitivi/timeline/ruler.py +++ b/pitivi/timeline/ruler.py @@ -37,13 +37,40 @@ from pitivi.utils.ui import NORMAL_FONT, PLAYHEAD_WIDTH, set_cairo_color, time_t HEIGHT = 25 -# A series of valid interval lengths in seconds. -SCALES = (0.5, 1, 2, 5, 10, 15, 30, 60, 120, 300, 600, 3600) +# Tuples of: +# - an interval lengths in seconds for which a timestamp will be displayed +# - how the ticks should be displayed for this interval: +# (count per interval, height ratio) tuples. +SCALES = ( + (0.1, ((0.1, 1.0), (0.05, .5), (0.01, .25))), + (0.2, ((0.2, 1.0), (0.1, .5), (0.05, .25))), + (0.5, ((0.5, 1.0), (0.1, .25))), + + # 1 second. + (1, ((1, 1.0), (0.5, .5), (0.1, .25))), + (2, ((2, 1.0), (1, .5), (0.5, .25))), + (5, ((5, 1.0), (1, .25))), + (10, ((10, 1.0), (5, .5), (1, .25))), + (20, ((20, 1.0), (10, .5), (1, .25))), + (30, ((30, 1.0), (10, .5), (1, .25))), + + # 1 minute. + (60, ((60, 1.0), (30, .5), (15, .25))), + # 2 minutes. + (120, ((120, 1.0), (60, .5), (30, .25))), + # 5 minutes. + (300, ((300, 1.0), (60, .25))), + # 10 minutes. + (600, ((600, 1.0), (300, .5), (60, .25))), + # 30 minutes. + (1800, ((1800, 1.0), (900, .5), (450, .25))), + + # 1 hour. + (3600, ((3600, 1.0), (1800, .75), (900, .5))), +) # The minimum distance between adjacent ticks. -MIN_TICK_SPACING_PIXELS = 3 -# (count per interval, height ratio) tuples determining how the ticks appear. -TICK_TYPES = ((1, 1.0), (2, 0.5), (10, .25)) +MIN_TICK_SPACING_PIXELS = 6 # For displaying the times a bit to the right. TIMES_LEFT_MARGIN_PIXELS = 3 @@ -204,9 +231,8 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): Set the lowest scale based on project framerate """ self.frame_rate = rate - self.ns_per_frame = float(1 / self.frame_rate) * Gst.SECOND - self.scales = (float(2 / rate), float( - 5 / rate), float(10 / rate)) + SCALES + self.ns_per_frame = float(Gst.SECOND / self.frame_rate) + self.scales = (2 / rate, 5 / rate, 10 / rate) + SCALES # Drawing methods @@ -220,26 +246,29 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): context.set_font_face(NORMAL_FONT) context.set_font_size(NORMAL_FONT_SIZE) - spacing, scale = self._getSpacing(context) + spacing, interval_seconds, ticks = self._getSpacing(context) offset = self.pixbuf_offset % spacing self.drawFrameBoundaries(context) - self.drawTicks(context, offset, spacing) - self.drawTimes(context, offset, spacing, scale) + self.drawTicks(context, offset, spacing, interval_seconds, ticks) + self.drawTimes(context, offset, spacing, interval_seconds) def _getSpacing(self, context): - textwidth = context.text_extents(time_to_string(0))[2] + # The longest timestamp we display is 0:00:00 because + # when we display millis, they are displayed by themselves. + min_interval_width = context.text_extents("0:00:00")[2] * 1.3 zoom = Zoomable.zoomratio - for scale in self.scales: - spacing = scale * zoom - if spacing >= textwidth * 1.5: - return spacing, scale + for interval_seconds, ticks in SCALES: + interval_width = interval_seconds * zoom + if interval_width >= min_interval_width: + return interval_width, interval_seconds, ticks raise Exception( "Failed to find an interval size for textwidth:%s, zoomratio:%s" % - (textwidth, Zoomable.zoomratio)) + (min_interval_width, Zoomable.zoomratio)) - def drawTicks(self, context, offset, spacing): - for count_per_interval, height_ratio in TICK_TYPES: - space = float(spacing) / count_per_interval + def drawTicks(self, context, offset, spacing, interval_seconds, ticks): + for tick_interval, height_ratio in ticks: + count_per_interval = interval_seconds / tick_interval + space = spacing / count_per_interval if space < MIN_TICK_SPACING_PIXELS: break paintpos = 0.5 - offset @@ -259,9 +288,9 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): context.close_path() context.stroke() - def drawTimes(self, context, offset, spacing, scale): + def drawTimes(self, context, offset, spacing, interval_seconds): # figure out what the optimal offset is - interval = int(Gst.SECOND * scale) + interval = int(Gst.SECOND * interval_seconds) current_time = self.pixelToNs(self.pixbuf_offset) paintpos = TIMES_LEFT_MARGIN_PIXELS if offset > 0: @@ -270,7 +299,6 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): set_cairo_color(context, self._color_normal) y_bearing = context.text_extents("0")[1] - millis = scale < 1 def split(x): # Seven elements: h : mm : ss . mmm @@ -283,6 +311,7 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): while paintpos < width: context.move_to(int(paintpos), 1 - y_bearing) current = split(time_to_string(int(current_time))) + millis = current_time % Gst.SECOND > 0 self._drawTime(context, current, previous, millis) previous = current paintpos += spacing @@ -292,15 +321,22 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): hour = int(current[0]) for index, (element, previous_element) in enumerate(zip(current, previous)): if index <= 1 and not hour: + # Don't draw hour if 0. continue - if index >= 5 and not millis: - break + if millis: + # Draw only the millis. + if index < 5: + continue + else: + # Don't draw the millis. + if index == 5: + break if element == previous_element: color = self._color_dimmed else: color = self._color_normal set_cairo_color(context, color) - # Display the millis with a smaller font + # Display the millis with a smaller font. small = index >= 5 if small: context.set_font_size(SMALL_FONT_SIZE) -- GitLab