# HG changeset patch # User Radek Brich # Date 1355782798 -3600 # Node ID c6e170452c7f29f4728ad1713795840f7da66ef9 # Parent 54dd866b8951c4e4dec38b63e3641291db058add Documentation, fix names of focus methods. diff -r 54dd866b8951 -r c6e170452c7f docs/conf.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 diff -r 54dd866b8951 -r c6e170452c7f docs/events.rst --- 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 diff -r 54dd866b8951 -r c6e170452c7f docs/index.rst --- 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 diff -r 54dd866b8951 -r c6e170452c7f docs/treeview.rst --- /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] + diff -r 54dd866b8951 -r c6e170452c7f docs/widget.rst --- 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: diff -r 54dd866b8951 -r c6e170452c7f tests/test_treeview.py --- 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')) diff -r 54dd866b8951 -r c6e170452c7f tuikit/button.py --- 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 diff -r 54dd866b8951 -r c6e170452c7f tuikit/container.py --- 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() diff -r 54dd866b8951 -r c6e170452c7f tuikit/menu.py --- 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]() diff -r 54dd866b8951 -r c6e170452c7f tuikit/menubar.py --- 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): diff -r 54dd866b8951 -r c6e170452c7f tuikit/treeview.py --- 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) diff -r 54dd866b8951 -r c6e170452c7f tuikit/widget.py --- 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()