tuikit/scrollbar.py
author Radek Brich <radek.brich@devl.cz>
Fri, 04 Jan 2013 00:13:59 +0100
changeset 45 43b2279b06e1
parent 43 369c8ef5070a
child 59 729fcdfe6b57
permissions -rw-r--r--
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