Clean up Emitter class, simplify event handling. Fix Container.focusnext() method. Add events test (handler auto-registration, order).
# -*- coding: utf-8 -*-
from tuikit.widget import Widget
from tuikit.events import Event
class VScrollbar(Widget):
def __init__(self, height=10):
Widget.__init__(self, 1, height)
self._max = height - 3
self._pos = 0
self._thumbpos = 0
self.interval = 0.1
self.dragging = False
self.move = None
self.add_events('change', Event)
@property
def max(self):
"""Maximum for scrolling position."""
return self._max
@max.setter
def max(self, value):
self._max = value
self._update_thumbpos()
@property
def pos(self):
"""Scrolling position.
Integer number between 0 and 'max'.
"""
return self._pos
@pos.setter
def pos(self, value):
if self._pos != value:
self._pos = value
self._update_thumbpos()
self.emit('change')
def _update_thumbpos(self):
self._thumbpos = 0
if self._max and self._pos <= self._max:
self._thumbpos = int(round(self._pos / self._max * (self.height - 3)))
self.redraw()
def on_draw(self, ev):
ev.driver.putch(ev.x, ev.y, ev.driver.unigraph.UP_ARROW)
for i in range(ev.y + 1, ev.y + self.height - 1):
ev.driver.putch(ev.x, i, ev.driver.unigraph.LIGHT_SHADE)
ev.driver.putch(ev.x, ev.y + 1 + self._thumbpos, ev.driver.unigraph.BLOCK)
ev.driver.putch(ev.x, ev.y + self.height - 1, ev.driver.unigraph.DOWN_ARROW)
def on_mousedown(self, ev):
self.dragging = False
self.move = None
# arrow buttons
if ev.wy == 0 or ev.wy == self.height - 1:
if ev.wy == 0:
self.move_up()
else:
self.move_down()
self.top.add_timeout(self.interval * 2, self._timeout)
return
# thumb bar
if ev.wy == 1 + self._thumbpos:
self.dragging = True
return
def on_mouseup(self, ev):
if self.dragging:
self.drag(ev.wy)
self.dragging = False
return
if self.move:
self.top.remove_timeout(self._timeout)
self.move = None
return
def on_mousemove(self, ev):
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
self.move = 'up'
def move_down(self):
if self._pos < self._max:
self.pos = self._pos + 1
self.move = 'down'
def drag(self, wy):
newpos = int(round((wy - 1) / (self.height - 3) * self._max))
if newpos < 0:
newpos = 0
if newpos > self._max:
newpos = self._max
if self._pos != newpos:
self.pos = newpos