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