]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/grids.py
8387190002b644b636be1993279eebe18b4eb2e8
[wxWidgets.git] / wxPython / wxPython / lib / grids.py
1 #----------------------------------------------------------------------
2 # Name: wxPython.lib.grids
3 # Purpose: An example sizer derived from the C++ wxPySizer that
4 # sizes items in a fixed or flexible grid.
5 #
6 # Author: Robin Dunn
7 #
8 # Created: 21-Sept-1999
9 # RCS-ID: $Id$
10 # Copyright: (c) 1999 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------
13
14 """
15 In this module you will find wxGridSizer and wxFlexGridSizer.
16
17 wxGridSizer: Sizes and positions items such that all rows are the same
18 height and all columns are the same width. You can specify a gap in
19 pixels to be used between the rows and/or the columns. When you
20 create the sizer you specify the number of rows or the number of
21 columns and then as you add items it figures out the other dimension
22 automatically. Like other sizers, items can be set to fill their
23 available space, or to be aligned on a side, in a corner, or in the
24 center of the space. When the sizer is resized, all the items are
25 resized the same amount so all rows and all columns remain the same
26 size.
27
28 wxFlexGridSizer: Derives from wxGridSizer and adds the ability for
29 particular rows and/or columns to be marked as growable. This means
30 that when the sizer changes size, the growable rows and colums are the
31 ones that stretch. The others remain at their initial size.
32
33 See the demo for a couple examples for how to use them.
34 """
35
36
37 from wxPython.wx import *
38
39 import operator
40
41 #----------------------------------------------------------------------
42
43 class wxGridSizer(wxPySizer):
44 def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
45 wxPySizer.__init__(self)
46 if rows == 0 and cols == 0:
47 raise ValueError, "rows and cols cannot both be zero"
48
49 self.rows = rows
50 self.cols = cols
51 self.hgap = hgap
52 self.vgap = vgap
53
54
55 def SetRows(self, rows):
56 if rows == 0 and self.cols == 0:
57 raise ValueError, "rows and cols cannot both be zero"
58 self.rows = rows
59
60 def SetColumns(self, cols):
61 if self.rows == 0 and cols == 0:
62 raise ValueError, "rows and cols cannot both be zero"
63 self.cols = cols
64
65 def GetRows(self):
66 return self.rows
67
68 def GetColumns(self):
69 return self.cols
70
71 def SetHgap(self, hgap):
72 self.hgap = hgap
73
74 def SetVgap(self, vgap):
75 self.vgap = vgap
76
77 def GetHgap(self, hgap):
78 return self.hgap
79
80 def GetVgap(self, vgap):
81 return self.vgap
82
83 #--------------------------------------------------
84 def CalcMin(self):
85 items = self.GetChildren()
86 nitems = len(items)
87 nrows = self.rows
88 ncols = self.cols
89
90 if ncols > 0:
91 nrows = (nitems + ncols-1) / ncols
92 else:
93 ncols = (nitems + nrows-1) / nrows
94
95 # Find the max width and height for any component.
96 w = 0
97 h = 0
98 for item in items:
99 size = item.CalcMin()
100 w = max(w, size.width)
101 h = max(h, size.height)
102
103 return wxSize(ncols * w + (ncols-1) * self.hgap,
104 nrows * h + (nrows-1) * self.vgap)
105
106
107 #--------------------------------------------------
108 def RecalcSizes(self):
109 items = self.GetChildren()
110 if not items:
111 return
112
113 nitems = len(items)
114 nrows = self.rows
115 ncols = self.cols
116
117 if ncols > 0:
118 nrows = (nitems + ncols-1) / ncols
119 else:
120 ncols = (nitems + nrows-1) / nrows
121
122
123 sz = self.GetSize()
124 pt = self.GetPosition()
125 w = (sz.width - (ncols - 1) * self.hgap) / ncols;
126 h = (sz.height - (nrows - 1) * self.vgap) / nrows;
127
128 x = pt.x
129 for c in range(ncols):
130 y = pt.y
131 for r in range(nrows):
132 i = r * ncols + c
133 if i < nitems:
134 self.SetItemBounds(items[i], x, y, w, h)
135 y = y + h + self.vgap
136 x = x + w + self.hgap
137
138
139 #--------------------------------------------------
140 def SetItemBounds(self, item, x, y, w, h):
141 # calculate the item's size and position within
142 # its grid cell
143 ipt = wxPoint(x, y)
144 isz = item.CalcMin()
145 flag = item.GetFlag()
146
147 if flag & wxEXPAND or flag & wxSHAPED:
148 isz = wxSize(w, h)
149 else:
150 if flag & wxALIGN_CENTER_HORIZONTAL:
151 ipt.x = x + (w - isz.width) / 2
152 elif flag & wxALIGN_RIGHT:
153 ipt.x = x + (w - isz.width)
154
155 if flag & wxALIGN_CENTER_VERTICAL:
156 ipt.y = y + (h - isz.height) / 2
157 elif flag & wxALIGN_BOTTOM:
158 ipt.y = y + (h - isz.height)
159
160 item.SetDimension(ipt, isz)
161
162
163 #----------------------------------------------------------------------
164
165
166
167 class wxFlexGridSizer(wxGridSizer):
168 def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
169 wxGridSizer.__init__(self, rows, cols, hgap, vgap)
170 self.rowHeights = []
171 self.colWidths = []
172 self.growableRows = []
173 self.growableCols = []
174
175 def AddGrowableRow(self, idx):
176 self.growableRows.append(idx)
177
178 def AddGrowableCol(self, idx):
179 self.growableCols.append(idx)
180
181 #--------------------------------------------------
182 def CalcMin(self):
183 items = self.GetChildren()
184 nitems = len(items)
185 nrows = self.rows
186 ncols = self.cols
187
188 if ncols > 0:
189 nrows = (nitems + ncols-1) / ncols
190 else:
191 ncols = (nitems + nrows-1) / nrows
192
193 # Find the max width and height for any component.
194 self.rowHeights = [0] * nrows
195 self.colWidths = [0] * ncols
196 for i in range(len(items)):
197 size = items[i].CalcMin()
198 row = i / ncols
199 col = i % ncols
200 self.rowHeights[row] = max(size.height, self.rowHeights[row])
201 self.colWidths[col] = max(size.width, self.colWidths[col])
202
203 # Add up all the widths and heights
204 cellsWidth = reduce(operator.__add__, self.colWidths)
205 cellHeight = reduce(operator.__add__, self.rowHeights)
206
207 return wxSize(cellsWidth + (ncols-1) * self.hgap,
208 cellHeight + (nrows-1) * self.vgap)
209
210
211 #--------------------------------------------------
212 def RecalcSizes(self):
213 items = self.GetChildren()
214 if not items:
215 return
216
217 nitems = len(items)
218 nrows = self.rows
219 ncols = self.cols
220
221 if ncols > 0:
222 nrows = (nitems + ncols-1) / ncols
223 else:
224 ncols = (nitems + nrows-1) / nrows
225
226 minsz = self.CalcMin()
227 sz = self.GetSize()
228 pt = self.GetPosition()
229
230 # Check for growables
231 if self.growableRows and sz.height > minsz.height:
232 delta = (sz.height - minsz.height) / len(self.growableRows)
233 for idx in self.growableRows:
234 self.rowHeights[idx] = self.rowHeights[idx] + delta
235
236 if self.growableCols and sz.width > minsz.width:
237 delta = (sz.width - minsz.width) / len(self.growableCols)
238 for idx in self.growableCols:
239 self.colWidths[idx] = self.colWidths[idx] + delta
240
241 # bottom right corner
242 sz = wxSize(pt.x + sz.width, pt.y + sz.height)
243
244 # Layout each cell
245 x = pt.x
246 for c in range(ncols):
247 y = pt.y
248 for r in range(nrows):
249 i = r * ncols + c
250 if i < nitems:
251 w = max(0, min(self.colWidths[c], sz.width - x))
252 h = max(0, min(self.rowHeights[r], sz.height - y))
253 self.SetItemBounds(items[i], x, y, w, h)
254 y = y + self.rowHeights[r] + self.vgap
255 x = x + self.colWidths[c] + self.hgap
256
257 #----------------------------------------------------------------------
258
259
260
261
262
263