Commit c5e5d11a authored by Alexandru Băluț's avatar Alexandru Băluț Committed by Thibault Saunier

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's avatarThibault Saunier <tsaunier@gnome.org>
Differential Revision: https://phabricator.freedesktop.org/D561
parent d691b3bf
...@@ -37,13 +37,40 @@ from pitivi.utils.ui import NORMAL_FONT, PLAYHEAD_WIDTH, set_cairo_color, time_t ...@@ -37,13 +37,40 @@ from pitivi.utils.ui import NORMAL_FONT, PLAYHEAD_WIDTH, set_cairo_color, time_t
HEIGHT = 25 HEIGHT = 25
# A series of valid interval lengths in seconds. # Tuples of:
SCALES = (0.5, 1, 2, 5, 10, 15, 30, 60, 120, 300, 600, 3600) # - 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. # The minimum distance between adjacent ticks.
MIN_TICK_SPACING_PIXELS = 3 MIN_TICK_SPACING_PIXELS = 6
# (count per interval, height ratio) tuples determining how the ticks appear.
TICK_TYPES = ((1, 1.0), (2, 0.5), (10, .25))
# For displaying the times a bit to the right. # For displaying the times a bit to the right.
TIMES_LEFT_MARGIN_PIXELS = 3 TIMES_LEFT_MARGIN_PIXELS = 3
...@@ -204,9 +231,8 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): ...@@ -204,9 +231,8 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
Set the lowest scale based on project framerate Set the lowest scale based on project framerate
""" """
self.frame_rate = rate self.frame_rate = rate
self.ns_per_frame = float(1 / self.frame_rate) * Gst.SECOND self.ns_per_frame = float(Gst.SECOND / self.frame_rate)
self.scales = (float(2 / rate), float( self.scales = (2 / rate, 5 / rate, 10 / rate) + SCALES
5 / rate), float(10 / rate)) + SCALES
# Drawing methods # Drawing methods
...@@ -220,26 +246,29 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): ...@@ -220,26 +246,29 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
context.set_font_face(NORMAL_FONT) context.set_font_face(NORMAL_FONT)
context.set_font_size(NORMAL_FONT_SIZE) context.set_font_size(NORMAL_FONT_SIZE)
spacing, scale = self._getSpacing(context) spacing, interval_seconds, ticks = self._getSpacing(context)
offset = self.pixbuf_offset % spacing offset = self.pixbuf_offset % spacing
self.drawFrameBoundaries(context) self.drawFrameBoundaries(context)
self.drawTicks(context, offset, spacing) self.drawTicks(context, offset, spacing, interval_seconds, ticks)
self.drawTimes(context, offset, spacing, scale) self.drawTimes(context, offset, spacing, interval_seconds)
def _getSpacing(self, context): 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 zoom = Zoomable.zoomratio
for scale in self.scales: for interval_seconds, ticks in SCALES:
spacing = scale * zoom interval_width = interval_seconds * zoom
if spacing >= textwidth * 1.5: if interval_width >= min_interval_width:
return spacing, scale return interval_width, interval_seconds, ticks
raise Exception( raise Exception(
"Failed to find an interval size for textwidth:%s, zoomratio:%s" % "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): def drawTicks(self, context, offset, spacing, interval_seconds, ticks):
for count_per_interval, height_ratio in TICK_TYPES: for tick_interval, height_ratio in ticks:
space = float(spacing) / count_per_interval count_per_interval = interval_seconds / tick_interval
space = spacing / count_per_interval
if space < MIN_TICK_SPACING_PIXELS: if space < MIN_TICK_SPACING_PIXELS:
break break
paintpos = 0.5 - offset paintpos = 0.5 - offset
...@@ -259,9 +288,9 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): ...@@ -259,9 +288,9 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
context.close_path() context.close_path()
context.stroke() context.stroke()
def drawTimes(self, context, offset, spacing, scale): def drawTimes(self, context, offset, spacing, interval_seconds):
# figure out what the optimal offset is # 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) current_time = self.pixelToNs(self.pixbuf_offset)
paintpos = TIMES_LEFT_MARGIN_PIXELS paintpos = TIMES_LEFT_MARGIN_PIXELS
if offset > 0: if offset > 0:
...@@ -270,7 +299,6 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): ...@@ -270,7 +299,6 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
set_cairo_color(context, self._color_normal) set_cairo_color(context, self._color_normal)
y_bearing = context.text_extents("0")[1] y_bearing = context.text_extents("0")[1]
millis = scale < 1
def split(x): def split(x):
# Seven elements: h : mm : ss . mmm # Seven elements: h : mm : ss . mmm
...@@ -283,6 +311,7 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): ...@@ -283,6 +311,7 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
while paintpos < width: while paintpos < width:
context.move_to(int(paintpos), 1 - y_bearing) context.move_to(int(paintpos), 1 - y_bearing)
current = split(time_to_string(int(current_time))) current = split(time_to_string(int(current_time)))
millis = current_time % Gst.SECOND > 0
self._drawTime(context, current, previous, millis) self._drawTime(context, current, previous, millis)
previous = current previous = current
paintpos += spacing paintpos += spacing
...@@ -292,15 +321,22 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable): ...@@ -292,15 +321,22 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
hour = int(current[0]) hour = int(current[0])
for index, (element, previous_element) in enumerate(zip(current, previous)): for index, (element, previous_element) in enumerate(zip(current, previous)):
if index <= 1 and not hour: if index <= 1 and not hour:
# Don't draw hour if 0.
continue continue
if index >= 5 and not millis: if millis:
break # Draw only the millis.
if index < 5:
continue
else:
# Don't draw the millis.
if index == 5:
break
if element == previous_element: if element == previous_element:
color = self._color_dimmed color = self._color_dimmed
else: else:
color = self._color_normal color = self._color_normal
set_cairo_color(context, color) set_cairo_color(context, color)
# Display the millis with a smaller font # Display the millis with a smaller font.
small = index >= 5 small = index >= 5
if small: if small:
context.set_font_size(SMALL_FONT_SIZE) context.set_font_size(SMALL_FONT_SIZE)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment