tuikit/widgets/textfield.py
author Radek Brich <radek.brich@devl.cz>
Wed, 03 Sep 2014 21:56:20 +0200
changeset 113 6796adfdc7eb
parent 112 ce2e67e7bbb8
parent 104 742e504ec053
child 119 dd91747504dd
permissions -rw-r--r--
Merge. Due to my schizophrenia, I've accidentally forked my own code. The other set of changes were found in another computer.

import locale

from tuikit.core.widget import Widget


class TextField(Widget):

    def __init__(self, value=''):
        Widget.__init__(self)
        self.allow_focus = True
        self.sizereq.update(10, 1)

        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.curspos = 0  # position of cursor in value
        self.ofs = 0      # position of value beginning on screen

        self._cursor_visible = True
        self.move_end()

    def resize(self, w, h):
        self.tw = self.width - 2
        if self.curspos >= self.tw:
            self.ofs = self.curspos - self.tw

    def draw(self, buffer):
        color = self.theme.active if self.has_focus() else self.theme.normal
        with buffer.attr(color):
            # 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
            buffer.puts(val.encode(self.code), 1)

            # draw arrows if content overflows
            c = ' '
            if self.ofs > 0:
                c = '<'
            buffer.putch(c)

            c = ' '
            if len(self.value[self.ofs:]) > self.tw:
                c = '>'
            buffer.putch(c, self.width-1, 0)

            self._cursor.update(1 + self.curspos - self.ofs, 0)

    def keypress_event(self, ev):
        map_keyname_to_func = {
            'left':       self.move_left,
            'right':      self.move_right,
            'home':       self.move_home,
            'end':        self.move_end,
            'backspace':  self.move_left_and_del,
            'delete':     self.del_char,
        }
        consumed = False
        if ev.keyname in map_keyname_to_func:
            map_keyname_to_func[ev.keyname]()
            consumed = True
        if not ev.keyname and ev.char:
            self.add_char(ev.char)
            self.move_right()
            consumed = True
        if consumed:
            #self.redraw()
            return True
        Widget.keypress_event(self, ev)

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

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

    def move_home(self):
        self.curspos = 0
        self.ofs = 0

    def move_end(self):
        self.curspos = len(self.value)
        if self.curspos >= self.tw:
            self.ofs = self.curspos - self.tw

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

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

    def move_left_and_del(self):
        if self.curspos > 0:
            self.move_left()
            self.del_char()