]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/rcsizer.py
af164089ea1fd833658197cef9331c8f2fd69d71
[wxWidgets.git] / wxPython / wxPython / lib / rcsizer.py
1 #----------------------------------------------------------------------
2 # Name: wxPython.lib.rcsizer
3 # Purpose: RowColSizer:
4 #
5 # Author: Robin Dunn, adapted from code by Niki Spahiev
6 #
7 # Created: 26-Feb-2002
8 # RCS-ID: $Id$
9 # Copyright: (c) 2002 by Total Control Software
10 # Licence: wxWindows license
11 #----------------------------------------------------------------------
12
13 """
14 A pure-Python wxSizer that lays out items in a grid similar to
15 wxFlexGridSizer but item position is not implicit but explicitly
16 specified by row and col, and row/col spanning is supported.
17
18 Adapted from code by Niki Spahiev.
19 """
20
21
22
23 from wxPython.wx import *
24 import operator
25
26 #----------------------------------------------------------------------
27
28 class RowColSizer(wxPySizer):
29
30 # default sizes for cells with no item
31 col_w = 10
32 row_h = 22
33
34 def __init__(self):
35 wxPySizer.__init__(self)
36 self.growableRows = []
37 self.growableCols = []
38
39
40 def AddGrowableRow(self, idx):
41 self.growableRows.append(idx)
42
43 def AddGrowableCol(self, idx):
44 self.growableCols.append(idx)
45
46
47
48 #--------------------------------------------------
49 def Add(self, item, option=0, flag=0, border=0,
50 row=-1, col=-1, # row, col and spanning can be specified individually...
51 rowspan=1, colspan=1,
52 pos=None, size=None, # or as tuples (row,col) and (rowspan,colspan)
53 ):
54
55 if pos is not None:
56 row, col = pos
57 if size is not None:
58 rowspan, colspan = size
59
60 assert row != -1, "Row must be specified"
61 assert col != -1, "Column must be specified"
62
63 # Do I really want to do this? Probably not...
64 #if rowspan > 1 or colspan > 1:
65 # flag = flag | wxEXPAND
66
67 wxPySizer.Add(self, item, option, flag, border,
68 userData=(row, col, row+rowspan, col+colspan))
69
70 #AddWindow = Add
71 #AddSizer = Add
72
73 def AddSpacer(self, width, height, option=0, flag=0, border=0,
74 row=-1, col=-1,
75 rowspan=1, colspan=1,
76 pos=None, size=None,
77 ):
78 if pos is not None:
79 row, col = pos
80 if size is not None:
81 rowspan, colspan = size
82
83 assert row != -1, "Row must be specified"
84 assert col != -1, "Column must be specified"
85
86 wxPySizer.AddSpacer(self, width, height, option, flag, border,
87 userData=(row, col, row+rowspan, col+colspan))
88
89 #--------------------------------------------------
90 def _add( self, size, dim ):
91 r, c, r2, c2 = dim # unpack coords and spanning
92
93 # are the widths and heights lists long enough?
94 if r2 > len(self.rowHeights):
95 x = [self.row_h] * (r2-len(self.rowHeights))
96 self.rowHeights.extend( x )
97 if c2 > len(self.colWidths):
98 x = [self.col_w] * (c2-len(self.colWidths))
99 self.colWidths.extend( x )
100
101 # set the widths and heights lists for this item
102 scale = (r2 - r)
103 for i in range(r, r2):
104 self.rowHeights[i] = max( self.rowHeights[i], size.height / scale )
105 scale = (c2 - c)
106 for i in range(c, c2):
107 self.colWidths[i] = max( self.colWidths[i], size.width / scale )
108
109
110 #--------------------------------------------------
111 def CalcMin( self ):
112 items = self.GetChildren()
113 if not items:
114 return wxSize(10, 10)
115
116 self.rowHeights = []
117 self.colWidths = []
118
119 for item in items:
120 self._add( item.CalcMin(), item.GetUserData() )
121
122 size = wxSize( reduce( operator.add, self.colWidths),
123 reduce( operator.add, self.rowHeights) )
124 return size
125
126
127 #--------------------------------------------------
128 def RecalcSizes( self ):
129 # save current dimensions, etc.
130 curWidth = self.GetSize().width
131 curHeight = self.GetSize().height
132 px = self.GetPosition().x
133 py = self.GetPosition().y
134 minWidth = self.CalcMin().width
135 minHeight = self.CalcMin().height
136
137 # Check for growables
138 if self.growableRows and curHeight > minHeight:
139 delta = (curHeight - minHeight) / len(self.growableRows)
140 extra = (curHeight - minHeight) % len(self.growableRows)
141 for idx in self.growableRows:
142 self.rowHeights[idx] += delta
143 self.rowHeights[self.growableRows[0]] += extra
144
145 if self.growableCols and curWidth > minWidth:
146 delta = (curWidth - minWidth) / len(self.growableCols)
147 extra = (curWidth - minWidth) % len(self.growableCols)
148 for idx in self.growableCols:
149 self.colWidths[idx] += delta
150 self.colWidths[self.growableCols[0]] += extra
151
152 rpos = [0] * len(self.rowHeights)
153 cpos = [0] * len(self.colWidths)
154
155 for i in range(len(self.rowHeights)):
156 height = self.rowHeights[i]
157 rpos[i] = px
158 px += height
159
160 for i in range(len(self.colWidths)):
161 width = self.colWidths[i]
162 cpos[i] = py
163 py += width
164
165 # iterate children and set dimensions...
166 for item in self.GetChildren():
167 r, c, r2, c2 = item.GetUserData()
168 width = reduce( operator.add, self.colWidths[c:c2] )
169 height = reduce( operator.add, self.rowHeights[r:r2] )
170 #item.SetDimension( (cpos[c], rpos[r]), (width, height))
171 self.SetItemBounds( item, cpos[c], rpos[r], width, height )
172
173
174 #--------------------------------------------------
175 def SetItemBounds(self, item, x, y, w, h):
176 # calculate the item's actual size and position within
177 # its grid cell
178 ipt = wxPoint(x, y)
179 isz = item.CalcMin()
180 flag = item.GetFlag()
181
182 if flag & wxEXPAND or flag & wxSHAPED:
183 isz = wxSize(w, h)
184 else:
185 if flag & wxALIGN_CENTER_HORIZONTAL:
186 ipt.x = x + (w - isz.width) / 2
187 elif flag & wxALIGN_RIGHT:
188 ipt.x = x + (w - isz.width)
189
190 if flag & wxALIGN_CENTER_VERTICAL:
191 ipt.y = y + (h - isz.height) / 2
192 elif flag & wxALIGN_BOTTOM:
193 ipt.y = y + (h - isz.height)
194
195 item.SetDimension(ipt, isz)
196
197
198 #----------------------------------------------------------------------
199 #----------------------------------------------------------------------
200
201
202
203
204 ## #--------------------------------------------------
205 ## def _add( self, size, opt, dim ):
206 ## r,c,r2,c2 = dim
207 ## if r2 > len(self.rows0):
208 ## x = [self.row_h] * (r2-len(self.rows0))
209 ## self.rows0.extend( x )
210 ## self.rows1.extend( x )
211 ## if c2 > len(self.cols0):
212 ## x = [self.col_w] * (c2-len(self.cols0))
213 ## self.cols0.extend( x )
214 ## self.cols1.extend( x )
215 ## if opt == 0: # fixed
216 ## scale = (r2-r)
217 ## for i in range(r,r2):
218 ## self.rows1[i] = self.rows0[i] = max( self.rows0[i], size.y/scale )
219 ## scale = (c2-c)
220 ## for i in range(c,c2):
221 ## self.cols1[i] = self.cols0[i] = max( self.cols0[i], size.x/scale )
222 ## else:
223 ## scale = (r2-r)
224 ## for i in range(r,r2):
225 ## self.rows0[i] = max( self.rows0[i], size.y/scale )
226 ## self.rows1[i] = self.rows0[i] * opt
227 ## scale = (c2-c)
228 ## for i in range(c,c2):
229 ## self.cols0[i] = max( self.cols0[i], size.x/scale )
230 ## self.cols1[i] = self.cols0[i] * opt
231
232
233 ## #--------------------------------------------------
234 ## def CalcMin( self ):
235 ## children = self.GetChildren()
236 ## if not children:
237 ## return wxSize(10, 10)
238
239 ## self.rows0 = []
240 ## self.cols0 = []
241 ## self.rows1 = []
242 ## self.cols1 = []
243
244 ## for cell in children:
245 ## self._add( cell.CalcMin(), cell.GetOption(), cell.GetUserData() )
246
247 ## self.minWidth = reduce( operator.add, self.cols1 )
248 ## self.minHeight = reduce( operator.add, self.rows1 )
249 ## self.fixedWidth = reduce( operator.add, self.cols0 ) # size without stretched widgets
250 ## self.fixedHeight = reduce( operator.add, self.rows0 )
251
252 ## return wxSize( self.minWidth, self.minHeight )
253
254
255 ## #--------------------------------------------------
256 ## def RecalcSizes( self ):
257 ## # get current dimensions, save for performance
258 ## myWidth = self.GetSize().x
259 ## myHeight = self.GetSize().y
260
261 ## # relative recent positions
262 ## px = self.GetPosition().x
263 ## py = self.GetPosition().y
264
265 ## # calculate space for one stretched item
266 ## stretchC = 0
267 ## for i in range(len(self.cols0)):
268 ## if self.cols1[i] <> self.cols0[i]:
269 ## stretchC = stretchC + self.cols1[i] / self.cols0[i]
270 ## if myWidth > self.fixedWidth and stretchC:
271 ## deltaw = (myWidth - self.fixedWidth) / stretchC
272 ## extraw = (myWidth - self.fixedWidth) % stretchC
273 ## else:
274 ## deltaw = extraw = 0
275
276 ## stretchR = 0
277 ## for i in range(len(self.rows0)):
278 ## if self.rows1[i] <> self.rows0[i]:
279 ## stretchR = stretchR + self.rows1[i] / self.rows0[i]
280 ## if myHeight > self.fixedHeight and stretchR:
281 ## deltah = (myHeight - self.fixedHeight) / stretchR
282 ## extrah = (myHeight - self.fixedHeight) % stretchR
283 ## else:
284 ## deltah = extrah = 0
285
286 ## self.rpos = [0] * len( self.rows0 )
287 ## self.cpos = [0] * len( self.cols0 )
288
289 ## for i in range(len(self.rows0)):
290 ## newHeight = self.rows0[i]
291 ## if self.rows1[i] <> self.rows0[i]:
292 ## weight = self.rows1[i] / self.rows0[i]
293 ## # first stretchable gets extra pixels
294 ## newHeight = newHeight + (deltah * weight) + extrah
295 ## extrah = 0
296 ## self.rpos[i] = py
297 ## self.rows1[i] = newHeight
298 ## py = py + newHeight
299
300 ## for i in range(len(self.cols0)):
301 ## newWidth = self.cols0[i]
302 ## if self.cols1[i] <> self.cols0[i]:
303 ## weight = self.cols1[i] / self.cols0[i]
304 ## # first stretchable gets extra pixels
305 ## newWidth = newWidth + (deltaw * weight) + extraw
306 ## extraw = 0
307 ## self.cpos[i] = px
308 ## self.cols1[i] = newWidth
309 ## px = px + newWidth
310
311 ## # iterate children ...
312 ## for cell in self.GetChildren():
313 ## r,c,r2,c2 = cell.GetUserData()
314 ## newWidth = reduce( operator.add, self.cols1[c:c2] )
315 ## newHeight = reduce( operator.add, self.rows1[r:r2] )
316 ## cell.SetDimension( (self.cpos[c], self.rpos[r]), (newWidth, newHeight) )
317