tuikit/widget.py
author Radek Brich <radek.brich@devl.cz>
Mon, 10 Oct 2011 22:20:59 +0200
changeset 25 f69a1f0382ce
parent 18 e6c3a5ee91aa
child 32 088b92ffb119
permissions -rw-r--r--
Partial DriverPygame.putch() implementation. Add patch for PyGame implementing font.render_glyph(). Add test for PyGame font module. Add special key definitions to DriverPygame.

# -*- coding: utf-8 -*-

import logging

from tuikit.eventsource import EventSource
from tuikit.common import Coords, Size


class Widget(EventSource):

    '''Base class for all widgets.'''

    def __init__(self, width = 10, height = 10):
        '''Blah.'''
        EventSource.__init__(self)

        #: Parent widget.
        self.parent = None
        
        #: Top widget (same for every widget in one application).
        self.top = None
        
        # Position inside parent widget. Modified by layout manager.
        self.position = Coords()
        
        # Actual size. Modified by layout manager.
        self.size = Size(width, height)
        
        #: Minimal size of widget. Under normal circumstances
        #: widget will never be sized smaller than this.
        #: Tuple (w, h). Both must be integers >= 1.
        self.sizemin = Size(1,1)
        
        #: Maximum size of widget. Widget will never be sized bigger than this.
        #: Tuple (w, h). Integers >= 1 or None (meaning no maximum size or infinite).
        self.sizemax = Size(None, None)
        
        #: Size request. This is default size of the widget. Will be fulfilled if possible.
        #: Tuple (w, h). Integers >= 1 or None (meaning use minumal size).
        self.sizereq = Size(10,10)
        
        #: When false, the widget is not considered in layout.
        self.allowlayout = True
        
        #: Dictionary containing optional parameters for layout managers etc.
        self.hints = {}
        
        #: Hidden widget does not affect layout.
        self.hidden = False
        
        # cursor
        self.cursor = None
        
        # redraw request
        self._redraw = True
        
        # event handlers
        self.addevents(
            'resize',
            'draw',
            'focus',
            'unfocus',
            'keypress',
            'mousedown',
            'mouseup',
            'mousemove',
            'mousewheel')


    @property
    def x(self):
        return self.position.x

    @x.setter
    def x(self, value):
        self.position.x = value
        #self.emit('resize')

    @property
    def y(self):
        return self.position.y

    @y.setter
    def y(self, value):
        self.position.y = value
        #self.emit('resize')


    @property
    def width(self):
        return self.size.w

    @width.setter
    def width(self, value):
        self.size.w = value
        self.emit('resize')

    @property
    def height(self):
        return self.size.h

    @height.setter
    def height(self, value):
        self.size.h = value
        self.emit('resize')


    def settop(self, top):
        self.top = top


    ### events


    def resize(self):
        log = logging.getLogger('tuikit')
        log.debug('%r: resize', self)
        self.handle('resize')


    def redraw(self, parent=True):
        self._redraw = True
        if parent and self.parent:
            self.parent._redraw = True


    def draw(self, screen, x=0, y=0):
        if self.hidden:
            return

        self.handle('draw', screen, x, y)

        if self.hasfocus():
            if self.cursor:
                cx, cy = self.cursor
                screen.showcursor(x + cx, y + cy)
            else:
                screen.hidecursor()


    def keypress(self, keyname, char):
        handled = self.handle('keypress', keyname, char)
        if not handled and self.parent and self.parent != self.top:
            self.parent.emit('keypress', keyname, char)


    def mousedown(self, ev):
        self.setfocus()
        self.handle('mousedown', ev)


    def mouseup(self, ev):
        self.handle('mouseup', ev)


    def mousemove(self, ev):
        self.handle('mousemove', ev)


    def mousewheel(self, ev):
        self.handle('mousewheel', ev)


    ### focus


    def canfocus(self):
        return bool(self.event['keypress'])


    def hasfocus(self):
        return self.top.focuswidget == self


    def setfocus(self):
        if self.hasfocus() or not self.canfocus():
            return
        if self.top.focuswidget:
            self.top.focuswidget.resetfocus()
        self.top.focuswidget = self
        self.emit('focus')


    def resetfocus(self):
        if self.top.focuswidget != self:
            return
        self.top.focuswidget = None
        self.emit('unfocus')


    def focus(self):
        '''handle focus event'''
        self.handle('focus')


    def unfocus(self, newfocus=None):
        '''handle unfocus event'''
        self.handle('unfocus', newfocus)


    ###

    def hint(self, key):
        if key in self.hints:
            return self.hints[key]

    def enclose(self, x, y):
        if self.hidden:
            return False
        if x < self.x or y < self.y \
        or x >= self.x + self.width or y >= self.y + self.height:
            return False
        return  True


    def screentest(self, y, x):
        sy, sx = self.screenyx()
        if y < sy or x < sx or y >= sy + self.height or x >= sx + self.width:
            return False
        return True


    def screenyx(self):
        if self.parent:
            y,x = self.parent.screenyx()
            return self.y + y, self.x + x
        return self.y, self.x


    def hide(self):
        '''Hide widget. Convenience method.'''
        self.hidden = True
        self.redraw()


    def show(self):
        '''Show widget. Convenience method.'''
        self.hidden = False
        self.redraw()