tuikit/editbox.py
author Radek Brich <radek.brich@devl.cz>
Wed, 16 Mar 2011 15:19:05 +0100
changeset 3 33ec838dc021
parent 0 a35731b5e31a
child 9 7175ed629a76
permissions -rw-r--r--
Fixed escape sequence handling.

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

from .widget import Widget

class EditBox(Widget):
    def __init__(self, width=20, height=20, text=''):
        Widget.__init__(self, width, height)

        self.xofs = 0
        self.yofs = 0

        # cursor
        self.cline = 0
        self.cpos = 0

        # selection
        self.sline = 0
        self.spos = 0

        self.connect('draw', self.on_draw)
        self.connect('keypress', self.on_keypress)
        self.connect('mousewheel', self.on_mousewheel)

        self.newevent('scroll')
        self.newevent('areasize')

        self.set_text(text)


    def on_draw(self, screen, x, y):
        for j in range(self.height):
            if self.yofs + j >= len(self.lines):
                break
            line = self.lines[self.yofs + j]
            #if len(line) < self.width:
                #line += ' ' * (self.width - len(line))
            #else:
                #line = line[:self.width]
            screen.puts(x, y + j, line)

        screen.showcursor(x + self.get_cpos() - self.xofs, y + self.cline - self.yofs)


    def on_keypress(self, keyname, char):
        if keyname:
            if keyname == 'left':
                self.move_left()

            if keyname == 'right':
                self.move_right()

            if keyname == 'home':
                self.move_home()

            if keyname == 'end':
                self.move_end()

            if keyname == 'up':
                self.move_up()

            if keyname == 'down':
                self.move_down()

            if keyname == 'pageup':
                self.move_pageup()

            if keyname == 'pagedown':
                self.move_pagedown()

            if keyname == 'backspace':
                if self.cline > 0 or self.cpos > 0:
                    self.move_left()
                    self.del_char()

            if keyname == 'delete':
                self.del_char()

            if keyname == 'enter':
                self.add_newline()
                self.move_right()

        if char:
            self.add_char(char)
            self.move_right()

        self.redraw()


    def on_mousewheel(self, ev):
        # up
        if ev.button == 4:
            self.move_up()
        # down
        if ev.button == 5:
            self.move_down()
        self.redraw()


    def set_text(self, text):
        self.lines = text.split('\n')
        self.handle('areasize')


    def get_text(self):
        return '\n'.join(self.lines)


    def get_linelen(self):
        return len(self.lines[self.cline])


    def get_cpos(self):
        if self.cpos > self.get_linelen():
            return self.get_linelen()
        return self.cpos


    def set_yofs(self, yofs):
        if yofs > len(self.lines) - self.height:
            yofs = len(self.lines) - self.height
        if yofs < 0:
            yofs = 0
        self.yofs = yofs
        self.handle('scroll')


    def move_left(self):
        if self.cpos > 0:
            self.cpos = self.get_cpos() - 1
        else:
            if self.move_up():
                self.cpos = self.get_linelen()


    def move_right(self):
        if self.cpos < self.get_linelen():
            self.cpos += 1
        else:
            if self.move_down():
                self.cpos = 0


    def move_home(self):
        self.cpos = 0


    def move_end(self):
        self.cpos = self.get_linelen()


    def move_up(self):
        if self.cline > 0:
            self.cline -= 1
            if self.cline < self.yofs:
                self.set_yofs(self.cline)
            return True
        return False


    def move_down(self):
        if self.cline < len(self.lines) - 1:
            self.cline += 1
            if self.cline > self.yofs + self.height - 1:
                self.set_yofs(self.cline - (self.height - 1))
            return True
        return False


    def move_pageup(self):
        if self.cline >= self.height - 1:
            self.cline -= self.height - 1
            self.set_yofs(self.yofs - (self.height - 1))
        else:
            self.cline = 0
            self.set_yofs(0)


    def move_pagedown(self):
        if self.cline <= len(self.lines) - (self.height - 1):
            self.cline += self.height - 1
            self.set_yofs(self.yofs + (self.height - 1))
        else:
            self.cline = len(self.lines) - 1
            self.set_yofs(self.cline)


    def move_pagefirst(self):
        self.cline = 0
        self.set_yofs(0)


    def move_pagelast(self):
        self.cline = len(self.lines) - 1
        self.set_yofs(self.cline)


    def add_char(self, c):
        ln = self.lines[self.cline]
        cpos = self.get_cpos()
        self.lines[self.cline] = ln[:cpos] + c + ln[cpos:]
        self.cpos = cpos


    def add_newline(self):
        ln = self.lines[self.cline]
        cpos = self.get_cpos()
        self.lines[self.cline] = ln[cpos:]
        self.lines.insert(self.cline, ln[:cpos])
        self.handle('areasize')


    def del_char(self):
        ln = self.lines[self.cline]
        cpos = self.get_cpos()
        if cpos == self.get_linelen():
            if self.cline + 1 < len(self.lines):
                self.lines[self.cline] = self.lines[self.cline] + self.lines[self.cline+1]
                del self.lines[self.cline+1]
                self.handle('areasize')
        else:
            self.lines[self.cline] = ln[:cpos] + ln[cpos+1:]