]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/grids.py
GetNumberOfLines on GTK doesn't count wrapped lines again...
[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 # 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
14 #
15 # o 2.5 Compatability changes
16 #
17 # 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
18 #
19 # o In keeping with the common idiom, the sizers in this module
20 # have been given the 'Py' prefix to avoid confusion with the
21 # native sizers of the same name. However, the reverse renamer
22 # still has the old wx*Sizer since the whole point of the
23 # reverse renamer is backward compatability.
24 # o wxGridSizer -> PyGridSizer
25 # o wxFlexGridSizer -> PyFlexGridSizer
26 # o Deprecation warning added.
27 #
28
29 """
30 In this module you will find PyGridSizer and PyFlexGridSizer. Please
31 note that these sizers have since been ported to C++ (as wx.GridSizer
32 and wx.FlexGridSizer) and those versions are now exposed in the regular
33 wxPython wrappers. However I am also leaving them here in the library
34 so they can serve as an example of how to implement sizers in Python.
35
36 PyGridSizer: Sizes and positions items such that all rows are the same
37 height and all columns are the same width. You can specify a gap in
38 pixels to be used between the rows and/or the columns. When you
39 create the sizer you specify the number of rows or the number of
40 columns and then as you add items it figures out the other dimension
41 automatically. Like other sizers, items can be set to fill their
42 available space, or to be aligned on a side, in a corner, or in the
43 center of the space. When the sizer is resized, all the items are
44 resized the same amount so all rows and all columns remain the same
45 size.
46
47 PyFlexGridSizer: Derives from PyGridSizer and adds the ability for
48 particular rows and/or columns to be marked as growable. This means
49 that when the sizer changes size, the growable rows and colums are the
50 ones that stretch. The others remain at their initial size.
51 """
52
53
54 import operator
55 import warnings
56 import wx
57
58 warningmsg = r"""\
59
60 ################################################\
61 # THIS MODULE IS DEPRECATED |
62 # |
63 # You should use the native wx.GridSizer and |
64 # wx.FlexGridSizer unless there is a compelling |
65 # need to use this module. |
66 ################################################/
67
68
69 """
70
71 warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
72
73
74 #----------------------------------------------------------------------
75
76 class PyGridSizer(wx.PySizer):
77 def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
78 wx.PySizer.__init__(self)
79 if rows == 0 and cols == 0:
80 raise ValueError, "rows and cols cannot both be zero"
81
82 self.rows = rows
83 self.cols = cols
84 self.hgap = hgap
85 self.vgap = vgap
86
87
88 def SetRows(self, rows):
89 if rows == 0 and self.cols == 0:
90 raise ValueError, "rows and cols cannot both be zero"
91 self.rows = rows
92
93 def SetColumns(self, cols):
94 if self.rows == 0 and cols == 0:
95 raise ValueError, "rows and cols cannot both be zero"
96 self.cols = cols
97
98 def GetRows(self):
99 return self.rows
100
101 def GetColumns(self):
102 return self.cols
103
104 def SetHgap(self, hgap):
105 self.hgap = hgap
106
107 def SetVgap(self, vgap):
108 self.vgap = vgap
109
110 def GetHgap(self, hgap):
111 return self.hgap
112
113 def GetVgap(self, vgap):
114 return self.vgap
115
116 #--------------------------------------------------
117 def CalcMin(self):
118 items = self.GetChildren()
119 nitems = len(items)
120 nrows = self.rows
121 ncols = self.cols
122
123 if ncols > 0:
124 nrows = (nitems + ncols-1) / ncols
125 else:
126 ncols = (nitems + nrows-1) / nrows
127
128 # Find the max width and height for any component.
129 w = 0
130 h = 0
131 for item in items:
132 size = item.CalcMin()
133 w = max(w, size.width)
134 h = max(h, size.height)
135
136 return wx.Size(ncols * w + (ncols-1) * self.hgap,
137 nrows * h + (nrows-1) * self.vgap)
138
139
140 #--------------------------------------------------
141 def RecalcSizes(self):
142 items = self.GetChildren()
143 if not items:
144 return
145
146 nitems = len(items)
147 nrows = self.rows
148 ncols = self.cols
149
150 if ncols > 0:
151 nrows = (nitems + ncols-1) / ncols
152 else:
153 ncols = (nitems + nrows-1) / nrows
154
155
156 sz = self.GetSize()
157 pt = self.GetPosition()
158 w = (sz.width - (ncols - 1) * self.hgap) / ncols;
159 h = (sz.height - (nrows - 1) * self.vgap) / nrows;
160
161 x = pt.x
162 for c in range(ncols):
163 y = pt.y
164 for r in range(nrows):
165 i = r * ncols + c
166 if i < nitems:
167 self.SetItemBounds(items[i], x, y, w, h)
168
169 y = y + h + self.vgap
170
171 x = x + w + self.hgap
172
173
174 #--------------------------------------------------
175 def SetItemBounds(self, item, x, y, w, h):
176 # calculate the item's size and position within
177 # its grid cell
178 ipt = wx.Point(x, y)
179 isz = item.CalcMin()
180 flag = item.GetFlag()
181
182 if flag & wx.EXPAND or flag & wx.SHAPED:
183 isz = (w, h)
184 else:
185 if flag & wx.ALIGN_CENTER_HORIZONTAL:
186 ipt.x = x + (w - isz.width) / 2
187 elif flag & wx.ALIGN_RIGHT:
188 ipt.x = x + (w - isz.width)
189
190 if flag & wx.ALIGN_CENTER_VERTICAL:
191 ipt.y = y + (h - isz.height) / 2
192 elif flag & wx.ALIGN_BOTTOM:
193 ipt.y = y + (h - isz.height)
194
195 item.SetDimension(ipt, isz)
196
197
198 #----------------------------------------------------------------------
199
200
201
202 class PyFlexGridSizer(PyGridSizer):
203 def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
204 PyGridSizer.__init__(self, rows, cols, hgap, vgap)
205 self.rowHeights = []
206 self.colWidths = []
207 self.growableRows = []
208 self.growableCols = []
209
210 def AddGrowableRow(self, idx):
211 self.growableRows.append(idx)
212
213 def AddGrowableCol(self, idx):
214 self.growableCols.append(idx)
215
216 #--------------------------------------------------
217 def CalcMin(self):
218 items = self.GetChildren()
219 nitems = len(items)
220 nrows = self.rows
221 ncols = self.cols
222
223 if ncols > 0:
224 nrows = (nitems + ncols-1) / ncols
225 else:
226 ncols = (nitems + nrows-1) / nrows
227
228 # Find the max width and height for any component.
229 self.rowHeights = [0] * nrows
230 self.colWidths = [0] * ncols
231
232 for i in range(len(items)):
233 size = items[i].CalcMin()
234 row = i / ncols
235 col = i % ncols
236 self.rowHeights[row] = max(size.height, self.rowHeights[row])
237 self.colWidths[col] = max(size.width, self.colWidths[col])
238
239 # Add up all the widths and heights
240 cellsWidth = reduce(operator.__add__, self.colWidths)
241 cellHeight = reduce(operator.__add__, self.rowHeights)
242
243 return wx.Size(cellsWidth + (ncols-1) * self.hgap,
244 cellHeight + (nrows-1) * self.vgap)
245
246
247 #--------------------------------------------------
248 def RecalcSizes(self):
249 items = self.GetChildren()
250 if not items:
251 return
252
253 nitems = len(items)
254 nrows = self.rows
255 ncols = self.cols
256
257 if ncols > 0:
258 nrows = (nitems + ncols-1) / ncols
259 else:
260 ncols = (nitems + nrows-1) / nrows
261
262 minsz = self.CalcMin()
263 sz = self.GetSize()
264 pt = self.GetPosition()
265
266 # Check for growables
267 if self.growableRows and sz.height > minsz.height:
268 delta = (sz.height - minsz.height) / len(self.growableRows)
269 for idx in self.growableRows:
270 self.rowHeights[idx] = self.rowHeights[idx] + delta
271
272 if self.growableCols and sz.width > minsz.width:
273 delta = (sz.width - minsz.width) / len(self.growableCols)
274 for idx in self.growableCols:
275 self.colWidths[idx] = self.colWidths[idx] + delta
276
277 # bottom right corner
278 sz = wx.Size(pt.x + sz.width, pt.y + sz.height)
279
280 # Layout each cell
281 x = pt.x
282 for c in range(ncols):
283 y = pt.y
284 for r in range(nrows):
285 i = r * ncols + c
286
287 if i < nitems:
288 w = max(0, min(self.colWidths[c], sz.width - x))
289 h = max(0, min(self.rowHeights[r], sz.height - y))
290 self.SetItemBounds(items[i], x, y, w, h)
291
292 y = y + self.rowHeights[r] + self.vgap
293
294 x = x + self.colWidths[c] + self.hgap
295
296 #----------------------------------------------------------------------
297
298
299
300
301
302