tuikit/core/buffer.py
author Radek Brich <radek.brich@devl.cz>
Fri, 14 Mar 2014 08:44:15 +0100
changeset 79 dbdc38f9981a
parent 78 6031e99c8ad3
child 81 5cd40c30c4f2
permissions -rw-r--r--
Add attribute storage to Buffer.

from tuikit.common import Size


class Cell:

    """Character buffer cell.

    Cell contains one character and its attribute.

    """

    __slots__ = ('char', 'attr')

    def __init__(self, char=' ', attr=0):
        self.char = char
        self.attr = attr

    def set(self, char, attr):
        self.char = char
        self.attr = attr


class Buffer:

    """Rectangular character buffer.

    Retains characters and colors drawn into it
    until resized. Contents are reset when resized.

    """

    def __init__(self, w=0, h=0):
        self._size = Size(w, h)
        self._data = None
        self._attr_descs = ['default']
        self._attr_map = {'default': 0}
        self._current_attr = 0
        self.clear()
        self._size.add_handler('change', self._on_resize)

    @property
    def size(self):
        return self._size

    def resize(self, w, h):
        """Resize buffer."""
        self._size.update(w, h)

    def _on_resize(self):
        """Reset contents of buffer when resized."""
        self.clear()

    def clear(self):
        """Reset buffer data."""
        self._data = [Cell() for _i in range(self._size.w * self._size.h)]

    def get(self, x, y):
        """Get cell data at `x`, `y` coords.

        Returns tuple (char, attr_desc).

        """
        cell = self._data[y * self._size.w + x]
        return cell.char, self._attr_descs[cell.attr]

    def putch(self, x, y, ch):
        """Set character on xy coords to c."""
        self._data[y * self._size.w + x].set(ch, self._current_attr)

    def puts(self, x, y, s):
        """Output string of characters."""
        for c in s:
            self.putch(x, y, c)
            x += 1

    def hline(self, x, y, w, c=' '):
        """Draw horizontal line."""
        self.puts(x, y, [c] * w)

    def vline(self, x, y, h, c=' '):
        """Draw vertical line."""
        for i in range(h):
            self.putch(x, y + i, c)

    def fill(self, x=0, y=0, w=0, h=0, c=' '):
        """Fill rectangular area."""
        w = self._size.w if not w else w
        h = self._size.h if not h else h
        for i in range(h):
            self.hline(x, y + i, w, c)

    def setattr(self, attr_desc):
        """Set attribute to be used for subsequent draw operations."""
        if attr_desc in self._attr_map:
            attr = self._attr_map[attr_desc]
        else:
            attr = len(self._attr_descs)
            self._attr_descs.append(attr_desc)
            self._attr_map[attr_desc] = attr
        self._current_attr = attr