]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/grids.py
Don't scroll too far if the child getting the focus is large.
[wxWidgets.git] / wxPython / wx / lib / grids.py
CommitLineData
d14a1e28
RD
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#----------------------------------------------------------------------
b881fc78
RD
13# 12/07/2003 - Jeff Grimmett (grimmtooth@softhome.net)
14#
15# o 2.5 Compatability changes
16#
d4b73b1b
RD
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#
d14a1e28
RD
28
29"""
d4b73b1b
RD
30In this module you will find PyGridSizer and PyFlexGridSizer. Please
31note that these sizers have since been ported to C++ (as wx.GridSizer
32and wx.FlexGridSizer) and those versions are now exposed in the regular
33wxPython wrappers. However I am also leaving them here in the library
34so they can serve as an example of how to implement sizers in Python.
d14a1e28 35
d4b73b1b 36PyGridSizer: Sizes and positions items such that all rows are the same
d14a1e28
RD
37height and all columns are the same width. You can specify a gap in
38pixels to be used between the rows and/or the columns. When you
39create the sizer you specify the number of rows or the number of
40columns and then as you add items it figures out the other dimension
41automatically. Like other sizers, items can be set to fill their
42available space, or to be aligned on a side, in a corner, or in the
43center of the space. When the sizer is resized, all the items are
44resized the same amount so all rows and all columns remain the same
45size.
46
d4b73b1b 47PyFlexGridSizer: Derives from PyGridSizer and adds the ability for
d14a1e28
RD
48particular rows and/or columns to be marked as growable. This means
49that when the sizer changes size, the growable rows and colums are the
50ones that stretch. The others remain at their initial size.
d14a1e28
RD
51"""
52
53
b881fc78 54import operator
d4b73b1b 55import warnings
b881fc78 56import wx
d14a1e28 57
d4b73b1b
RD
58warningmsg = 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
71warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
72
73
d14a1e28
RD
74#----------------------------------------------------------------------
75
d4b73b1b 76class PyGridSizer(wx.PySizer):
d14a1e28 77 def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
b881fc78 78 wx.PySizer.__init__(self)
d14a1e28
RD
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
b881fc78
RD
136 return wx.Size(ncols * w + (ncols-1) * self.hgap,
137 nrows * h + (nrows-1) * self.vgap)
d14a1e28
RD
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)
b881fc78 168
d14a1e28 169 y = y + h + self.vgap
b881fc78 170
d14a1e28
RD
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
b881fc78 178 ipt = wx.Point(x, y)
d14a1e28
RD
179 isz = item.CalcMin()
180 flag = item.GetFlag()
181
b881fc78
RD
182 if flag & wx.EXPAND or flag & wx.SHAPED:
183 isz = (w, h)
d14a1e28 184 else:
b881fc78 185 if flag & wx.ALIGN_CENTER_HORIZONTAL:
d14a1e28 186 ipt.x = x + (w - isz.width) / 2
b881fc78 187 elif flag & wx.ALIGN_RIGHT:
d14a1e28
RD
188 ipt.x = x + (w - isz.width)
189
b881fc78 190 if flag & wx.ALIGN_CENTER_VERTICAL:
d14a1e28 191 ipt.y = y + (h - isz.height) / 2
b881fc78 192 elif flag & wx.ALIGN_BOTTOM:
d14a1e28
RD
193 ipt.y = y + (h - isz.height)
194
195 item.SetDimension(ipt, isz)
196
197
198#----------------------------------------------------------------------
199
200
201
07ec2506 202class PyFlexGridSizer(PyGridSizer):
d14a1e28
RD
203 def __init__(self, rows=0, cols=0, hgap=0, vgap=0):
204 wxGridSizer.__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
b881fc78 231
d14a1e28
RD
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
b881fc78
RD
243 return wx.Size(cellsWidth + (ncols-1) * self.hgap,
244 cellHeight + (nrows-1) * self.vgap)
d14a1e28
RD
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
b881fc78 278 sz = wx.Size(pt.x + sz.width, pt.y + sz.height)
d14a1e28
RD
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
b881fc78 286
d14a1e28
RD
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)
b881fc78 291
d14a1e28 292 y = y + self.rowHeights[r] + self.vgap
b881fc78 293
d14a1e28
RD
294 x = x + self.colWidths[c] + self.hgap
295
296#----------------------------------------------------------------------
297
298
299
300
1fded56b 301
1fded56b 302