# HG changeset patch # User Radek Brich # Date 1359905921 -3600 # Node ID fc1989059e19be35ebbe337f5e50ed71550db53d # Parent fa5301e58eca9bb7449c78528007bdc91158e4f9 Propagate "quit" event, do not just terminate application. Resize: flag widgets to be resized, do resizes only once before draw. Draw: flag widgets to be redrawn, do not draw everything on any event. diff -r fa5301e58eca -r fc1989059e19 demo_anchorlayout.py --- a/demo_anchorlayout.py Sat Feb 02 12:54:27 2013 +0100 +++ b/demo_anchorlayout.py Sun Feb 03 16:38:41 2013 +0100 @@ -51,7 +51,7 @@ align = self.win.get_hint(align_type) align.select_next() ev.originator.label = '%s: %s' % (align_type, align.selected) - self.top.emit('resize') + self.top.need_resize() return True def on_label_margin_draw(self, ev): diff -r fa5301e58eca -r fc1989059e19 demo_input.py --- a/demo_input.py Sat Feb 02 12:54:27 2013 +0100 +++ b/demo_input.py Sun Feb 03 16:38:41 2013 +0100 @@ -19,12 +19,12 @@ scroll.add(self.editbox) self.top.add(scroll, halign='fill', valign='fill') - 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) + scroll.add_handler('keypress', self.on_any_input) + scroll.add_handler('mousedown', self.on_any_input) + scroll.add_handler('mouseup', self.on_any_input) + scroll.add_handler('mousewheel', self.on_any_input) + scroll.add_handler('mousemove', self.on_any_input) + scroll.add_handler('mousehover', self.on_any_input) def on_any_input(self, ev): if ev.event_name == 'keypress' and ev.keyname == 'escape': diff -r fa5301e58eca -r fc1989059e19 demo_menu.py --- a/demo_menu.py Sat Feb 02 12:54:27 2013 +0100 +++ b/demo_menu.py Sun Feb 03 16:38:41 2013 +0100 @@ -11,6 +11,7 @@ def __init__(self): Application.__init__(self) self.top.add_handler('keypress', self.on_top_keypress, last=True) + self.top.add_handler('quit', lambda ev: self.terminate()) helpwin = Window() helpwin.title = 'About' diff -r fa5301e58eca -r fc1989059e19 tuikit/application.py --- a/tuikit/application.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/application.py Sun Feb 03 16:38:41 2013 +0100 @@ -64,15 +64,15 @@ self._load_conf('tuikit.conf') self._setup_logging() + #: Driver class instance (render + input), e.g. DriverCurses. + self.driver = self.get_driver_instance(self.cfg['driver']) + # Top widget self._top = None self._timer = Timer() self.top = top_layout() - self.quit = False - - #: Driver class instance (render + input), e.g. DriverCurses. - self.driver = self.get_driver_instance(self.cfg['driver']) + self._quit = False def _load_conf(self, file_name): try: @@ -111,16 +111,16 @@ def terminate(self): '''Terminate application.''' - self.quit = True + self._quit = True def main_loop(self): '''The main loop.''' self.startup() self._top._size = self.driver.size # link top widget size to screen size - self._top.emit('resize') timer = self._timer - while True: + while not self._quit: + self._top.complete_requests() self._top.draw(self.driver, 0, 0) self.driver.commit() @@ -129,13 +129,7 @@ timer.process_timeouts() for event in events: - if event[0] == 'quit': - self.quit = True - else: - self._top.emit(event[0], *event[1:]) - - if self.quit: - break + self._top.emit(event[0], *event[1:]) self.log.info('=== quit ===') def startup(self): @@ -153,7 +147,7 @@ drv.defcolor('window:normal', 'lightgray on blue') drv.defcolor('window:controls', 'white on blue, bold') drv.defcolor('window:controls-active', 'cyan on blue, bold') - drv.defcolor('button', 'black on white') + drv.defcolor('button', 'black on lightgray') drv.defcolor('button-active', 'black on cyan') drv.defcolor('menu', 'black on cyan') drv.defcolor('menu-active', 'white on cyan, bold') diff -r fa5301e58eca -r fc1989059e19 tuikit/checkbox.py --- a/tuikit/checkbox.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/checkbox.py Sun Feb 03 16:38:41 2013 +0100 @@ -25,4 +25,5 @@ else: self.checked = True self.prefix = '[x] ' + self.redraw() diff -r fa5301e58eca -r fc1989059e19 tuikit/container.py --- a/tuikit/container.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/container.py Sun Feb 03 16:38:41 2013 +0100 @@ -26,8 +26,6 @@ #: Child widgets are placed within borders. self.borders = Borders() - self._layout = None - self.widthrequest = (None, None) self.heightrequest = (None, None) @@ -60,17 +58,6 @@ self.children.remove(child) self.children.append(child) - @property - def layout(self): - return self._layout - - @layout.setter - def layout(self, value): - """Layout manager for placing child widgets.""" - self._layout = value - self._layout.container = self - - def move_child(self, child, x, y): pass @@ -131,6 +118,11 @@ if self.focuschild: self.focuschild.emit('unfocus', ev) + def redraw(self): + Widget.redraw(self) + for child in self.children: + child.redraw() + def draw(self, driver, x, y): """Draw the container and its children. @@ -251,3 +243,8 @@ self.mousechild = child return True + def complete_requests(self): + Widget.complete_requests(self) + for child in self.children: + child.complete_requests() + diff -r fa5301e58eca -r fc1989059e19 tuikit/driver.py --- a/tuikit/driver.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/driver.py Sun Feb 03 16:38:41 2013 +0100 @@ -41,6 +41,11 @@ for i in range(h): self.putch(x, y+i, c) + def fill_clip(self, c=' '): + """Fill current clip region.""" + rect = self.clipstack.top() + self.fill(rect.x, rect.y, rect.w, rect.h, c) + def fill(self, x, y, w, h, c=' '): '''Fill rectangular area.''' for i in range(h): diff -r fa5301e58eca -r fc1989059e19 tuikit/driver_curses.py --- a/tuikit/driver_curses.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/driver_curses.py Sun Feb 03 16:38:41 2013 +0100 @@ -195,9 +195,10 @@ ## cursor ## def showcursor(self, x, y): - if not self.clipstack.test(x, y): - return - self.cursor = (y, x) + if self.clipstack.test(x, y): + self.cursor = (y, x) + else: + self.cursor = None def hidecursor(self): curses.curs_set(False) diff -r fa5301e58eca -r fc1989059e19 tuikit/editbox.py --- a/tuikit/editbox.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/editbox.py Sun Feb 03 16:38:41 2013 +0100 @@ -49,6 +49,7 @@ def on_draw(self, ev): ev.driver.pushcolor('normal') + ev.driver.fill_clip() end_y = min(len(self.lines), ev.exposed.y + ev.exposed.h) for j in range(ev.exposed.y, end_y): line = self.lines[j] @@ -83,6 +84,7 @@ y = ev.wy x = min(ev.wx, len(self.lines[y])) self._spot.update(x=x, y=y) + self.redraw() def on_mousewheel(self, ev): if ev.button == 4: diff -r fa5301e58eca -r fc1989059e19 tuikit/layout.py --- a/tuikit/layout.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/layout.py Sun Feb 03 16:38:41 2013 +0100 @@ -21,8 +21,11 @@ widget.add_handler('show', self._on_child_size_change) widget.add_handler('hide', self._on_child_size_change) + def on_resize(self, ev): + self.redraw() + def _on_child_size_change(self, ev): - self.emit('resize') + self.need_resize() def _get_children(self): return [child for child in self.children @@ -225,6 +228,7 @@ for child in self.children: x, y = child.hint_value('position') child._pos.update(x=x+ox, y=y+oy) + self.redraw() class GridLayout(Layout): diff -r fa5301e58eca -r fc1989059e19 tuikit/scrollview.py --- a/tuikit/scrollview.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/scrollview.py Sun Feb 03 16:38:41 2013 +0100 @@ -15,6 +15,9 @@ def add(self, widget, **kwargs): self._inner.add(widget, **kwargs) + def on_draw(self, ev): + ev.driver.fill_clip() + class Scrolling: def __init__(self): @@ -94,7 +97,7 @@ self.vscroll.hide() else: self.vscroll.show() - self._inner.need_resize() + # self._inner.need_resize() class ScrollView(OffsetView, Scrolling): diff -r fa5301e58eca -r fc1989059e19 tuikit/tableview.py --- a/tuikit/tableview.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/tableview.py Sun Feb 03 16:38:41 2013 +0100 @@ -161,6 +161,7 @@ def on_draw(self, ev): ev.driver.pushcolor('normal') + ev.driver.fill_clip() self.rowcount = self.model.getcount() numrows = min(self.rowcount - self.offset.y, self.height - self.headsize) rows = self.model.getrows(self.offset.y, self.offset.y + numrows) @@ -185,8 +186,8 @@ 'pagedown': self.move_pagedown} if ev.keyname in key_map: key_map[ev.keyname]() + self.redraw() return True - self.redraw() def set_yofs(self, yofs): if yofs > self.rowcount - (self.height - self.headsize): diff -r fa5301e58eca -r fc1989059e19 tuikit/treeview.py --- a/tuikit/treeview.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/treeview.py Sun Feb 03 16:38:41 2013 +0100 @@ -251,6 +251,7 @@ def on_draw(self, ev): ev.driver.pushcolor('normal') + ev.driver.fill_clip() lines = 0 # bit array, bit 0 - draw vertical line on first column, etc. y = ev.y @@ -292,8 +293,8 @@ 'right': self.move_right} if ev.keyname in key_map: key_map[ev.keyname]() + self.redraw() return True - self.redraw() def prev_node(self, node): # previous sibling diff -r fa5301e58eca -r fc1989059e19 tuikit/widget.py --- a/tuikit/widget.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/widget.py Sun Feb 03 16:38:41 2013 +0100 @@ -28,7 +28,6 @@ self._pos = Coords() #: Actual size. Modified only by layout manager. self._size = Size(10, 10) - self._size.add_handler('change', lambda ev: self.emit('resize')) #: Size of visible part of widget. Used in OffsetLayout. Modified only by layout manager. self._view_size = Size(10, 10) #: Default (natural) size of Widget. @@ -73,6 +72,7 @@ self.add_events( 'resize', Event, 'draw', DrawEvent, + 'quit', Event, 'keypress', KeyboardEvent, 'mousedown', MouseEvent, 'mouseup', MouseEvent, @@ -111,6 +111,14 @@ def height(self): return self._size.h + @property + def view_width(self): + return self._view_size.w + + @property + def view_height(self): + return self._view_size.h + def resize(self, w=None, h=None): """Set size request. @@ -120,14 +128,6 @@ self._sizereq.update(w, h) @property - def view_width(self): - return self._view_size.w - - @property - def view_height(self): - return self._view_size.h - - @property def sizereq(self): """Size request. @@ -144,6 +144,16 @@ logging.getLogger('tuikit').info('xy') self._size.update(self._sizereq) + def need_resize(self): + self._need_resize = True + + def on_resize(self, ev): + self._need_resize = False + + def complete_requests(self): + if self._need_resize: + self.emit('resize') + ### misc @property @@ -170,6 +180,8 @@ """Real setter for top. Allows override.""" self._top = value + ### hints + def reset_hints(self): """Reset all hints to their initial value. @@ -205,13 +217,8 @@ ### events - def need_resize(self): - self._need_resize = True - - def redraw(self, parent=False): + def redraw(self): self._need_draw = True - if parent and self.parent: - self.parent._redraw = True def draw(self, driver, x, y): """Draw the widget. @@ -220,7 +227,7 @@ use on_draw method instead. """ - if self.hidden: + if self.hidden or not self._need_draw: return True driver.clipstack.push(x, y, self.width, self.height) @@ -233,6 +240,7 @@ driver.showcursor(x + cx, y + cy) else: driver.hidecursor() + self._need_draw = False def on_mousedown(self, ev): self.grab_focus() @@ -240,11 +248,9 @@ ### focus - def can_focus(self): return not self.hidden and self.allow_focus - def has_focus(self): if self.parent is None: return True @@ -271,7 +277,9 @@ self.parent.focuschild = self if oldfocuschild: oldfocuschild.emit('unfocus', new=self) + oldfocuschild.redraw() self.emit('focus', old=oldfocuschild) + self.redraw() def grab_focus(self): """Focus the widget and its parents.""" @@ -314,6 +322,8 @@ self._hidden = True self.emit('hide') self.redraw() + if self.floater and self.top: + self.top.redraw() def show(self): '''Show widget. Convenience method.''' diff -r fa5301e58eca -r fc1989059e19 tuikit/window.py --- a/tuikit/window.py Sat Feb 02 12:54:27 2013 +0100 +++ b/tuikit/window.py Sun Feb 03 16:38:41 2013 +0100 @@ -40,6 +40,7 @@ self.colorprefix = 'window:' self._inner = inner_layout() + self._inner.add_handler('draw', self._on_inner_draw) Container.add(self, self._inner, halign='fill', valign='fill', margin=Borders(1,1,1,1)) def add(self, widget, **kwargs): @@ -55,7 +56,6 @@ self._closebutton = value self.closebtn.hidden = not value - def on_draw(self, ev): ev.driver.pushcolor('normal') ev.driver.frame(ev.x, ev.y, self.width, self.height) @@ -84,23 +84,30 @@ ev.driver.fill(ev.x+1, ev.y+1, self.width-2, self.height-2) ev.driver.popcolor() + def _on_inner_draw(self, ev): + ev.driver.pushcolor('normal') + ev.driver.fill_clip() + ev.driver.popcolor() + + def on_mousedown(self, ev): + self.bring_up() def after_mousedown(self, ev): if self.resizable and ev.wx >= self.width - 1 and ev.wy >= self.height - 1: self._resizing = True elif self.movable: self._moving = True - self.redraw(True) + self.parent.redraw() def after_mouseup(self, ev): self._resize_or_move(ev) self._resizing = False self._moving = False - self.redraw(True) + self.parent.redraw() def after_mousemove(self, ev): self._resize_or_move(ev) - self.redraw(True) + self.parent.redraw() def _resize_or_move(self, ev): if self._resizing: