tuikit/window.py
author Radek Brich <radek.brich@devl.cz>
Sat, 19 Jan 2013 13:05:21 +0100
changeset 63 2a0e04091898
parent 62 2f61931520c9
child 71 cfd3445107b4
permissions -rw-r--r--
Rework MenuBar. Add MenuButton. Add mouse event cascading to floaters. LinearLayout: spacing now applies to all children, not just those with expand. Fix Window resize request inside layouts. UnicodeGraphics: prepare for styling/theming.

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

from tuikit.container import Container
from tuikit.button import Button
from tuikit.layout import AnchorLayout
from tuikit.common import Borders

import logging

class Window(AnchorLayout):

    '''Window widget.

    It represents part of screen with border, close button and contents.
    Window can be moved, resized or closed by user.'''

    def __init__(self, inner_layout=AnchorLayout):
        '''Create window of requested size.'''
        AnchorLayout.__init__(self)
        self.sizemin.update(8, 3)

        #: Window title.
        self.title = ''

        #: Allow user to resize window.
        self.resizable = True
        self._resizing = False
        #: Allow user to move window.
        self.movable = True
        self._moving = False

        self.closebtn = Button('x')
        self.closebtn.sizereq.w = 3
        self.closebtn.add_handler('click', self.on_closebtn_click)
        self.closebtn.bg = 'controls'
        self.closebtn.bghi = 'controls-active'
        Container.add(self, self.closebtn, halign='right', margin=Borders(r=1))
        self._closebutton = True

        self.colorprefix = 'window:'

        self._inner = inner_layout()
        Container.add(self, self._inner, halign='fill', valign='fill', margin=Borders(1,1,1,1))

    def add(self, widget, **kwargs):
        self._inner.add(widget, **kwargs)

    @property
    def closebutton(self):
        '''Show/hide close button.'''
        return self._closebutton

    @closebutton.setter
    def closebutton(self, value):
        self._closebutton = value
        self.closebtn.hidden = not value


    def on_draw(self, ev):
        ev.driver.pushcolor('normal')
        ev.driver.frame(ev.x, ev.y, self.width, self.height)

        if self.resizable:
            if self._resizing:
                ev.driver.pushcolor('controls-active')
            else:
                ev.driver.pushcolor('controls')
            ev.driver.puts(ev.x + self.width - 2, ev.y + self.height - 1, '─┘') # '━┛'
            ev.driver.popcolor()

        if self.title:
            title = ' ' + self.title + ' '
            left = max(1, (self.width - len(title))//2)
            right = self.width - len(title) - left
            maxlen = self.width - 5
            if left > 1 and right < 4:
                # move space from left to right to make space for close button
                left -= 1
            if len(title) > maxlen:
                title = title[:maxlen]
                title = title[:-1] + ' '
            ev.driver.puts(ev.x + left, ev.y, title)

        ev.driver.fill(ev.x+1, ev.y+1, self.width-2, self.height-2)
        ev.driver.popcolor()


    def after_mousedown(self, ev):
        self.dragstart = (ev.wx, ev.wy)
        if self.resizable and ev.wx >= self.width - 1 and ev.wy >= self.height - 1:
            self._resizing = True
        elif self.movable:
            self._moving = True
        self.origsize = (self.width, self.height)

        self.redraw(True)


    def after_mouseup(self, ev):
        if self._resizing:
            self.resize(self.origsize[0] + ev.wx - self.dragstart[0],
                        self.origsize[1] + ev.wy - self.dragstart[1])
            self._resizing = False
        elif self._moving:
            self.move(ev.px - self.dragstart[0],
                      ev.py - self.dragstart[1])
            self._moving = False

        self.redraw(True)


    def after_mousemove(self, ev):
        if ev.px == self.x + self.dragstart[0] \
        and ev.py == self.y + self.dragstart[1]:
            return

        #if x > self.parent.width-self.width:
        #    return

        if self._resizing:
            self.resize(self.origsize[0] + ev.wx - self.dragstart[0],
                        self.origsize[1] + ev.wy - self.dragstart[1])
        elif self._moving:
            self.move(ev.px - self.dragstart[0],
                      ev.py - self.dragstart[1])

        self.redraw(True)


    def on_closebtn_click(self, ev):
        self.hide()