]>
Commit | Line | Data |
---|---|---|
2f90df85 | 1 | #---------------------------------------------------------------------- |
694759cf | 2 | # Name: wxPython.lib.grids |
2f90df85 RD |
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 | """ | |
a6ad3e89 | 15 | In this module you will find wxGridSizer and wxFlexGridSizer. |
2f90df85 RD |
16 | wxGridSizer arrainges its items in a grid in which all the widths and |
17 | heights are the same. wxFlexgridSizer allows different widths and | |
18 | heights, and you can also specify rows and/or columns that are | |
19 | growable. See the demo for a couple examples for how to use them. | |
2f90df85 RD |
20 | """ |
21 | ||
22 | ||
23 | from wxPython.wx import * | |
24 | ||
25 | import operator | |
26 | ||
27 | #---------------------------------------------------------------------- | |
28 | ||
29 | class wxGridSizer(wxPySizer): | |
30 | def __init__(self, rows=0, cols=0, hgap=0, vgap=0): | |
31 | wxPySizer.__init__(self) | |
32 | if rows == 0 and cols == 0: | |
33 | raise ValueError, "rows and cols cannot both be zero" | |
34 | ||
35 | self.rows = rows | |
36 | self.cols = cols | |
37 | self.hgap = hgap | |
38 | self.vgap = vgap | |
39 | ||
40 | ||
41 | def SetRows(self, rows): | |
42 | if rows == 0 and self.cols == 0: | |
43 | raise ValueError, "rows and cols cannot both be zero" | |
44 | self.rows = rows | |
45 | ||
46 | def SetColumns(self, cols): | |
47 | if self.rows == 0 and cols == 0: | |
48 | raise ValueError, "rows and cols cannot both be zero" | |
49 | self.cols = cols | |
50 | ||
51 | def GetRows(self): | |
52 | return self.rows | |
53 | ||
54 | def GetColumns(self): | |
55 | return self.cols | |
56 | ||
57 | def SetHgap(self, hgap): | |
58 | self.hgap = hgap | |
59 | ||
60 | def SetVgap(self, vgap): | |
61 | self.vgap = vgap | |
62 | ||
63 | def GetHgap(self, hgap): | |
64 | return self.hgap | |
65 | ||
66 | def GetVgap(self, vgap): | |
67 | return self.vgap | |
68 | ||
69 | #-------------------------------------------------- | |
70 | def CalcMin(self): | |
71 | items = self.GetChildren() | |
72 | nitems = len(items) | |
73 | nrows = self.rows | |
74 | ncols = self.cols | |
75 | ||
76 | if ncols > 0: | |
77 | nrows = (nitems + ncols-1) / ncols | |
78 | else: | |
79 | ncols = (nitems + nrows-1) / nrows | |
80 | ||
81 | # Find the max width and height for any component. | |
82 | w = 0 | |
83 | h = 0 | |
84 | for item in items: | |
85 | size = item.CalcMin() | |
86 | w = max(w, size.width) | |
87 | h = max(h, size.height) | |
88 | ||
89 | return wxSize(ncols * w + (ncols-1) * self.hgap, | |
90 | nrows * h + (nrows-1) * self.vgap) | |
91 | ||
92 | ||
93 | #-------------------------------------------------- | |
94 | def RecalcSizes(self): | |
95 | items = self.GetChildren() | |
96 | if not items: | |
97 | return | |
98 | ||
99 | nitems = len(items) | |
100 | nrows = self.rows | |
101 | ncols = self.cols | |
102 | ||
103 | if ncols > 0: | |
104 | nrows = (nitems + ncols-1) / ncols | |
105 | else: | |
106 | ncols = (nitems + nrows-1) / nrows | |
107 | ||
108 | ||
109 | sz = self.GetSize() | |
110 | pt = self.GetPosition() | |
111 | w = (sz.width - (ncols - 1) * self.hgap) / ncols; | |
112 | h = (sz.height - (nrows - 1) * self.vgap) / nrows; | |
113 | ||
114 | x = pt.x | |
115 | for c in range(ncols): | |
116 | y = pt.y | |
117 | for r in range(nrows): | |
118 | i = r * ncols + c | |
119 | if i < nitems: | |
120 | self.SetItemBounds(items[i], x, y, w, h) | |
121 | y = y + h + self.vgap | |
122 | x = x + w + self.hgap | |
123 | ||
124 | ||
125 | #-------------------------------------------------- | |
126 | def SetItemBounds(self, item, x, y, w, h): | |
127 | # calculate the item's size and position within | |
128 | # its grid cell | |
129 | ipt = wxPoint(x, y) | |
130 | isz = item.CalcMin() | |
131 | flag = item.GetFlag() | |
132 | ||
be2577e4 | 133 | if flag & wxEXPAND or flag & wxSHAPED: |
2f90df85 | 134 | isz = wxSize(w, h) |
be2577e4 RD |
135 | else: |
136 | if flag & wxALIGN_CENTER_HORIZONTAL: | |
137 | ipt.x = x + (w - isz.width) / 2 | |
138 | elif flag & wxALIGN_RIGHT: | |
139 | ipt.x = x + (w - isz.width) | |
140 | ||
141 | if flag & wxALIGN_CENTER_VERTICAL: | |
142 | ipt.y = y + (h - isz.height) / 2 | |
143 | elif flag & wxALIGN_BOTTOM: | |
144 | ipt.y = y + (h - isz.height) | |
2f90df85 RD |
145 | |
146 | item.SetDimension(ipt, isz) | |
147 | ||
148 | ||
149 | #---------------------------------------------------------------------- | |
150 | ||
151 | ||
152 | ||
153 | class wxFlexGridSizer(wxGridSizer): | |
154 | def __init__(self, rows=0, cols=0, hgap=0, vgap=0): | |
155 | wxGridSizer.__init__(self, rows, cols, hgap, vgap) | |
156 | self.rowHeights = [] | |
157 | self.colWidths = [] | |
158 | self.growableRows = [] | |
159 | self.growableCols = [] | |
160 | ||
161 | def AddGrowableRow(self, idx): | |
162 | self.growableRows.append(idx) | |
163 | ||
164 | def AddGrowableCol(self, idx): | |
165 | self.growableCols.append(idx) | |
166 | ||
167 | #-------------------------------------------------- | |
168 | def CalcMin(self): | |
169 | items = self.GetChildren() | |
170 | nitems = len(items) | |
171 | nrows = self.rows | |
172 | ncols = self.cols | |
173 | ||
174 | if ncols > 0: | |
175 | nrows = (nitems + ncols-1) / ncols | |
176 | else: | |
177 | ncols = (nitems + nrows-1) / nrows | |
178 | ||
179 | # Find the max width and height for any component. | |
180 | self.rowHeights = [0] * nrows | |
181 | self.colWidths = [0] * ncols | |
182 | for i in range(len(items)): | |
183 | size = items[i].CalcMin() | |
184 | row = i / ncols | |
185 | col = i % ncols | |
186 | self.rowHeights[row] = max(size.height, self.rowHeights[row]) | |
187 | self.colWidths[col] = max(size.width, self.colWidths[col]) | |
188 | ||
189 | # Add up all the widths and heights | |
190 | cellsWidth = reduce(operator.__add__, self.colWidths) | |
191 | cellHeight = reduce(operator.__add__, self.rowHeights) | |
192 | ||
193 | return wxSize(cellsWidth + (ncols-1) * self.hgap, | |
194 | cellHeight + (nrows-1) * self.vgap) | |
195 | ||
196 | ||
197 | #-------------------------------------------------- | |
198 | def RecalcSizes(self): | |
199 | items = self.GetChildren() | |
200 | if not items: | |
201 | return | |
202 | ||
203 | nitems = len(items) | |
204 | nrows = self.rows | |
205 | ncols = self.cols | |
206 | ||
207 | if ncols > 0: | |
208 | nrows = (nitems + ncols-1) / ncols | |
209 | else: | |
210 | ncols = (nitems + nrows-1) / nrows | |
211 | ||
212 | minsz = self.CalcMin() | |
213 | sz = self.GetSize() | |
214 | pt = self.GetPosition() | |
215 | ||
216 | # Check for growables | |
217 | if self.growableRows and sz.height > minsz.height: | |
218 | delta = (sz.height - minsz.height) / len(self.growableRows) | |
219 | for idx in self.growableRows: | |
220 | self.rowHeights[idx] = self.rowHeights[idx] + delta | |
221 | ||
222 | if self.growableCols and sz.width > minsz.width: | |
223 | delta = (sz.width - minsz.width) / len(self.growableCols) | |
224 | for idx in self.growableCols: | |
225 | self.colWidths[idx] = self.colWidths[idx] + delta | |
226 | ||
eec92d76 RD |
227 | # bottom right corner |
228 | sz = wxSize(pt.x + sz.width, pt.y + sz.height) | |
229 | ||
2f90df85 RD |
230 | # Layout each cell |
231 | x = pt.x | |
232 | for c in range(ncols): | |
233 | y = pt.y | |
234 | for r in range(nrows): | |
235 | i = r * ncols + c | |
236 | if i < nitems: | |
237 | w = max(0, min(self.colWidths[c], sz.width - x)) | |
238 | h = max(0, min(self.rowHeights[r], sz.height - y)) | |
239 | self.SetItemBounds(items[i], x, y, w, h) | |
240 | y = y + self.rowHeights[r] + self.vgap | |
241 | x = x + self.colWidths[c] + self.hgap | |
242 | ||
243 | #---------------------------------------------------------------------- | |
244 | ||
245 | ||
246 | ||
247 | ||
248 | ||
249 |