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