# HG changeset patch # User Radek Brich # Date 1297982105 -3600 # Node ID 69318aba22bfcbcd3a53efdfcf413353b1249d4a # Parent a35731b5e31a59c1d1192e0fc9b022b2128f43f9 Menu development. New focus. Easier imports from tuikit package. diff -r a35731b5e31a -r 69318aba22bf docs/focus.rst --- a/docs/focus.rst Wed Feb 16 23:51:30 2011 +0100 +++ b/docs/focus.rst Thu Feb 17 23:35:05 2011 +0100 @@ -1,14 +1,16 @@ Focus ===== -Only one non-container widget can have focus at the time. -All parent containers also have focus. +Only one widget can have focus at the time. +Top widget has link to currently focused widget in 'focuswidget'. Events emitted on change: focus, unfocus -mousedown - focus widget under mouse or its parent if canfocus() == false +mousedown - focus widget under mouse -tab - focus next child in container +tab - focus next child in container (depends on canfocus()) shift-tab - previous child hide() -> unfocus + +tab/shift-tab into / out off containers? diff -r a35731b5e31a -r 69318aba22bf example.py --- a/example.py Wed Feb 16 23:51:30 2011 +0100 +++ b/example.py Thu Feb 17 23:35:05 2011 +0100 @@ -4,17 +4,7 @@ import locale locale.setlocale(locale.LC_ALL, '') -import os - -from tuikit.application import Application -from tuikit.editfield import EditField -from tuikit.window import Window -from tuikit.button import Button -from tuikit.scrollbar import VScrollbar -from tuikit.textedit import TextEdit -from tuikit.menubar import MenuBar -from tuikit.menu import Menu -from tuikit.layout import VerticalLayout +from tuikit import * class MyApplication(Application): @@ -25,34 +15,39 @@ menubar = MenuBar() self.top.add(menubar) - filemenu = Menu(['New', '-', 'Open', 'Save', '-', 'Quit']) + win = Window() + self.top.add(win) + win.x = 10 + win.y = 5 + win.allowlayout = False + + + filemenu = Menu([ + ('New', None), + None, + ('Open', None), + ('Save', None), + None, + ('Quit', self.terminate), + ]) self.top.add(filemenu) - filemenu.allowlayout = False - filemenu.hidden = True - editmenu = Menu(['Copy', 'Paste']) + editmenu = Menu([('Copy', None), ('Paste', None)]) + helpmenu = Menu([('About', None)]) + self.top.add(editmenu) - editmenu.allowlayout = False - editmenu.hidden = True - - helpmenu = Menu(['About']) self.top.add(helpmenu) - helpmenu.allowlayout = False - helpmenu.hidden = True menubar.setitems([ ('File', filemenu), ('Edit', editmenu), - ('Help', helpmenu) + ('Help', helpmenu), ]) vert = VerticalLayout() self.top.layout(vert) - #win = Window() - #self.top.add(win) - #button = Button('click!') #win.add(button) #button.x = 10 diff -r a35731b5e31a -r 69318aba22bf tuikit/__init__.py --- a/tuikit/__init__.py Wed Feb 16 23:51:30 2011 +0100 +++ b/tuikit/__init__.py Thu Feb 17 23:35:05 2011 +0100 @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- + +from tuikit.application import Application +from tuikit.button import Button +from tuikit.common import Rect +from tuikit.container import Container +from tuikit.editbox import EditBox +from tuikit.editfield import EditField +from tuikit.layout import VerticalLayout +from tuikit.menu import Menu +from tuikit.menubar import MenuBar +from tuikit.scrollbar import VScrollbar +from tuikit.textedit import TextEdit +from tuikit.widget import Widget +from tuikit.window import Window diff -r a35731b5e31a -r 69318aba22bf tuikit/application.py --- a/tuikit/application.py Wed Feb 16 23:51:30 2011 +0100 +++ b/tuikit/application.py Thu Feb 17 23:35:05 2011 +0100 @@ -14,6 +14,8 @@ def __init__(self): Container.__init__(self) + self.focuswidget = None + self.top = self self.timeout = [] @@ -21,6 +23,11 @@ self.connect('draw', self.on_draw) + def keypress(self, keyname, char): + if self.focuswidget and self.focuswidget != self: + self.focuswidget.emit('keypress', keyname, char) + self.handle('keypress', keyname, char) + def on_draw(self, screen, x, y): screen.erase() @@ -87,7 +94,6 @@ self.screen = BackendCurses(screen) self.top.width, self.top.height = self.screen.width, self.screen.height self.top.emit('resize') - self.top.setfocus() while True: self.top.draw(self.screen) diff -r a35731b5e31a -r 69318aba22bf tuikit/container.py --- a/tuikit/container.py Wed Feb 16 23:51:30 2011 +0100 +++ b/tuikit/container.py Thu Feb 17 23:35:05 2011 +0100 @@ -8,7 +8,6 @@ Widget.__init__(self, width, height) self.children = [] - self.focuschild = None self.mousechild = None self.borders = (0, 0, 0, 0) # left, top, right, bottom @@ -34,34 +33,6 @@ child.settop(top) - ### focus - - - def canfocus(self): - return True - - - def setfocus(self): - self.focus = True - if self.focuschild is None and len(self.children) > 0: - for child in self.children: - if self.focuschild is None: - if child.canfocus(): - self.focuschild = child - child.setfocus() - else: - if child.focus: - child.unfocus() - - def unfocus(self): - self.focus = False - for child in self.children: - child.unfocus() - - - ### - - def draw(self, screen, x=0, y=0): #if self._redraw: #self.fill(screen, self.y, self.x, self.height, self.width) @@ -80,14 +51,6 @@ #self._redraw = False - def keypress(self, keyname, char): - # always relay key event to some child - if self.focus: - self.handle('keypress', keyname, char) - if self.focuschild: - self.focuschild.keypress(keyname, char) - - def mousedown(self, ev): handled = False for child in reversed(self.children): @@ -98,6 +61,7 @@ handled = True break if not handled: + self.setfocus() self.handle('mousedown', ev) diff -r a35731b5e31a -r 69318aba22bf tuikit/menu.py --- a/tuikit/menu.py Wed Feb 16 23:51:30 2011 +0100 +++ b/tuikit/menu.py Thu Feb 17 23:35:05 2011 +0100 @@ -6,14 +6,19 @@ class Menu(Widget): def __init__(self, items=[]): Widget.__init__(self) - self.width = max([len(x) for x in items]) + 4 + self.width = max([len(x[0]) for x in items if x is not None]) + 4 self.height = len(items) + 2 self.bg = 2 + self.highlight = 3 self.items = items + self.selected = items[0] self.connect('draw', self.on_draw) self.connect('keypress', self.on_keypress) + self.connect('mousedown', self.on_mousedown) + self.connect('mousemove', self.on_mousemove) + self.connect('mouseup', self.on_mouseup) def on_draw(self, screen, x, y): @@ -21,14 +26,71 @@ screen.frame(x, y, self.width, self.height) i = 1 for item in self.items: - if item == '-': + if item is None: screen.puts(x, y + i, screen.LTEE + screen.HLINE * (self.width - 2) + screen.RTEE) else: - screen.puts(x + 1, y + i, ' ' + item + ' ' * (self.width - 3 - len(item))) + if self.selected == item: + screen.pushcolor(self.highlight, screen.BOLD) + screen.puts(x + 1, y + i, ' ' + item[0] + ' ' * (self.width - 3 - len(item[0]))) + screen.popcolor() + else: + screen.puts(x + 1, y + i, ' ' + item[0] + ' ' * (self.width - 3 - len(item[0]))) i += 1 screen.popcolor() def on_keypress(self, keyname, char): + if keyname == 'up': + self.move_selected(-1) + if keyname == 'down': + self.move_selected(+1) + if keyname == 'enter': + self.run_selected() self.redraw() + + def on_mousedown(self, ev): + self.select_at_pos(ev.wy - 1) + self.run_selected() + + + def on_mousemove(self, ev): + self.select_at_pos(ev.wy - 1) + + + def on_mouseup(self, ev): + ok = self.select_at_pos(ev.wy - 1) + if ok: + self.run_selected() + + + def select_at_pos(self, pos): + if pos < 0: + return False + try: + item = self.items[pos] + except IndexError: + return False + if item is None: + return False + self.selected = item + self.redraw() + return True + + + def move_selected(self, offset): + if self.selected: + i = self.items.index(self.selected) + i += offset + item = self.items[i % len(self.items)] + if item is None: + i += offset + item = self.items[i % len(self.items)] + self.selected = item + self.redraw() + + + def run_selected(self): + if self.selected and self.selected[1] is not None: + self.selected[1]() + diff -r a35731b5e31a -r 69318aba22bf tuikit/menubar.py --- a/tuikit/menubar.py Wed Feb 16 23:51:30 2011 +0100 +++ b/tuikit/menubar.py Thu Feb 17 23:35:05 2011 +0100 @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from .widget import Widget +import logging class MenuBar(Widget): @@ -16,11 +17,23 @@ self.connect('draw', self.on_draw) self.connect('keypress', self.on_keypress) self.connect('mousedown', self.on_mousedown) + self.connect('mousemove', self.on_mousemove) + self.connect('unfocus', self.on_unfocus) def setitems(self, items): self.items = items + i = 0 + for item in self.items: + if isinstance(item[1], Widget): + item[1].x = i + item[1].y = self.y + 1 + item[1].allowlayout = False + item[1].hidden = True + item[1].connect('focus', self.on_submenu_focus) + i += len(item[0]) + 4 + def on_draw(self, screen, x, y): screen.pushcolor(self.bg) @@ -39,23 +52,60 @@ def on_keypress(self, keyname, char): + if keyname == 'left': + self.move_selected(-1) + elif keyname == 'right': + self.move_selected(+1) + else: + if self.selected: + if isinstance(self.selected[1], Widget): + self.selected[1].emit('keypress', keyname, char) + + + def move_selected(self, offset): + if self.selected: + i = self.items.index(self.selected) + item = self.items[(i + offset) % len(self.items)] + self.unselect() + self.select(item) self.redraw() def on_mousedown(self, ev): i = 0 + self.unselect() + for item in self.items: + w = len(item[0]) + 4 + if ev.wx >= i and ev.wx < i + w: + self.select(item) + i += w + + + def on_mousemove(self, ev): + self.on_mousedown(ev) + + + def on_unfocus(self, newfocus): + #logging.getLogger('tuikit').debug('unfocus') + if self.selected and newfocus == self.selected[1]: + return + self.unselect() + + + def on_submenu_focus(self): + self.setfocus() + + + def select(self, item): + self.selected = item + if isinstance(item[1], Widget): + item[1].hidden = False + item[1].redraw() + + + def unselect(self): if self.selected: if isinstance(self.selected[1], Widget): self.selected[1].hidden = True self.selected = None - for item in self.items: - w = len(item[0]) + 4 - if ev.wx >= i and ev.wx < i + w: - self.selected = item - if isinstance(item[1], Widget): - item[1].x = i - item[1].y = self.y + 1 - item[1].hidden = False - item[1].redraw() - i += w diff -r a35731b5e31a -r 69318aba22bf tuikit/widget.py --- a/tuikit/widget.py Wed Feb 16 23:51:30 2011 +0100 +++ b/tuikit/widget.py Thu Feb 17 23:35:05 2011 +0100 @@ -16,17 +16,19 @@ self.allowlayout = True # redraw request self._redraw = True - self.focus = False self.hidden = False # event handlers self.event = { 'resize' : [], 'draw' : [], + 'focus' : [], + 'unfocus' : [], 'keypress' : [], 'mousedown' : [], 'mouseup' : [], 'mousemove' : [], - 'mousewheel' : []} + 'mousewheel' : [], + } def settop(self, top): @@ -85,27 +87,42 @@ def setfocus(self): - self.focus = True + if self.hasfocus(): + return + if self.top.focuswidget: + self.top.focuswidget.unfocus(self) + self.top.focuswidget = self + self.emit('focus') def unfocus(self): - self.focus = False + if self.top.focuswidget != self: + return + self.top.focuswidget = None + self.emit('unfocus') - def grabfocus(self): - if not self.focus: - self.parent.grabfocus(self) # grab focus for me + def hasfocus(self): + return self.top.focuswidget == self + + + def focus(self): + self.handle('focus') + + + def unfocus(self, newfocus=None): + self.handle('unfocus', newfocus) ### def keypress(self, keyname, char): - if self.focus: - self.handle('keypress', keyname, char) + self.handle('keypress', keyname, char) def mousedown(self, ev): + self.setfocus() self.handle('mousedown', ev) @@ -142,3 +159,4 @@ y,x = self.parent.screenyx() return self.y + y, self.x + x return self.y, self.x +