Update demo_input, demo_editor. Update ScrollView: show/hide scrollbars as needed on child size requests.
authorRadek Brich <radek.brich@devl.cz>
Sat, 02 Feb 2013 12:54:27 +0100
changeset 76 fa5301e58eca
parent 75 2430c643838a
child 77 fc1989059e19
Update demo_input, demo_editor. Update ScrollView: show/hide scrollbars as needed on child size requests.
demo_anchorlayout.py
demo_editor.py
demo_input.py
tuikit/editbox.py
tuikit/layout.py
tuikit/scrollbar.py
tuikit/scrollview.py
tuikit/widget.py
tuikit/window.py
--- a/demo_anchorlayout.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/demo_anchorlayout.py	Sat Feb 02 12:54:27 2013 +0100
@@ -26,17 +26,17 @@
         self.top.add(win, halign='left', valign='top')
         self.win = win
 
-        button_valign = Button('valign: ' + self.win.hints['valign'].selected)
+        button_valign = Button('valign: ' + self.win.hint_value('valign'))
         button_valign.name = 'button_valign'
         button_valign.add_handler('click', self.on_button_align_click)
         win.add(button_valign, halign='center', margin=Borders(t=2))
 
-        button_halign = Button('halign: ' + self.win.hints['halign'].selected)
+        button_halign = Button('halign: ' + self.win.hint_value('halign'))
         button_halign.name = 'button_halign'
         button_halign.add_handler('click', self.on_button_align_click)
         win.add(button_halign, halign='center', margin=Borders(t=4))
 
-        label_margin = Label(str(self.win.hints['margin']))
+        label_margin = Label(str(self.win.hint_value('margin')))
         label_margin.name = 'label_margin'
         label_margin.add_handler('draw', self.on_label_margin_draw)
         win.add(label_margin, halign='center', margin=Borders(t=6))
@@ -48,14 +48,14 @@
 
     def on_button_align_click(self, ev):
         align_type = ev.originator.label.split(':', 1)[0]
-        align = self.win.hints[align_type]
+        align = self.win.get_hint(align_type)
         align.select_next()
         ev.originator.label = '%s: %s' % (align_type, align.selected)
         self.top.emit('resize')
         return True
 
     def on_label_margin_draw(self, ev):
-        ev.originator.label = str(self.win.hints['margin'])
+        ev.originator.label = str(self.win.hint_value('margin'))
 
     def on_label_size_draw(self, ev):
         ev.originator.label = str(self.win.sizereq)
--- a/demo_editor.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/demo_editor.py	Sat Feb 02 12:54:27 2013 +0100
@@ -7,7 +7,8 @@
 import os
 
 from tuikit.application import Application
-from tuikit.textedit import TextEdit
+from tuikit.scrollview import ScrollView
+from tuikit.editbox import EditBox
 
 
 class MyApplication(Application):
@@ -16,8 +17,12 @@
         self.top.add_handler('keypress', self.on_top_keypress)
 
         t = open('tuikit/widget.py').read()
-        textedit = TextEdit(t)
-        self.top.add(textedit, halign='fill', valign='fill')
+        editbox = EditBox(t)
+
+        scroll = ScrollView()
+        scroll.add(editbox)
+
+        self.top.add(scroll, halign='fill', valign='fill')
 
     def on_top_keypress(self, ev):
         if ev.keyname == 'escape':
--- a/demo_input.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/demo_input.py	Sat Feb 02 12:54:27 2013 +0100
@@ -4,7 +4,9 @@
 import locale
 locale.setlocale(locale.LC_ALL, '')
 
-from tuikit import Application, TextEdit
+from tuikit.application import Application
+from tuikit.scrollview import ScrollView
+from tuikit.editbox import EditBox
 
 
 class MyApplication(Application):
@@ -12,23 +14,23 @@
         Application.__init__(self)
 
         self.text = ''
-        self.textedit = TextEdit(self.text)
-        self.top.add(self.textedit, halign='fill', valign='fill')
+        self.editbox = EditBox(self.text)
+        scroll = ScrollView()
+        scroll.add(self.editbox)
+        self.top.add(scroll, halign='fill', valign='fill')
 
-        editbox = self.textedit.editbox
-        editbox.add_handler('keypress', self.on_any_input)
-        editbox.add_handler('mousedown', self.on_any_input)
-        editbox.add_handler('mouseup', self.on_any_input)
-        editbox.add_handler('mousewheel', self.on_any_input)
-        editbox.add_handler('mousemove', self.on_any_input)
-        editbox.add_handler('mousehover', self.on_any_input)
+        self.editbox.add_handler('keypress', self.on_any_input)
+        self.editbox.add_handler('mousedown', self.on_any_input)
+        self.editbox.add_handler('mouseup', self.on_any_input)
+        self.editbox.add_handler('mousewheel', self.on_any_input)
+        self.editbox.add_handler('mousemove', self.on_any_input)
+        self.editbox.add_handler('mousehover', self.on_any_input)
 
     def on_any_input(self, ev):
-        if ev.event_name == 'keypress' and ev.char == 'q':
+        if ev.event_name == 'keypress' and ev.keyname == 'escape':
             self.terminate()
-        self.text += ''.join((ev.event_name.ljust(10), ' : ', repr(ev), '\n'))
-        self.textedit.settext(self.text)
-        self.textedit.scrolltoend()
+        line = ''.join((ev.event_name.ljust(10), ' : ', repr(ev)))
+        self.editbox.add_line(line)
         return True
 
 
--- a/tuikit/editbox.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/tuikit/editbox.py	Sat Feb 02 12:54:27 2013 +0100
@@ -168,6 +168,17 @@
         if move:
             self.move_right()
 
+    def add_line(self, text):
+        ln = self.cur_line
+        sx = self._spot.x
+        self.cur_line = ln[sx:]
+        self.lines.insert(self._spot.y, ln[:sx] + text)
+        self.cursor_column = 0
+        self._spot.x = 0
+        self._spot.y += 1
+        w = max(self._default_size.w, len(ln[:sx] + text))
+        self._default_size.update(w=w, h=len(self.lines))
+
     def backspace(self):
         if self._spot.y > 0 or self._spot.x > 0:
             self.move_left()
--- a/tuikit/layout.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/tuikit/layout.py	Sat Feb 02 12:54:27 2013 +0100
@@ -17,9 +17,11 @@
 class Layout(Container):
     def add(self, widget, **kwargs):
         Container.add(self, widget, **kwargs)
-        widget.add_handler('sizereq', self.on_child_sizereq)
+        widget.add_handler('sizereq', self._on_child_size_change)
+        widget.add_handler('show', self._on_child_size_change)
+        widget.add_handler('hide', self._on_child_size_change)
 
-    def on_child_sizereq(self, ev):
+    def _on_child_size_change(self, ev):
         self.emit('resize')
 
     def _get_children(self):
--- a/tuikit/scrollbar.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/tuikit/scrollbar.py	Sat Feb 02 12:54:27 2013 +0100
@@ -37,6 +37,8 @@
 
     @scroll_max.setter
     def scroll_max(self, value):
+        if value < 0:
+            value = 0
         self._scroll_max = value
         if self._scroll_pos > value:
             self._scroll_pos = value
--- a/tuikit/scrollview.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/tuikit/scrollview.py	Sat Feb 02 12:54:27 2013 +0100
@@ -71,23 +71,30 @@
         max_width = 0
         max_height = 0
         for child in self._inner.children:
-            child_width = child.x - self._inner.offset.x + child.sizereq.w
+            posx, posy = child.hint_value('position')
+            child_width = posx + child.sizereq.w
             if child_width > max_width:
                 max_width = child_width
-            child_height = child.y - self._inner.offset.y + child.sizereq.h
+            child_height = posy + child.sizereq.h
             if child_height > max_height:
                 max_height = child_height
         max_width += 1
-        if max_width < self._inner.width:
+        self.hscroll.scroll_max = max_width - self._inner.width
+        self.vscroll.scroll_max = max_height - self._inner.height
+        hscroll_hide = max_width < self._inner.width
+        vscroll_hide = max_height < self._inner.height
+        self._toggle_scrollers(hscroll_hide, vscroll_hide)
+
+    def _toggle_scrollers(self, hscroll_hide, vscroll_hide):
+        if hscroll_hide:
             self.hscroll.hide()
         else:
-            self.hscroll.scroll_max = max_width - self._inner.width
             self.hscroll.show()
-        if max_height < self._inner.height:
+        if vscroll_hide:
             self.vscroll.hide()
         else:
-            self.vscroll.scroll_max = max_height - self._inner.height
             self.vscroll.show()
+        self._inner.need_resize()
 
 
 class ScrollView(OffsetView, Scrolling):
@@ -106,3 +113,11 @@
         OffsetView.add(self, widget, **kwargs)
         self._connect_child(widget)
 
+    def _toggle_scrollers(self, hscroll_hide, vscroll_hide):
+        bpad = int(not hscroll_hide)
+        self.vscroll.update_hint('margin', b=bpad)
+        rpad = int(not vscroll_hide)
+        self.hscroll.update_hint('margin', r=rpad)
+        self._inner.update_hint('margin', b=bpad, r=rpad)
+        Scrolling._toggle_scrollers(self, hscroll_hide, vscroll_hide)
+
--- a/tuikit/widget.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/tuikit/widget.py	Sat Feb 02 12:54:27 2013 +0100
@@ -54,7 +54,7 @@
         self._hints = {}
 
         #: Hidden widget does not affect layout.
-        self.hidden = False
+        self._hidden = False
 
         #: Cursor is position where text input will occur,
         #: i.e. classic blinking cursor in console.
@@ -65,8 +65,9 @@
         self._spot = Coords()
         self._spot.add_handler('change', lambda ev: self.emit('spotmove'))
 
-        # redraw request
-        self._redraw = True
+        # pending resize/draw request
+        self._need_resize = True
+        self._need_draw = True
 
         # event handlers
         self.add_events(
@@ -82,7 +83,9 @@
             'scrollreq', GenericEvent,
             'spotmove', Event,
             'focus', FocusEvent,
-            'unfocus', FocusEvent)
+            'unfocus', FocusEvent,
+            'show', Event,
+            'hide', Event)
 
     ### placing and size
 
@@ -197,10 +200,16 @@
         except AttributeError:
             return self._hints[hint_name]
 
+    def get_hint(self, hint_name):
+        return self._hints[hint_name]
+
     ### events
 
-    def redraw(self, parent=True):
-        self._redraw = True
+    def need_resize(self):
+        self._need_resize = True
+
+    def redraw(self, parent=False):
+        self._need_draw = True
         if parent and self.parent:
             self.parent._redraw = True
 
@@ -295,17 +304,23 @@
             return self.y + y, self.x + x
         return self.y, self.x
 
+    @property
+    def hidden(self):
+        return self._hidden
 
     def hide(self):
         '''Hide widget. Convenience method.'''
-        self.hidden = True
-        self.redraw()
-
+        if not self._hidden:
+            self._hidden = True
+            self.emit('hide')
+            self.redraw()
 
     def show(self):
         '''Show widget. Convenience method.'''
-        self.hidden = False
-        self.redraw()
+        if self._hidden:
+            self._hidden = False
+            self.emit('show')
+            self.redraw()
 
     def bring_up(self):
         if self.parent:
--- a/tuikit/window.py	Fri Feb 01 09:34:15 2013 +0100
+++ b/tuikit/window.py	Sat Feb 02 12:54:27 2013 +0100
@@ -108,9 +108,9 @@
                         self.sizereq.h + ev.rely)
             # AnchorLayout, right/bottom align
             # also move the window so that it visualy stays in place
-            if 'halign' in self.hints and self.hints['halign'].selected == 'right':
+            if 'halign' in self._hints and self.hint_value('halign') == 'right':
                 self.move(x = self.x + ev.relx)
-            if 'valign' in self.hints and self.hints['valign'].selected == 'bottom':
+            if 'valign' in self._hints and self.hint_value('valign') == 'bottom':
                 self.move(y = self.y + ev.rely)
         elif self._moving:
             self.move(self.x + ev.relx,