1 #----------------------------------------------------------------------
2 # Name: wxPython.lib.rcsizer
3 # Purpose: RowColSizer:
5 # Author: Robin Dunn, adapted from code by Niki Spahiev
9 # Copyright: (c) 2002 by Total Control Software
10 # Licence: wxWindows license
11 #----------------------------------------------------------------------
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.
18 Adapted from code by Niki Spahiev.
23 from wxPython
.wx
import *
26 #----------------------------------------------------------------------
28 class RowColSizer(wxPySizer
):
30 # default sizes for cells with no item
35 wxPySizer
.__init
__(self
)
36 self
.growableRows
= []
37 self
.growableCols
= []
40 def AddGrowableRow(self
, idx
):
41 self
.growableRows
.append(idx
)
43 def AddGrowableCol(self
, idx
):
44 self
.growableCols
.append(idx
)
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...
52 pos
=None, size
=None, # or as tuples (row,col) and (rowspan,colspan)
58 rowspan
, colspan
= size
60 assert row
!= -1, "Row must be specified"
61 assert col
!= -1, "Column must be specified"
63 # Do I really want to do this? Probably not...
64 #if rowspan > 1 or colspan > 1:
65 # flag = flag | wxEXPAND
67 wxPySizer
.Add(self
, item
, option
, flag
, border
,
68 userData
=(row
, col
, row
+rowspan
, col
+colspan
))
73 def AddSpacer(self
, width
, height
, option
=0, flag
=0, border
=0,
81 rowspan
, colspan
= size
83 assert row
!= -1, "Row must be specified"
84 assert col
!= -1, "Column must be specified"
86 wxPySizer
.AddSpacer(self
, width
, height
, option
, flag
, border
,
87 userData
=(row
, col
, row
+rowspan
, col
+colspan
))
89 #--------------------------------------------------
90 def _add( self
, size
, dim
):
91 r
, c
, r2
, c2
= dim
# unpack coords and spanning
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
)
101 # set the widths and heights lists for this item
103 for i
in range(r
, r2
):
104 self
.rowHeights
[i
] = max( self
.rowHeights
[i
], size
.height
/ scale
)
106 for i
in range(c
, c2
):
107 self
.colWidths
[i
] = max( self
.colWidths
[i
], size
.width
/ scale
)
110 #--------------------------------------------------
112 items
= self
.GetChildren()
114 return wxSize(10, 10)
120 self
._add
( item
.CalcMin(), item
.GetUserData() )
122 size
= wxSize( reduce( operator
.add
, self
.colWidths
),
123 reduce( operator
.add
, self
.rowHeights
) )
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
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
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
152 rpos
= [0] * len(self
.rowHeights
)
153 cpos
= [0] * len(self
.colWidths
)
155 for i
in range(len(self
.rowHeights
)):
156 height
= self
.rowHeights
[i
]
160 for i
in range(len(self
.colWidths
)):
161 width
= self
.colWidths
[i
]
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
)
174 #--------------------------------------------------
175 def SetItemBounds(self
, item
, x
, y
, w
, h
):
176 # calculate the item's actual size and position within
180 flag
= item
.GetFlag()
182 if flag
& wxEXPAND
or flag
& wxSHAPED
:
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
)
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
)
195 item
.SetDimension(ipt
, isz
)
198 #----------------------------------------------------------------------
199 #----------------------------------------------------------------------
204 ## #--------------------------------------------------
205 ## def _add( self, size, opt, 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
217 ## for i in range(r,r2):
218 ## self.rows1[i] = self.rows0[i] = max( self.rows0[i], size.y/scale )
220 ## for i in range(c,c2):
221 ## self.cols1[i] = self.cols0[i] = max( self.cols0[i], size.x/scale )
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
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
233 ## #--------------------------------------------------
234 ## def CalcMin( self ):
235 ## children = self.GetChildren()
237 ## return wxSize(10, 10)
244 ## for cell in children:
245 ## self._add( cell.CalcMin(), cell.GetOption(), cell.GetUserData() )
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 )
252 ## return wxSize( self.minWidth, self.minHeight )
255 ## #--------------------------------------------------
256 ## def RecalcSizes( self ):
257 ## # get current dimensions, save for performance
258 ## myWidth = self.GetSize().x
259 ## myHeight = self.GetSize().y
261 ## # relative recent positions
262 ## px = self.GetPosition().x
263 ## py = self.GetPosition().y
265 ## # calculate space for one stretched item
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
274 ## deltaw = extraw = 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
284 ## deltah = extrah = 0
286 ## self.rpos = [0] * len( self.rows0 )
287 ## self.cpos = [0] * len( self.cols0 )
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
297 ## self.rows1[i] = newHeight
298 ## py = py + newHeight
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
308 ## self.cols1[i] = newWidth
309 ## px = px + newWidth
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) )