GridLayout: basic implementation.
--- a/demos/04_texteditor.py Sun Feb 15 12:48:23 2015 +0100
+++ b/demos/04_texteditor.py Sun Feb 15 12:52:46 2015 +0100
@@ -11,6 +11,7 @@
def __init__(self):
Application.__init__(self)
+ self.window_manager.sig_keypress.connect(self.on_wm_keypress)
#self.top.add_handler('keypress', self.on_top_keypress)
t = open('../tuikit/core/widget.py').read()
@@ -22,9 +23,9 @@
self.root_window.add(editbox)
#self.root_window.add(scroll, halign='fill', valign='fill')
- def on_top_keypress(self, ev):
+ def on_wm_keypress(self, ev):
if ev.keyname == 'escape':
- self.terminate()
+ self.stop()
return True
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/05_gridlayout.py Sun Feb 15 12:52:46 2015 +0100
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+
+import demobase
+
+from tuikit.layouts.grid import GridLayout
+from tuikit.widgets.label import Label
+
+l1 = Label('Hello')
+l1.sizemin.update(10, 1)
+
+grid = GridLayout()
+grid.add(l1, 1, 1)
+grid.update(10, 10)
+
+print(grid._grid_size)
+print(grid._grid)
+
+for row in range(grid.row_count):
+ for col in range(grid.column_count):
+ w = grid.get_widget_at(row, col)
+ name = w.name if w else '--'
+ print(name.center(16), end='')
+ print()
+
+print(l1.pos)
+print(l1.size)
\ No newline at end of file
--- a/tuikit/core/container.py Sun Feb 15 12:48:23 2015 +0100
+++ b/tuikit/core/container.py Sun Feb 15 12:52:46 2015 +0100
@@ -35,7 +35,7 @@
def resize(self, w, h):
Widget.resize(self, w, h)
- self.layout.update()
+ self.layout.update(w, h)
def draw(self, buffer):
"""Draw child widgets."""
--- a/tuikit/core/coords.py Sun Feb 15 12:48:23 2015 +0100
+++ b/tuikit/core/coords.py Sun Feb 15 12:52:46 2015 +0100
@@ -83,7 +83,7 @@
# string representation
def __repr__(self):
- return '{0.__class__.__name__}(x={0.x},y={0.y})'.format(self)
+ return '{0.__class__.__name__}(x={0.x}, y={0.y})'.format(self)
def immutable(self):
return ImmutablePoint(*self)
@@ -136,7 +136,7 @@
return (self.w, self.h)[key]
def __repr__(self):
- return '{0.__class__.__name__}(w={0.w},h={0.h})'.format(self)
+ return '{0.__class__.__name__}(w={0.w}, h={0.h})'.format(self)
def update(self, *args, **kwargs):
"""Update size.
@@ -219,7 +219,7 @@
return Rect(x, y, w, h)
def __repr__(self):
- return '{0.__class__.__name__}(x={0.x},y={0.y},w={0.w},h={0.h})'.format(self)
+ return '{0.__class__.__name__}(x={0.x}, y={0.y}, w={0.w}, h={0.h})'.format(self)
def __contains__(self, point):
"""Test if point is positioned inside rectangle.
--- a/tuikit/layouts/fixed.py Sun Feb 15 12:48:23 2015 +0100
+++ b/tuikit/layouts/fixed.py Sun Feb 15 12:52:46 2015 +0100
@@ -3,7 +3,7 @@
class FixedLayout(Layout):
- def update(self):
+ def update(self, _w, _h):
for widget in self._managed_widgets:
widget.resize(*widget.sizereq)
widget.pos.update(*widget.posreq)
--- a/tuikit/layouts/grid.py Sun Feb 15 12:48:23 2015 +0100
+++ b/tuikit/layouts/grid.py Sun Feb 15 12:52:46 2015 +0100
@@ -1,4 +1,33 @@
from .layout import Layout
+from ..core.coords import Size
+
+
+class GridCell:
+
+ """Grid cell,
+
+ This class contains attributes of the row/column
+ and references to all widgets placed here.
+
+ """
+
+ def __init__(self, widget=None):
+ self.widget = widget
+
+ @property
+ def sizemin(self):
+ return self.widget.sizemin if self.widget else Size(0, 0)
+
+ def __repr__(self):
+ return '%s(%r)' % (self.__class__.__name__, self.widget)
+
+
+class GridRow:
+ pass
+
+
+class GridColumn:
+ pass
class GridLayout(Layout):
@@ -11,14 +40,86 @@
def __init__(self):
Layout.__init__(self)
+ #: map grid coordinates (x,y) to Widget
+ self._grid = {}
+ #: size of grid, expanded to accommodate given grid coordinates
+ self._grid_size = Size()
+ #: GridRow object for each row contains row parameters
+ self._rows = []
+ #: GridColumn object for each column contains column parameters
+ self._columns = []
+
+ @property
+ def row_count(self):
+ return self._grid_size.h
+
+ @property
+ def column_count(self):
+ return self._grid_size.w
def add(self, widget, row, column):
Layout.add(self, widget)
+ self._grid_size.update(w=max(row + 1, self._grid_size.h),
+ h=max(column + 1, self._grid_size.w))
+ if (row, column) in self._grid:
+ raise Exception(
+ 'GridLayout.add: Cell (%s,%s) is occupied, cannot add widget.'
+ % (row, column))
+ self._grid[(row, column)] = GridCell(widget)
+ def get_widget_at(self, row, column):
+ cell = self._grid.get((row, column))
+ return cell.widget if cell else None
+ def update(self, w, h):
+ row_height = []
+ column_width = []
+ # compute min. height of each row
+ for row in range(self.row_count):
+ minh = 0
+ for col in range(self.column_count):
+ widget = self.get_widget_at(row, col)
+ if widget:
+ minh = max(minh, widget.sizemin.h)
+ row_height.append(minh)
- def update(self):
- for widget in self._managed_widgets:
- widget.resize(*widget.sizereq)
- widget.pos.update(*(widget.posreq + self.offset))
+ # compute min. width of each column
+ for col in range(self.column_count):
+ minw = 0
+ for row in range(self.row_count):
+ widget = self.get_widget_at(row, col)
+ if widget:
+ minw = max(minw, widget.sizemin.w)
+ column_width.append(minw)
+
+ # distribute rest of space to rows
+ resth = h - sum(row_height)
+ if resth > 0:
+ addh = resth // self.row_count
+ resth = resth % self.row_count
+ for row in range(self.row_count):
+ row_height[row] += addh
+ if resth:
+ row_height[row] += 1
+ resth -= 1
+
+ # distribute rest of space to columns
+ restw = w - sum(column_width)
+ if restw > 0:
+ addw = restw // self.column_count
+ restw = restw % self.column_count
+ for col in range(self.column_count):
+ column_width[col] += addw
+ if restw:
+ column_width[col] += 1
+ restw -= 1
+
+ # place widgets
+ for row in range(self.row_count):
+ for col in range(self.column_count):
+ widget = self.get_widget_at(row, col)
+ if widget:
+ widget.resize(column_width[col], row_height[row])
+ widget.move(sum(column_width[:col]), sum(row_height[:row]))
+
--- a/tuikit/layouts/layout.py Sun Feb 15 12:48:23 2015 +0100
+++ b/tuikit/layouts/layout.py Sun Feb 15 12:52:46 2015 +0100
@@ -3,10 +3,15 @@
def __init__(self):
self._managed_widgets = []
- def add(self, widget):
+ def add(self, widget, **_kwargs):
self._managed_widgets.append(widget)
- def update(self):
- """Rearrange managed widgets."""
+ def update(self, w, h):
+ """Rearrange managed widgets in given space.
+
+ `w`, `h` is available horizontal and vertical space,
+ or width and height of parent container of managed widgets.
+
+ """
pass
--- a/tuikit/layouts/offset.py Sun Feb 15 12:48:23 2015 +0100
+++ b/tuikit/layouts/offset.py Sun Feb 15 12:52:46 2015 +0100
@@ -15,7 +15,7 @@
"""Offset of child widgets."""
return self._offset
- def update(self):
+ def update(self, _w, _h):
for widget in self._managed_widgets:
widget.resize(*widget.sizereq)
widget.pos.update(*(widget.posreq + self.offset))