# HG changeset patch # User Radek Brich # Date 1424001166 -3600 # Node ID b4ff7392003a79ecd0d3257a0ba661aec0b93fc3 # Parent 26c02bd94bd98e553901a2bf73b25020392b6801 GridLayout: basic implementation. diff -r 26c02bd94bd9 -r b4ff7392003a demos/04_texteditor.py --- 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 diff -r 26c02bd94bd9 -r b4ff7392003a demos/05_gridlayout.py --- /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 diff -r 26c02bd94bd9 -r b4ff7392003a tuikit/core/container.py --- 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.""" diff -r 26c02bd94bd9 -r b4ff7392003a tuikit/core/coords.py --- 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. diff -r 26c02bd94bd9 -r b4ff7392003a tuikit/layouts/fixed.py --- 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) diff -r 26c02bd94bd9 -r b4ff7392003a tuikit/layouts/grid.py --- 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])) + diff -r 26c02bd94bd9 -r b4ff7392003a tuikit/layouts/layout.py --- 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 diff -r 26c02bd94bd9 -r b4ff7392003a tuikit/layouts/offset.py --- 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))