Documentation, fix names of focus methods.
authorRadek Brich <radek.brich@devl.cz>
Mon, 17 Dec 2012 23:19:58 +0100
changeset 38 c6e170452c7f
parent 37 54dd866b8951
child 39 5e5deb1d3945
Documentation, fix names of focus methods.
docs/conf.py
docs/events.rst
docs/index.rst
docs/treeview.rst
docs/widget.rst
tests/test_treeview.py
tuikit/button.py
tuikit/container.py
tuikit/menu.py
tuikit/menubar.py
tuikit/treeview.py
tuikit/widget.py
--- a/docs/conf.py	Mon Dec 17 21:07:59 2012 +0100
+++ b/docs/conf.py	Mon Dec 17 23:19:58 2012 +0100
@@ -38,7 +38,7 @@
 
 # General information about the project.
 project = u'Tuikit'
-copyright = u'2011, Radek Brich'
+copyright = u'2011-2012, Radek Brich'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
--- a/docs/events.rst	Mon Dec 17 21:07:59 2012 +0100
+++ b/docs/events.rst	Mon Dec 17 23:19:58 2012 +0100
@@ -9,8 +9,8 @@
 Normal widgets should implement only on_draw() method, which is called from draw().
 
 
-Keypress event, focus
----------------------
+Keypress event
+--------------
 
 Keyboard events go in top down order, from top window to focused widget in each level. When implementing on_keypress method,
 add super().on_keypress(). Anything before that will be executed in top down walk, anything after in bottom up. Return True if you want to stop
@@ -24,18 +24,26 @@
   3       5          container
   4       4            edit box
 
-Each container maintains its focus child and allows to cycle focus between children (See Container.focusnext). Focus cycling works throughout
+Focus
+-----
+
+Basics:
+ * Only one node in hierarchy can have focus.
+ * All parent containers have focus, so they can relay events to focused child.
+ * Top container has always focus.
+
+Each container maintains its focus child and allows to cycle focus between children (See Container.focus_next). Focus cycling works throughout
 container levels - if focus was on last child and would go to the first, 'tab' key is not handled thus allowing parent level to cycle focus.
 
 When focus changes, two events are generated: focus on new widget, unfocus on previous one.
 Mousedown causes focus change when allowed (Widget.allow_focus).
 
- * tab key - change focus to next widget
- * shift-tab - previous widget (FIXME: not implemented)
+ * Use grab_focus() on widget to make it receive keyboard events. This will clean old focus and set focus to this child.
+ * Global shortcuts can be handled in keypress event from top widget. All keyboard events go through there.
+ * Tab key changes focus to next widget. Shift-tab changes back to previous widget (FIXME: not implemented).
+ * Hide on focused widget causes focus change like if tab key was pressed.
 
-Hide on focused widget causes focus change like if tab key was pressed.
-
-See Container.trapfocus, Widget.canfocus(), Widget.hasfocus(), Widget.setfocus() for more information.
+See Container.trap_focus, Widget.can_focus(), Widget.has_focus(), Widget.set_focus() for more information.
 
 
 Other event propagation
--- a/docs/index.rst	Mon Dec 17 21:07:59 2012 +0100
+++ b/docs/index.rst	Mon Dec 17 23:19:58 2012 +0100
@@ -16,7 +16,6 @@
    events
    redraw
    colors
-   tableview
 
 .. inheritance-diagram:: tuikit.application
                          tuikit.emitter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/treeview.rst	Mon Dec 17 23:19:58 2012 +0100
@@ -0,0 +1,23 @@
+TreeView
+========
+
+.. toctree::
+   :maxdepth: 3
+   :titlesonly:
+
+.. automodule:: tuikit.treeview
+   :members:
+   :show-inheritance:
+
+
+Path
+----
+The path may be string or list. Components are names or indexes.
+String path uses slash char as separator, names as components.
+
+Examples:
+ * '/'
+ * '/a/b/c'
+ * ['a', 'b', 'c']
+ * [0, 3, 1]
+
--- a/docs/widget.rst	Mon Dec 17 21:07:59 2012 +0100
+++ b/docs/widget.rst	Mon Dec 17 23:19:58 2012 +0100
@@ -7,6 +7,8 @@
 
    container
    button
+   treeview
+   tableview
 
 .. autoclass:: tuikit.widget.Widget
    :members:
--- a/tests/test_treeview.py	Mon Dec 17 21:07:59 2012 +0100
+++ b/tests/test_treeview.py	Mon Dec 17 23:19:58 2012 +0100
@@ -24,7 +24,7 @@
         """
         self.model = TreeModel()
         self.model.add('/',  ['a', 'b'])
-        self.model.add('/a', [TreeNode('c'), TreeNode('d')])
+        self.model.add(['a'], [TreeNode('c'), TreeNode('d')])
         self.model.add((0,1), ['e', TreeNode('f')])
         self.model.add([0,1,0], 'g')
         self.model.add('/a/d/f', TreeNode('h'))
--- a/tuikit/button.py	Mon Dec 17 21:07:59 2012 +0100
+++ b/tuikit/button.py	Mon Dec 17 23:19:58 2012 +0100
@@ -79,7 +79,7 @@
 
 
     def getcolor(self):
-        if self.highlight or self.hasfocus():
+        if self.highlight or self.has_focus():
             return self.bghi
         return self.bg
 
--- a/tuikit/container.py	Mon Dec 17 21:07:59 2012 +0100
+++ b/tuikit/container.py	Mon Dec 17 23:19:58 2012 +0100
@@ -33,7 +33,7 @@
 
         self.colorprefix = None
 
-        self.trapfocus = False  # if True, tab cycles inside container
+        self.trap_focus = False  # if True, tab cycles inside container
 
 
     def add(self, widget, **kw):
@@ -42,7 +42,7 @@
         widget.parent = self
         widget.settop(self.top)
         widget.hints.update(kw)
-        if self.focuschild is None and widget.canfocus():
+        if self.focuschild is None and widget.can_focus():
             self.focuschild = widget
 
 
@@ -60,7 +60,24 @@
             child.settop(top)
 
 
-    def focusnext(self):
+    def focus_next(self):
+        """Focus next child.
+
+        Sets focus to next child, if there is one
+        which can be focused. Cycles from last child
+        to first when needed. Return value depends on
+        this cycling:
+
+         * False means there wasn't any child to focus
+           before end of list, so first child was focused.
+
+         * True when focus is set to next child in normal
+           way or when self.trap_focus is set.
+
+        Return value is supposed to be returned from keypress
+        event - in that case, True stops event propagation.
+
+        """
         idx_current = self.children.index(self.focuschild)
         idx_new = idx_current + 1
         cycled = False
@@ -68,9 +85,9 @@
             if idx_new >= len(self.children):
                 idx_new = 0
                 cycled = True
-            if self.children[idx_new].canfocus():
-                self.children[idx_new].setfocus()
-                return self.trapfocus or not cycled
+            if self.children[idx_new].can_focus():
+                self.children[idx_new].set_focus()
+                return self.trap_focus or not cycled
             idx_new += 1
 
     def on_keypress(self, keyname, char):
@@ -80,7 +97,7 @@
             if handled:
                 return True
         if keyname == 'tab':
-            return self.focusnext()
+            return self.focus_next()
 
     def on_resize(self):
         super().on_resize()
--- a/tuikit/menu.py	Mon Dec 17 21:07:59 2012 +0100
+++ b/tuikit/menu.py	Mon Dec 17 23:19:58 2012 +0100
@@ -93,8 +93,7 @@
                 self.emit('activate', self.selected[1])
             elif isinstance(self.selected[1], Widget):
                 self.selected[1].show()
-                self.selected[1].setfocus()
+                self.selected[1].set_focus()
             else:
-                self.menubar.resetfocus()
                 self.selected[1]()
 
--- a/tuikit/menubar.py	Mon Dec 17 21:07:59 2012 +0100
+++ b/tuikit/menubar.py	Mon Dec 17 23:19:58 2012 +0100
@@ -94,7 +94,7 @@
 
 
     def on_submenu_focus(self):
-        self.setfocus()
+        self.set_focus()
 
 
     def select(self, item):
--- a/tuikit/treeview.py	Mon Dec 17 21:07:59 2012 +0100
+++ b/tuikit/treeview.py	Mon Dec 17 23:19:58 2012 +0100
@@ -7,6 +7,12 @@
 
 
 class TreeIter:
+    """Iterates nodes under root in depth-first order.
+
+    This is useful for displaying the tree.
+
+    """
+
     def __init__(self, root, collapsed=[]):
         self._node = root
         self._index = 0
@@ -42,6 +48,16 @@
 
 
 class TreeNode:
+    """Node of tree.
+
+    Maintains its parent and children.
+
+    Attributes:
+     * name - used for searching
+     * title - this is displayed on screen
+
+    """
+
     def __init__(self, name, title=None, parent=None, model=None):
         self.model = model
         self.children = []
@@ -60,12 +76,14 @@
 
     @property
     def path(self):
+        """Path of this node in model."""
         if self.parent:
             return self.parent.path + '/' + self.name
         else:
             return self.name
 
     def add(self, node):
+        """Add child and connect it to self."""
         node.parent = self
         node.model = self.model
         self.children.append(node)
@@ -73,6 +91,13 @@
 
 
 class TreeModel(Emitter):
+    """Tree data model.
+
+    Tree model stores all nodes of tree but knows nothing about displaying them.
+    Same model can be used in many views.
+
+    """
+
     def __init__(self):
         self.add_events('node_added')  # node added, arg is the node
         self.root = TreeNode('', model=self)
@@ -144,6 +169,8 @@
 
 
 class TreeView(Widget):
+    """Tree view displays data from tree model."""
+
     def __init__(self, model=None, width=20, height=20):
         Widget.__init__(self, width, height)
 
--- a/tuikit/widget.py	Mon Dec 17 21:07:59 2012 +0100
+++ b/tuikit/widget.py	Mon Dec 17 23:19:58 2012 +0100
@@ -127,7 +127,7 @@
 
         self.emit('draw', driver, x, y)
 
-        if self.hasfocus():
+        if self.has_focus():
             if self.cursor:
                 cx, cy = self.cursor
                 driver.showcursor(x + cx, y + cy)
@@ -136,25 +136,36 @@
 
     def on_mousedown(self, ev):
         super().on_mousedown(ev)
-        self.setfocus()
+        self.set_focus()
 
 
     ### focus
 
 
-    def canfocus(self):
+    def can_focus(self):
         return not self.hidden and self.allow_focus
 
 
-    def hasfocus(self):
+    def has_focus(self):
         if self.parent is None:
             return True
-        return (self.parent.hasfocus() \
+        return (self.parent.has_focus() \
             and self.parent.focuschild == self)
 
 
-    def setfocus(self):
-        if self.hasfocus() or not self.canfocus():
+    def set_focus(self):
+        """Focus the widget.
+
+        This changes focus state of parent widget,
+        but it does not check if parent widget actually
+        has focus. It still works if it has not,
+        but keyboard events will go to really focused widget,
+        not this one.
+
+        See also grab_focus() which cares about parents.
+
+        """
+        if self.has_focus() or not self.can_focus():
             return
         if self.parent.focuschild:
             self.parent.focuschild.emit('unfocus', self)
@@ -162,6 +173,13 @@
         self.emit('focus')
 
 
+    def grab_focus(self):
+        """Focus the widget and its parents."""
+        self.set_focus()
+        if self.parent and not self.parent.has_focus():
+            self.parent.grab_focus()
+
+
     ###
 
     def hint(self, key):
@@ -194,8 +212,8 @@
     def hide(self):
         '''Hide widget. Convenience method.'''
         self.hidden = True
-        if self.hasfocus():
-            self.parent.focusnext()
+        if self.has_focus():
+            self.parent.focus_next()
         self.redraw()