tuikit/layouts/grid.py
author Radek Brich <radek.brich@devl.cz>
Sun, 15 Feb 2015 12:52:46 +0100
changeset 115 b4ff7392003a
parent 114 26c02bd94bd9
permissions -rw-r--r--
GridLayout: basic implementation.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
114
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     1
from .layout import Layout
115
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
     2
from ..core.coords import Size
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
     3
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
     4
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
     5
class GridCell:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
     6
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
     7
    """Grid cell,
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
     8
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
     9
    This class contains attributes of the row/column
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    10
    and references to all widgets placed here.
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    11
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    12
    """
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    13
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    14
    def __init__(self, widget=None):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    15
        self.widget = widget
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    16
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    17
    @property
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    18
    def sizemin(self):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    19
        return self.widget.sizemin if self.widget else Size(0, 0)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    20
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    21
    def __repr__(self):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    22
        return '%s(%r)' % (self.__class__.__name__, self.widget)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    23
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    24
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    25
class GridRow:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    26
    pass
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    27
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    28
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    29
class GridColumn:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    30
    pass
114
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    31
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    32
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    33
class GridLayout(Layout):
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    34
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    35
    """Lay out widgets in a grid.
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    36
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    37
    Grid size is determined by each widget's specified column and row.
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    38
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    39
    """
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    40
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    41
    def __init__(self):
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    42
        Layout.__init__(self)
115
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    43
        #: map grid coordinates (x,y) to Widget
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    44
        self._grid = {}
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    45
        #: size of grid, expanded to accommodate given grid coordinates
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    46
        self._grid_size = Size()
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    47
        #: GridRow object for each row contains row parameters
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    48
        self._rows = []
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    49
        #: GridColumn object for each column contains column parameters
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    50
        self._columns = []
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    51
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    52
    @property
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    53
    def row_count(self):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    54
        return self._grid_size.h
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    55
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    56
    @property
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    57
    def column_count(self):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    58
        return self._grid_size.w
114
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    59
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    60
    def add(self, widget, row, column):
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    61
        Layout.add(self, widget)
115
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    62
        self._grid_size.update(w=max(row + 1, self._grid_size.h),
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    63
                               h=max(column + 1, self._grid_size.w))
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    64
        if (row, column) in self._grid:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    65
            raise Exception(
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    66
                'GridLayout.add: Cell (%s,%s) is occupied, cannot add widget.'
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    67
                % (row, column))
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    68
        self._grid[(row, column)] = GridCell(widget)
114
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    69
115
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    70
    def get_widget_at(self, row, column):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    71
        cell = self._grid.get((row, column))
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    72
        return cell.widget if cell else None
114
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    73
115
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    74
    def update(self, w, h):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    75
        row_height = []
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    76
        column_width = []
114
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    77
115
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    78
        # compute min. height of each row
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    79
        for row in range(self.row_count):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    80
            minh = 0
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    81
            for col in range(self.column_count):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    82
                widget = self.get_widget_at(row, col)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    83
                if widget:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    84
                    minh = max(minh, widget.sizemin.h)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    85
            row_height.append(minh)
114
26c02bd94bd9 Add Widget.posreq. Add OffsetLayout.
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    86
115
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    87
        # compute min. width of each column
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    88
        for col in range(self.column_count):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    89
            minw = 0
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    90
            for row in range(self.row_count):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    91
                widget = self.get_widget_at(row, col)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    92
                if widget:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    93
                    minw = max(minw, widget.sizemin.w)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    94
            column_width.append(minw)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    95
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    96
        # distribute rest of space to rows
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    97
        resth = h - sum(row_height)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    98
        if resth > 0:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
    99
            addh = resth // self.row_count
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   100
            resth = resth % self.row_count
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   101
            for row in range(self.row_count):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   102
                row_height[row] += addh
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   103
                if resth:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   104
                    row_height[row] += 1
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   105
                    resth -= 1
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   106
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   107
        # distribute rest of space to columns
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   108
        restw = w - sum(column_width)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   109
        if restw > 0:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   110
            addw = restw // self.column_count
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   111
            restw = restw % self.column_count
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   112
            for col in range(self.column_count):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   113
                column_width[col] += addw
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   114
                if restw:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   115
                    column_width[col] += 1
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   116
                    restw -= 1
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   117
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   118
        # place widgets
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   119
        for row in range(self.row_count):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   120
            for col in range(self.column_count):
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   121
                widget = self.get_widget_at(row, col)
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   122
                if widget:
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   123
                    widget.resize(column_width[col], row_height[row])
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   124
                    widget.move(sum(column_width[:col]), sum(row_height[:row]))
b4ff7392003a GridLayout: basic implementation.
Radek Brich <radek.brich@devl.cz>
parents: 114
diff changeset
   125