tuikit/widgets/textfield.py
author Radek Brich <radek.brich@devl.cz>
Mon, 01 Sep 2014 08:45:51 +0200
changeset 104 742e504ec053
parent 103 49f212aa0228
child 113 6796adfdc7eb
permissions -rw-r--r--
Update TextBox: Replace "spot" with "cursor".
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     1
import locale
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     2
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
     3
from tuikit.core.widget import Widget
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     4
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     5
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
     6
class TextField(Widget):
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
     7
62
2f61931520c9 Rework layouts: Layout is now normal Container which places its children upon resize event.
Radek Brich <radek.brich@devl.cz>
parents: 45
diff changeset
     8
    def __init__(self, value=''):
2f61931520c9 Rework layouts: Layout is now normal Container which places its children upon resize event.
Radek Brich <radek.brich@devl.cz>
parents: 45
diff changeset
     9
        Widget.__init__(self)
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    10
        self.sizereq.update(10, 1)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    11
34
e3beacd5e536 Update event propagation, keypress event, focusing.
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    12
        self.allow_focus = True
e3beacd5e536 Update event propagation, keypress event, focusing.
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    13
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    14
        self.code = locale.getpreferredencoding()
10
ec1d47e6fe09 Use isinstance instead of type.
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
    15
        if not isinstance(value, str):
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    16
            value = str(value, self.code)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    17
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    18
        self.value = value
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    19
        self.maxlen = None   # unlimited
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    20
8
fcaabd817774 Update editfield - place cursor to end initially.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    21
        self.tw = 0       # real width of text field (minus space for arrows)
103
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    22
        self.curspos = 0  # position of cursor in value
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    23
        self.ofs = 0      # position of value beginning on screen
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    24
103
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    25
        self.move_end()
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    26
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    27
    def resize(self, w, h):
8
fcaabd817774 Update editfield - place cursor to end initially.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    28
        self.tw = self.width - 2
103
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    29
        if self.curspos >= self.tw:
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    30
            self.ofs = self.curspos - self.tw
5
ae128c885d0f New GridLayout. Change cursor behavior (hide on unfocus event). Change resize event to propagate through containers. Change container clipping - allowlayout=false children are clipped without borders. More Widget doc.
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    31
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    32
    def set_theme(self, theme):
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    33
        self.color = theme.normal
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    34
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    35
    def draw(self, buffer):
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    36
        with buffer.attr(self.color):
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    37
            # draw value
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    38
            val = self.value + ' ' * self.tw         # add spaces to fill rest of field
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    39
            val = val[self.ofs : self.ofs + self.tw]  # cut value - begin from ofs, limit to tw chars
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    40
            buffer.puts(val.encode(self.code), 1)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    41
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    42
            # draw arrows if content overflows
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    43
            c = ' '
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    44
            if self.ofs > 0:
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    45
                c = '<'
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    46
            buffer.putch(c)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    47
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    48
            c = ' '
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    49
            if len(self.value[self.ofs:]) > self.tw:
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    50
                c = '>'
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    51
            buffer.putch(c, self.width-1, 0)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    52
104
742e504ec053 Update TextBox: Replace "spot" with "cursor".
Radek Brich <radek.brich@devl.cz>
parents: 103
diff changeset
    53
            self._cursor.update(1 + self.curspos - self.ofs, 0)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    54
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    55
    def keypress(self, keyname, char, mod=0):
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    56
        Widget.keypress(self, keyname, char, mod)
103
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    57
        map_keyname_to_func = {
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    58
            'left':       self.move_left,
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    59
            'right':      self.move_right,
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    60
            'home':       self.move_home,
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    61
            'end':        self.move_end,
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    62
            'backspace':  self.move_left_and_del,
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    63
            'delete':     self.del_char,
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    64
        }
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    65
        accepted = False
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    66
        if keyname in map_keyname_to_func:
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    67
            map_keyname_to_func[keyname]()
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    68
            accepted = True
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    69
        if char:
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    70
            self.add_char(char)
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    71
            self.move_right()
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    72
            accepted = True
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    73
        #if accepted:
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    74
            #self.redraw()
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    75
        return accepted
9
7175ed629a76 Added ComboBox, HorizontalLayout, TreeNode, TreeModel, TreeView. Widget is now descendant of EventSource. Improved color management (color prefixes).
Radek Brich <radek.brich@devl.cz>
parents: 8
diff changeset
    76
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    77
    def move_left(self):
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    78
        if self.curspos - self.ofs > 1 or (self.ofs == 0 and self.curspos == 1):
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    79
            # move cursor
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    80
            self.curspos -= 1
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    81
        else:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    82
            # move content in field
8
fcaabd817774 Update editfield - place cursor to end initially.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    83
            if self.ofs > 0:
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    84
                self.curspos -= 1
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    85
                self.ofs -= 1
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    86
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    87
    def move_right(self):
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    88
        if self.curspos < len(self.value):
103
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    89
            if self.curspos - self.ofs < self.tw - 1 \
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    90
            or (self.curspos - self.ofs == self.tw - 1 and self.curspos == len(self.value)-1):
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    91
                # move cursor
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    92
                self.curspos += 1
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    93
            else:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    94
                # move content in field
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
    95
                self.curspos += 1
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    96
                self.ofs += 1
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    97
103
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    98
    def move_home(self):
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    99
        self.curspos = 0
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   100
        self.ofs = 0
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   101
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   102
    def move_end(self):
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   103
        self.curspos = len(self.value)
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   104
        if self.curspos >= self.tw:
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   105
            self.ofs = self.curspos - self.tw
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   106
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   107
    def add_char(self, c):
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
   108
        self.value = self.value[:self.curspos] + c + self.value[self.curspos:]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   109
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   110
    def del_char(self):
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 62
diff changeset
   111
        self.value = self.value[:self.curspos] + self.value[self.curspos+1:]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   112
103
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   113
    def move_left_and_del(self):
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   114
        if self.curspos > 0:
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   115
            self.move_left()
49f212aa0228 Update TextField: Handle home, end keys.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   116
            self.del_char()