tuikit/window.py
author Radek Brich <radek.brich@devl.cz>
Wed, 20 Aug 2014 15:06:52 +0200
changeset 102 29a8a26a721f
parent 98 dcfb185ac866
permissions -rw-r--r--
Update TreeView (old uncommitted work).

# -*- 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.

    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()
        self._inner.add_handler('draw', self._on_inner_draw)
        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 _on_inner_draw(self, ev):
        ev.driver.pushcolor('normal')
        ev.driver.fill_clip()
        ev.driver.popcolor()

    def on_mousedown(self, ev):
        self.bring_up()

    def after_mousedown(self, ev):
        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.redraw()

    def after_mouseup(self, ev):
        self._resize_or_move(ev)
        self._resizing = False
        self._moving = False
        self.redraw()

    def after_mousemove(self, ev):
        self._resize_or_move(ev)
        self.redraw()

    def _resize_or_move(self, ev):
        if self._resizing:
            self.resize(self.sizereq.w + ev.relx,
                        self.sizereq.h + ev.rely)
            # AnchorLayout, right/bottom align
            # also move the window so that it visualy stays in place
            if 'halign' in self._hints and self.hint_value('halign') == 'right':
                self.move(x = self.x + ev.relx)
            if 'valign' in self._hints and self.hint_value('valign') == 'bottom':
                self.move(y = self.y + ev.rely)
        elif self._moving:
            self.move(self.x + ev.relx,
                      self.y + ev.rely)

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