tuikit/editfield.py
author Radek Brich <radek.brich@devl.cz>
Fri, 18 Jan 2013 22:36:50 +0100
changeset 62 2f61931520c9
parent 45 43b2279b06e1
permissions -rw-r--r--
Rework layouts: Layout is now normal Container which places its children upon resize event. Drop TopWindow, top is now any subclass of Container. Add floater concept: floaters are widgets drawn over normal widgets, not clipped by parent. Add HScrollbar and Scrollbar abstract base class.

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

import locale

from tuikit.widget import Widget


class EditField(Widget):
    def __init__(self, value=''):
        Widget.__init__(self)
        self._default_size.update(10, 1)

        self.allow_focus = True

        self.code = locale.getpreferredencoding()
        if not isinstance(value, str):
            value = str(value, self.code)

        self.value = value
        self.maxlen = None   # unlimited

        self.tw = 0       # real width of text field (minus space for arrows)
        self.pos = len(value)      # position of cursor in value
        self.ofs = 0      # position of value beginning on screen

    def on_resize(self, ev):
        self.tw = self.width - 2

    def on_draw(self, ev):
        ev.driver.pushcolor('normal')
        # draw value
        val = self.value + ' ' * self.tw         # add spaces to fill rest of field
        val = val[self.ofs : self.ofs + self.tw]  # cut value - begin from ofs, limit to tw chars
        ev.driver.puts(ev.x + 1, ev.y, val.encode(self.code))

        # draw arrows if content overflows
        c = ' '
        if self.ofs > 0:
            c = '<'
        ev.driver.putch(ev.x, ev.y, c)

        c = ' '
        if len(self.value[self.ofs:]) > self.tw:
            c = '>'
        ev.driver.putch(ev.x + self.width-1, ev.y, c)

        self.cursor = (1 + self.pos - self.ofs, 0)
        ev.driver.popcolor()

    def on_keypress(self, ev):
        handled = False
        if ev.keyname:
            handled = True
            if ev.keyname == 'left':
                self.move_left()

            elif ev.keyname == 'right':
                self.move_right()

            elif ev.keyname == 'backspace':
                if self.pos > 0:
                    self.move_left()
                    self.del_char()

            elif ev.keyname == 'delete':
                self.del_char()

            else:
                handled = False

        if ev.char:
            self.add_char(ev.char)
            self.move_right()
            handled = True

        self.redraw()

        return handled

    def move_left(self):
        if self.pos - self.ofs > 1 or (self.ofs == 0 and self.pos == 1):
            # move cursor
            self.pos -= 1
        else:
            # move content in field
            if self.ofs > 0:
                self.pos -= 1
                self.ofs -= 1

    def move_right(self):
        if self.pos < len(self.value):
            if self.pos - self.ofs < self.tw - 2 \
            or (self.pos - self.ofs == self.tw - 2 and self.pos == len(self.value)-1):
                # move cursor
                self.pos += 1
            else:
                # move content in field
                self.pos += 1
                self.ofs += 1

    def add_char(self, c):
        self.value = self.value[:self.pos] + c + self.value[self.pos:]

    def del_char(self):
        self.value = self.value[:self.pos] + self.value[self.pos+1:]