[pitivi] ruler: Different tick patterns for different zoom levels



commit c5e5d11ae5230d59bd1a356d54961c45460e06cd
Author: Alexandru Băluț <alexandru balut gmail com>
Date:   Mon Nov 9 22:25:41 2015 +0100

    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 <tsaunier gnome org>
    Differential Revision: https://phabricator.freedesktop.org/D561

 pitivi/timeline/ruler.py |   88 ++++++++++++++++++++++++++++++++-------------
 1 files changed, 62 insertions(+), 26 deletions(-)
---
diff --git a/pitivi/timeline/ruler.py b/pitivi/timeline/ruler.py
index 41369c3..d918394 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)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]