]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/rcsizer.py
Merged the wxPy_newswig branch into the HEAD branch (main trunk)
[wxWidgets.git] / wxPython / wx / 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 If anyone is interested, it would be nice to have this ported to C++.
21 """
22
23
24
25 from wxPython.wx import *
26 import operator
27
28 #----------------------------------------------------------------------
29
30 class RowColSizer(wxPySizer):
31
32 # default sizes for cells with no item
33 col_w = 10
34 row_h = 22
35
36 def __init__(self):
37 wxPySizer.__init__(self)
38 self.growableRows = []
39 self.growableCols = []
40
41
42 def AddGrowableRow(self, idx):
43 self.growableRows.append(idx)
44
45 def AddGrowableCol(self, idx):
46 self.growableCols.append(idx)
47
48
49
50 #--------------------------------------------------
51 def Add(self, item, option=0, flag=0, border=0,
52 row=-1, col=-1, # row, col and spanning can be specified individually...
53 rowspan=1, colspan=1,
54 pos=None, size=None, # or as tuples (row,col) and (rowspan,colspan)
55 ):
56
57 if pos is not None:
58 row, col = pos
59 if size is not None:
60 rowspan, colspan = size
61
62 assert row != -1, "Row must be specified"
63 assert col != -1, "Column must be specified"
64
65 # Do I really want to do this? Probably not...
66 #if rowspan > 1 or colspan > 1:
67 # flag = flag | wxEXPAND
68
69 wxPySizer.Add(self, item, option, flag, border,
70 userData=(row, col, row+rowspan, col+colspan))
71
72 #AddWindow = Add
73 #AddSizer = Add
74
75 def AddSpacer(self, width, height, option=0, flag=0, border=0,
76 row=-1, col=-1,
77 rowspan=1, colspan=1,
78 pos=None, size=None,
79 ):
80 if pos is not None:
81 row, col = pos
82 if size is not None:
83 rowspan, colspan = size
84
85 assert row != -1, "Row must be specified"
86 assert col != -1, "Column must be specified"
87
88 wxPySizer.AddSpacer(self, width, height, option, flag, border,
89 userData=(row, col, row+rowspan, col+colspan))
90
91 #--------------------------------------------------
92 def _add( self, size, dim ):
93 r, c, r2, c2 = dim # unpack coords and spanning
94
95 # are the widths and heights lists long enough?
96 if r2 > len(self.rowHeights):
97 x = [self.row_h] * (r2-len(self.rowHeights))
98 self.rowHeights.extend( x )
99 if c2 > len(self.colWidths):
100 x = [self.col_w] * (c2-len(self.colWidths))
101 self.colWidths.extend( x )
102
103 # set the widths and heights lists for this item
104 scale = (r2 - r)
105 for i in range(r, r2):
106 self.rowHeights[i] = max( self.rowHeights[i], size.height / scale )
107 scale = (c2 - c)
108 for i in range(c, c2):
109 self.colWidths[i] = max( self.colWidths[i], size.width / scale )
110
111
112 #--------------------------------------------------
113 def CalcMin( self ):
114 self.rowHeights = []
115 self.colWidths = []
116
117 items = self.GetChildren()
118 if not items:
119 return wxSize(10, 10)
120
121 for item in items:
122 self._add( item.CalcMin(), item.GetUserData() )
123
124 size = wxSize( reduce( operator.add, self.colWidths),
125 reduce( operator.add, self.rowHeights) )
126 return size
127
128
129 #--------------------------------------------------
130 def RecalcSizes( self ):
131 # save current dimensions, etc.
132 curWidth = self.GetSize().width
133 curHeight = self.GetSize().height
134 px = self.GetPosition().x
135 py = self.GetPosition().y
136 minWidth = self.CalcMin().width
137 minHeight = self.CalcMin().height
138
139 # Check for growables
140 if self.growableRows and curHeight > minHeight:
141 delta = (curHeight - minHeight) / len(self.growableRows)
142 extra = (curHeight - minHeight) % len(self.growableRows)
143 for idx in self.growableRows:
144 self.rowHeights[idx] += delta
145 self.rowHeights[self.growableRows[0]] += extra
146
147 if self.growableCols and curWidth > minWidth:
148 delta = (curWidth - minWidth) / len(self.growableCols)
149 extra = (curWidth - minWidth) % len(self.growableCols)
150 for idx in self.growableCols:
151 self.colWidths[idx] += delta
152 self.colWidths[self.growableCols[0]] += extra
153
154 rpos = [0] * len(self.rowHeights)
155 cpos = [0] * len(self.colWidths)
156
157 for i in range(len(self.rowHeights)):
158 height = self.rowHeights[i]
159 rpos[i] = py
160 py += height
161
162 for i in range(len(self.colWidths)):
163 width = self.colWidths[i]
164 cpos[i] = px
165 px += width
166
167 # iterate children and set dimensions...
168 for item in self.GetChildren():
169 r, c, r2, c2 = item.GetUserData()
170 width = reduce( operator.add, self.colWidths[c:c2] )
171 height = reduce( operator.add, self.rowHeights[r:r2] )
172 self.SetItemBounds( item, cpos[c], rpos[r], width, height )
173
174
175 #--------------------------------------------------
176 def SetItemBounds(self, item, x, y, w, h):
177 # calculate the item's actual size and position within
178 # its grid cell
179 ipt = wxPoint(x, y)
180 isz = item.CalcMin()
181 flag = item.GetFlag()
182
183 if flag & wxEXPAND or flag & wxSHAPED:
184 isz = wxSize(w, h)
185 else:
186 if flag & wxALIGN_CENTER_HORIZONTAL:
187 ipt.x = x + (w - isz.width) / 2
188 elif flag & wxALIGN_RIGHT:
189 ipt.x = x + (w - isz.width)
190
191 if flag & wxALIGN_CENTER_VERTICAL:
192 ipt.y = y + (h - isz.height) / 2
193 elif flag & wxALIGN_BOTTOM:
194 ipt.y = y + (h - isz.height)
195
196 item.SetDimension(ipt, isz)
197
198
199 #----------------------------------------------------------------------
200 #----------------------------------------------------------------------
201
202
203