Drop Container.offset, add special layout for that - OffsetLayout.
Add Widget.bring_up(): moves child to end of children list.
--- a/demo_menu.py Sat Jan 19 13:05:21 2013 +0100
+++ b/demo_menu.py Sun Jan 20 00:49:19 2013 +0100
@@ -44,6 +44,8 @@
menubtn = MenuButton('MenuButton', menu)
self.top.add(menubtn, halign='center', valign='center')
+ helpwin.bring_up()
+
def on_top_keypress(self, ev):
if ev.keyname == 'escape':
self.terminate()
--- a/demo_tableview.py Sat Jan 19 13:05:21 2013 +0100
+++ b/demo_tableview.py Sun Jan 20 00:49:19 2013 +0100
@@ -5,7 +5,6 @@
locale.setlocale(locale.LC_ALL, '')
from tuikit import Application
-from tuikit.layout import VerticalLayout
from tuikit.tableview import TableView, TableModel
@@ -27,9 +26,7 @@
for x in range(10):
view.addcolumn(title='head'+str(x))
- self.top.add(view, expand=True, fill=True)
-
- self.top.layout = VerticalLayout()
+ self.top.add(view, halign='fill', valign='fill')
def on_top_keypress(self, ev):
if ev.keyname == 'escape':
--- a/demo_treeview.py Sat Jan 19 13:05:21 2013 +0100
+++ b/demo_treeview.py Sun Jan 20 00:49:19 2013 +0100
@@ -4,12 +4,12 @@
import locale
locale.setlocale(locale.LC_ALL, '')
-from tuikit import Application, TreeView, TreeModel, ScrollView, VerticalLayout
+from tuikit import Application, TreeView, TreeModel, ScrollView
class MyApplication(Application):
def __init__(self):
- Application.__init__(self, top_layout=VerticalLayout)
+ Application.__init__(self)
self.top.add_handler('keypress', self.on_top_keypress)
model = TreeModel()
@@ -27,7 +27,7 @@
scroll = ScrollView()
scroll.add(view)
- self.top.add(scroll, expand=True, fill=True)
+ self.top.add(scroll, halign='fill', valign='fill')
def on_top_keypress(self, ev):
if ev.keyname == 'escape':
--- a/tuikit/common.py Sat Jan 19 13:05:21 2013 +0100
+++ b/tuikit/common.py Sun Jan 20 00:49:19 2013 +0100
@@ -34,13 +34,32 @@
return type(name, (Select,), {'_options': args})
-class Coords:
+class Coords(Emitter):
'''2D coordinates.'''
def __init__(self, x=0, y=0):
- self.x = x
- self.y = y
+ self._x = x
+ self._y = y
+ self.add_events('change', Event)
+
+ @property
+ def x(self):
+ return self._x
+
+ @x.setter
+ def x(self, value):
+ self._x = value
+ self.emit('change')
+
+ @property
+ def y(self):
+ return self._y
+
+ @y.setter
+ def y(self, value):
+ self._y = value
+ self.emit('change')
def __getitem__(self, key):
try:
@@ -60,6 +79,7 @@
return 'Coords(x={0.x},y={0.y})'.format(self)
def update(self, x=None, y=None):
+ old_x, old_y = self._x, self._y
if isinstance(x, Coords) and y is None:
self.x, self.y = x
else:
@@ -71,6 +91,8 @@
self.y = y
elif y is not None:
raise ValueError('Coords.update(): second parameter must be int')
+ if self._x != old_x or self._y != old_y:
+ self.emit('change')
class Size(Emitter):
--- a/tuikit/container.py Sat Jan 19 13:05:21 2013 +0100
+++ b/tuikit/container.py Sun Jan 20 00:49:19 2013 +0100
@@ -17,9 +17,6 @@
self.children = []
self._hint_class = {}
- #: Offset for child widgets
- self.offset = Coords()
-
self.focuschild = None
self.mousechild = None
@@ -61,6 +58,11 @@
for hint_name, hint_class in zip(hints[::2], hints[1::2]):
self._hint_class[hint_name] = hint_class
+ def bring_up_child(self, child):
+ if child in self.children:
+ self.children.remove(child)
+ self.children.append(child)
+
@property
def layout(self):
return self._layout
@@ -100,7 +102,10 @@
event - in that case, True stops event propagation.
"""
- idx_current = self.children.index(self.focuschild)
+ if self.focuschild is None:
+ idx_current = 0
+ else:
+ idx_current = self.children.index(self.focuschild)
idx_new = idx_current
cycled = False
while True:
@@ -150,8 +155,8 @@
for child in [ch for ch in self.children if not ch.floater]:
child.draw(driver,
- x + self.offset.x + child.x,
- y + self.offset.y + child.y)
+ x + child.x,
+ y + child.y)
driver.clipstack.pop()
@@ -168,13 +173,13 @@
# draw our floaters
for child in [ch for ch in self.children if ch.floater]:
child.draw(driver,
- x + self.offset.x + child.x,
- y + self.offset.y + child.y)
+ x + child.x,
+ y + child.y)
# delve into child containers, draw their floaters
for child in [ch for ch in self.children if not ch.floater and isinstance(ch, Container)]:
child.draw_floaters(driver,
- x + self.offset.x + child.x,
- y + self.offset.y + child.y)
+ x + child.x,
+ y + child.y)
def on_resize(self, ev):
for child in self.children:
@@ -221,7 +226,7 @@
if self.floaters_mouse_event(ev):
return True
for child in reversed([ch for ch in self.children if not ch.floater]):
- if child.enclose(ev.wx - self.offset.x, ev.wy - self.offset.y):
+ if child.enclose(ev.wx, ev.wy):
child_ev = ev.make_child_event(self, child)
child.emit(ev.event_name, child_ev)
if ev.event_name == 'mousedown':
@@ -241,7 +246,7 @@
return True
# test our floaters
for child in reversed([ch for ch in self.children if ch.floater]):
- if child.enclose(ev.wx - self.offset.x, ev.wy - self.offset.y):
+ if child.enclose(ev.wx, ev.wy):
child_ev = ev.make_child_event(self, child)
child.emit(ev.event_name, child_ev)
if ev.event_name == 'mousedown':
--- a/tuikit/layout.py Sat Jan 19 13:05:21 2013 +0100
+++ b/tuikit/layout.py Sun Jan 20 00:49:19 2013 +0100
@@ -186,6 +186,36 @@
self._resize(ax1, ax2)
+class OffsetLayout(Layout):
+
+ """Offsets widget position, useful for scrollable area."""
+
+ def __init__(self):
+ Layout.__init__(self)
+ self._offset = Coords()
+ self._offset.add_handler('change', lambda ev: self._update_children_position())
+ self.register_hints('position', Coords)
+
+ @property
+ def offset(self):
+ """Offset of child widgets."""
+ return self._offset
+
+ def on_resize(self, ev):
+ for child in self._get_children():
+ w, h = child.sizereq
+ child._size.update(w=w, h=h)
+
+ def move_child(self, child, x, y):
+ child.hints('position').update(x, y)
+
+ def _update_children_position(self):
+ ox, oy = self._offset
+ for child in self.children:
+ x, y = child.hints['position']
+ child._pos.update(x=x+ox, y=y+oy)
+
+
class GridLayout(Layout):
def __init__(self, numcols=2):
Layout.__init__(self)
--- a/tuikit/menubar.py Sat Jan 19 13:05:21 2013 +0100
+++ b/tuikit/menubar.py Sun Jan 20 00:49:19 2013 +0100
@@ -22,6 +22,12 @@
widget.move(0, 1)
widget.hide()
+ def on_keypress(self, ev):
+ if ev.keyname == 'escape':
+ if not self.menu.hidden:
+ self.menu.hide()
+ return True
+
def on_click(self, ev):
self.menu.show()
@@ -76,7 +82,4 @@
return res
elif ev.keyname == 'down':
return self.focuschild.show_menu()
- elif menu_visible and ev.keyname == 'escape':
- self.focuschild.menu.hide()
- return True
--- a/tuikit/scrollview.py Sat Jan 19 13:05:21 2013 +0100
+++ b/tuikit/scrollview.py Sun Jan 20 00:49:19 2013 +0100
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
-from tuikit.container import Container
+from tuikit.layout import AnchorLayout, OffsetLayout
from tuikit.scrollbar import VScrollbar
+from tuikit.common import Borders
-class ScrollView(Container):
+class ScrollView(AnchorLayout):
"""Scrolling view
Shows scrollbars when needed.
@@ -13,50 +14,47 @@
"""
def __init__(self):
- Container.__init__(self)
+ AnchorLayout.__init__(self)
self._default_size.update(20, 20)
+ self.inner = OffsetLayout()
+ AnchorLayout.add(self, self.inner, halign='fill', valign='fill', margin=Borders(r=1))
+
self.vscroll = VScrollbar()
self.vscroll.add_handler('change', self._on_vscroll_change)
- self.vscroll.evade_layout = 2
- self.add(self.vscroll)
+ AnchorLayout.add(self, self.vscroll, halign='right', valign='fill')
def add(self, widget, **kwargs):
- Container.add(self, widget, **kwargs)
- if widget != self.vscroll:
- widget.add_handler('sizereq', self._on_child_sizereq)
- widget.add_handler('spotmove', self._on_child_spotmove)
+ self.inner.add(widget, **kwargs)
+ widget.add_handler('sizereq', self._on_child_sizereq)
+ widget.add_handler('spotmove', self._on_child_spotmove)
def on_resize(self, ev):
- self.vscroll.move(x = self.size.w - 1)
- self.vscroll.resize(h = self.height)
self._update_vscroll_max()
def _on_vscroll_change(self, ev):
- self.offset.y = - self.vscroll.pos
+ self.inner.offset.y = - self.vscroll.scroll_pos
def _on_child_sizereq(self, ev):
self._update_vscroll_max()
def _on_child_spotmove(self, ev):
child = ev.originator
- spot = child.y + child.spot.y
- if spot < self.vscroll.pos:
- self.vscroll.pos = spot
- if spot > (self.size.h - 1) + self.vscroll.pos:
- self.vscroll.pos = spot - (self.size.h - 1)
+ spot = child.y - self.inner.offset.y + child.spot.y
+ if spot < self.vscroll.scroll_pos:
+ self.vscroll.scroll_pos = spot
+ if spot > (self.height - 1) + self.vscroll.scroll_pos:
+ self.vscroll.scroll_pos = spot - (self.height - 1)
def _update_vscroll_max(self):
max_height = 0
- for child in self.children:
- if child == self.vscroll:
- continue
- child_height = child.x + child.sizereq.h
+ for child in self.inner.children:
+ child_height = child.y - self.inner.offset.y + child.sizereq.h
if child_height > max_height:
max_height = child_height
- if max_height < self.size.h:
+ if max_height < self.height:
self.vscroll.hide()
else:
- self.vscroll.max = max_height - self.size.h
+ self.vscroll.scroll_max = max_height - self.height
self.vscroll.show()
--- a/tuikit/tableview.py Sat Jan 19 13:05:21 2013 +0100
+++ b/tuikit/tableview.py Sun Jan 20 00:49:19 2013 +0100
@@ -64,8 +64,9 @@
class TableView(Widget):
- def __init__(self, model=None, width=20, height=20):
- Widget.__init__(self, width, height)
+ def __init__(self, model=None):
+ Widget.__init__(self)
+ self._default_size.update(20, 20)
self.allow_focus = True
@@ -79,8 +80,8 @@
self.headsize = 1
self.offset = Coords()
+ #: Active cell (cursor)
self.acell = Coords()
- '''Active cell (cursor).'''
self.add_events(
'scroll', Event,
@@ -106,7 +107,7 @@
self.columns.append(col)
def compute_column_sizes(self):
- total_space = self.size.w - self.spacing * len(self.columns)
+ total_space = self.width - self.spacing * len(self.columns)
no_expand_cols = [col for col in self.columns if not col.expand]
no_expand_size = sum([col.sizereq for col in no_expand_cols])
expand_cols = [col for col in self.columns if col.expand]
@@ -161,7 +162,7 @@
def on_draw(self, ev):
ev.driver.pushcolor('normal')
self.rowcount = self.model.getcount()
- numrows = min(self.rowcount - self.offset.y, self.size.h - self.headsize)
+ numrows = min(self.rowcount - self.offset.y, self.height - self.headsize)
rows = self.model.getrows(self.offset.y, self.offset.y + numrows)
self.compute_column_sizes()
self.draw_head(ev.driver, ev.x, ev.y)
--- a/tuikit/widget.py Sat Jan 19 13:05:21 2013 +0100
+++ b/tuikit/widget.py Sun Jan 20 00:49:19 2013 +0100
@@ -89,7 +89,7 @@
def y(self):
return self._pos.y
- def move(self, x, y):
+ def move(self, x=None, y=None):
if self.floater:
self._pos.update(x, y)
if self.parent:
@@ -263,6 +263,10 @@
self.hidden = False
self.redraw()
+ def bring_up(self):
+ if self.parent:
+ self.parent.bring_up_child(self)
+
## timeout ##