Cleanup timeouts.
authorRadek Brich <radek.brich@devl.cz>
Tue, 08 Jan 2013 23:59:55 +0100
changeset 59 729fcdfe6b57
parent 58 50308ed5e4f9
child 60 fccca2a60492
Cleanup timeouts.
tuikit/application.py
tuikit/scrollbar.py
tuikit/widget.py
--- a/tuikit/application.py	Tue Jan 08 23:36:01 2013 +0100
+++ b/tuikit/application.py	Tue Jan 08 23:59:55 2013 +0100
@@ -2,11 +2,55 @@
 
 import logging
 import time
-import math
 
 from tuikit.container import Container
 
 
+class Timer:
+    def __init__(self):
+        self.timeouts = []
+        self.timelast = None
+
+    def add_timeout(self, delay, callback):
+        """Register callback to be called after delay seconds.
+
+        delay -- in seconds, float
+        callback -- function to be called with no parameters
+
+        """
+        if not len(self.timeouts):
+            self.timelast = time.time()
+        self.timeouts += [[delay, callback]]
+
+    def remove_timeout(self, callback):
+        """Unregister callback previously registered with add_timeout."""
+        for timeout in self.timeouts[:]:
+            if timeout[1] == callback:
+                self.timeouts.remove(timeout)
+
+    def has_timeout(self):
+        return len(self.timeouts) > 0
+
+    def nearest_timeout(self):
+        if not self.has_timeout():
+            return None
+        return min(self.timeouts)[0]
+
+    def process_timeouts(self):
+        if not self.has_timeout():
+            return
+        now = time.time()
+        lasted = now - self.timelast
+        self.timelast = now
+        for timeout in self.timeouts[:]:
+            adjusted_delay = timeout[0] - lasted
+            if adjusted_delay <= 0.0:
+                timeout[1]()
+                self.timeouts.remove(timeout)
+            else:
+                timeout[0] = adjusted_delay
+
+
 class TopWindow(Container):
 
     '''Top window of an application. Covers entire screen.'''
@@ -14,11 +58,8 @@
     def __init__(self):
         '''Create top window.'''
         Container.__init__(self)
-
         self.top = self
-
-        self.timeout = []
-        self.timelast = None
+        self.timer = Timer()
 
     def draw(self, driver, x=0, y=0):
         """Draw the top window and its children.
@@ -29,42 +70,6 @@
         driver.erase()
         Container.draw(self, driver, x, y)
 
-    def add_timeout(self, s, func):
-        if not len(self.timeout):
-            self.timelast = time.time()
-        self.timeout += [[s, func]]
-
-
-    def remove_timeout(self, func):
-        for to in self.timeout[:]:
-            if to[1] == func:
-                self.timeout.remove(to)
-
-
-    def has_timeout(self):
-        return len(self.timeout) > 0
-
-
-    def nearest_timeout(self):
-        if not self.has_timeout():
-            return None
-        return min(self.timeout)[0]
-
-
-    def process_timeout(self):
-        if not self.has_timeout():
-            return
-        now = time.time()
-        lasted = now - self.timelast
-        self.timelast = now
-        for to in self.timeout[:]:
-            newt = to[0] - lasted
-            if newt <= 0.0:
-                to[1]()
-                self.timeout.remove(to)
-            else:
-                to[0] = newt
-
 
 class Application:
 
@@ -102,14 +107,15 @@
         self.applytheme()
         self.top.size = self.driver.size  # link top widget size to screen size
         self.top.emit('resize')
+        timer = self.top.timer
 
         while True:
             self.top.draw(self.driver)
             self.driver.commit()
 
-            timeout = self.top.nearest_timeout()
+            timeout = timer.nearest_timeout()
             events = self.driver.getevents(timeout)
-            self.top.process_timeout()
+            timer.process_timeouts()
 
             for event in events:
                 if event[0] == 'quit':
--- a/tuikit/scrollbar.py	Tue Jan 08 23:36:01 2013 +0100
+++ b/tuikit/scrollbar.py	Tue Jan 08 23:59:55 2013 +0100
@@ -12,7 +12,9 @@
         self._pos = 0
         self._thumbpos = 0
 
-        self.interval = 0.1
+        # interval for continuous scroll when user holds mouse on scrollbar arrow
+        self.scroll_delay = 0.150
+        self.scroll_interval = 0.030
 
         self.dragging = False
         self.move = None
@@ -67,7 +69,7 @@
                 self.move_up()
             else:
                 self.move_down()
-            self.top.add_timeout(self.interval * 2, self._timeout)
+            self.add_timeout(self.scroll_delay, self._continuous_scroll)
             return
         # thumb bar
         if ev.wy == 1 + self._thumbpos:
@@ -80,7 +82,7 @@
             self.dragging = False
             return
         if self.move:
-            self.top.remove_timeout(self._timeout)
+            self.remove_timeout(self._continuous_scroll)
             self.move = None
             return
 
@@ -88,13 +90,6 @@
         if self.dragging:
             self.drag(ev.wy)
 
-    def _timeout(self):
-        if self.move == 'up':
-            self.move_up()
-        if self.move == 'down':
-            self.move_down()
-        self.top.add_timeout(self.interval, self._timeout)
-
     def move_up(self):
         if self._pos > 0:
             self.pos = self._pos - 1
@@ -114,3 +109,10 @@
         if self._pos != newpos:
             self.pos = newpos
 
+    def _continuous_scroll(self):
+        if self.move == 'up':
+            self.move_up()
+        if self.move == 'down':
+            self.move_down()
+        self.add_timeout(self.scroll_interval, self._continuous_scroll)
+
--- a/tuikit/widget.py	Tue Jan 08 23:36:01 2013 +0100
+++ b/tuikit/widget.py	Tue Jan 08 23:59:55 2013 +0100
@@ -260,3 +260,19 @@
         self.hidden = False
         self.redraw()
 
+
+    ## timeout ##
+
+    def add_timeout(self, delay, callback):
+        """Register callback to be called after delay seconds.
+
+        delay -- in seconds, float
+        callback -- function to be called with no parameters
+
+        """
+        self.top.timer.add_timeout(delay, callback)
+
+    def remove_timeout(self, callback):
+        """Unregister callback previously registered with add_timeout."""
+        self.top.timer.remove_timeout(callback)
+