]>
Commit | Line | Data |
---|---|---|
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 | # 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net) | |
13 | # | |
14 | # o 2.5 compatability update. | |
15 | # o There appears to be a prob with the wx.PySizer.GetSize() method. | |
16 | # | |
17 | # 12/23/2003 - Jeff Grimmett (grimmtooth@softhome.net) | |
18 | # | |
19 | # o wx.PySizer.GetSize() method working right now. | |
20 | # | |
21 | ||
22 | """ | |
23 | A pure-Python Sizer that lays out items in a grid similar to | |
24 | wx.FlexGridSizer but item position is not implicit but explicitly | |
25 | specified by row and col, and row/col spanning is supported. | |
26 | ||
27 | Adapted from code by Niki Spahiev. | |
28 | ||
29 | NOTE: There is now a C++ version of this class that has been wrapped | |
30 | as wx.GridBagSizer. It is quicker and more capable so you are | |
31 | encouraged to switch. | |
32 | """ | |
33 | ||
34 | import operator | |
35 | import wx | |
36 | ||
37 | ||
38 | # After the lib and demo no longer uses this sizer enable this warning... | |
39 | ||
40 | ## import warnings | |
41 | ## warningmsg = r"""\ | |
42 | ||
43 | ## #####################################################\ | |
44 | ## # THIS MODULE IS NOW DEPRECATED | | |
45 | ## # | | |
46 | ## # The core wx library now contains a similar class | | |
47 | ## # wrapped as wx.GridBagSizer. | | |
48 | ## #####################################################/ | |
49 | ||
50 | ## """ | |
51 | ||
52 | ## warnings.warn(warningmsg, DeprecationWarning, stacklevel=2) | |
53 | ||
54 | #---------------------------------------------------------------------- | |
55 | ||
56 | class RowColSizer(wx.PySizer): | |
57 | ||
58 | # default sizes for cells with no item | |
59 | col_w = 10 | |
60 | row_h = 22 | |
61 | ||
62 | def __init__(self): | |
63 | wx.PySizer.__init__(self) | |
64 | self.growableRows = [] | |
65 | self.growableCols = [] | |
66 | ||
67 | ||
68 | def AddGrowableRow(self, idx): | |
69 | self.growableRows.append(idx) | |
70 | ||
71 | def AddGrowableCol(self, idx): | |
72 | self.growableCols.append(idx) | |
73 | ||
74 | ||
75 | ||
76 | #-------------------------------------------------- | |
77 | def Add(self, item, option=0, flag=0, border=0, | |
78 | # row, col and spanning can be specified individually... | |
79 | row=-1, col=-1, | |
80 | rowspan=1, colspan=1, | |
81 | # or as tuples (row,col) and (rowspan,colspan) | |
82 | pos=None, size=None, | |
83 | ): | |
84 | ||
85 | if pos is not None: | |
86 | row, col = pos | |
87 | if size is not None: | |
88 | rowspan, colspan = size | |
89 | ||
90 | assert row != -1, "Row must be specified" | |
91 | assert col != -1, "Column must be specified" | |
92 | ||
93 | # Do I really want to do this? Probably not... | |
94 | #if rowspan > 1 or colspan > 1: | |
95 | # flag = flag | wx.EXPAND | |
96 | ||
97 | wx.PySizer.Add(self, item, option, flag, border, | |
98 | userData=(row, col, row+rowspan, col+colspan)) | |
99 | ||
100 | #AddWindow = Add | |
101 | #AddSizer = Add | |
102 | ||
103 | def AddSpacer(self, width, height, option=0, flag=0, border=0, | |
104 | row=-1, col=-1, | |
105 | rowspan=1, colspan=1, | |
106 | pos=None, size=None, | |
107 | ): | |
108 | if pos is not None: | |
109 | row, col = pos | |
110 | if size is not None: | |
111 | rowspan, colspan = size | |
112 | ||
113 | assert row != -1, "Row must be specified" | |
114 | assert col != -1, "Column must be specified" | |
115 | ||
116 | wx.PySizer.AddSpacer(self, (width, height), option, flag, border, | |
117 | userData=(row, col, row+rowspan, col+colspan)) | |
118 | ||
119 | #-------------------------------------------------- | |
120 | def _add( self, size, dim ): | |
121 | r, c, r2, c2 = dim # unpack coords and spanning | |
122 | ||
123 | # are the widths and heights lists long enough? | |
124 | if r2 > len(self.rowHeights): | |
125 | x = [self.row_h] * (r2-len(self.rowHeights)) | |
126 | self.rowHeights.extend( x ) | |
127 | if c2 > len(self.colWidths): | |
128 | x = [self.col_w] * (c2-len(self.colWidths)) | |
129 | self.colWidths.extend( x ) | |
130 | ||
131 | # set the widths and heights lists for this item | |
132 | scale = (r2 - r) | |
133 | for i in range(r, r2): | |
134 | self.rowHeights[i] = max( self.rowHeights[i], size.height / scale ) | |
135 | scale = (c2 - c) | |
136 | for i in range(c, c2): | |
137 | self.colWidths[i] = max( self.colWidths[i], size.width / scale ) | |
138 | ||
139 | ||
140 | #-------------------------------------------------- | |
141 | def CalcMin( self ): | |
142 | self.rowHeights = [] | |
143 | self.colWidths = [] | |
144 | ||
145 | items = self.GetChildren() | |
146 | if not items: | |
147 | return wx.Size(10, 10) | |
148 | ||
149 | for item in items: | |
150 | self._add( item.CalcMin(), item.GetUserData() ) | |
151 | ||
152 | size = wx.Size( reduce( operator.add, self.colWidths), | |
153 | reduce( operator.add, self.rowHeights) ) | |
154 | return size | |
155 | ||
156 | ||
157 | #-------------------------------------------------- | |
158 | def RecalcSizes( self ): | |
159 | # save current dimensions, etc. | |
160 | curWidth, curHeight = self.GetSize() | |
161 | px, py = self.GetPosition() | |
162 | minWidth, minHeight = self.CalcMin() | |
163 | ||
164 | # Check for growables | |
165 | if self.growableRows and curHeight > minHeight: | |
166 | delta = (curHeight - minHeight) / len(self.growableRows) | |
167 | extra = (curHeight - minHeight) % len(self.growableRows) | |
168 | for idx in self.growableRows: | |
169 | self.rowHeights[idx] += delta | |
170 | self.rowHeights[self.growableRows[0]] += extra | |
171 | ||
172 | if self.growableCols and curWidth > minWidth: | |
173 | delta = (curWidth - minWidth) / len(self.growableCols) | |
174 | extra = (curWidth - minWidth) % len(self.growableCols) | |
175 | for idx in self.growableCols: | |
176 | self.colWidths[idx] += delta | |
177 | self.colWidths[self.growableCols[0]] += extra | |
178 | ||
179 | rpos = [0] * len(self.rowHeights) | |
180 | cpos = [0] * len(self.colWidths) | |
181 | ||
182 | for i in range(len(self.rowHeights)): | |
183 | height = self.rowHeights[i] | |
184 | rpos[i] = py | |
185 | py += height | |
186 | ||
187 | for i in range(len(self.colWidths)): | |
188 | width = self.colWidths[i] | |
189 | cpos[i] = px | |
190 | px += width | |
191 | ||
192 | # iterate children and set dimensions... | |
193 | for item in self.GetChildren(): | |
194 | r, c, r2, c2 = item.GetUserData() | |
195 | width = reduce( operator.add, self.colWidths[c:c2] ) | |
196 | height = reduce( operator.add, self.rowHeights[r:r2] ) | |
197 | self.SetItemBounds( item, cpos[c], rpos[r], width, height ) | |
198 | ||
199 | ||
200 | #-------------------------------------------------- | |
201 | def SetItemBounds(self, item, x, y, w, h): | |
202 | # calculate the item's actual size and position within | |
203 | # its grid cell | |
204 | ipt = wx.Point(x, y) | |
205 | isz = item.CalcMin() | |
206 | flag = item.GetFlag() | |
207 | ||
208 | if flag & wx.EXPAND or flag & wx.SHAPED: | |
209 | isz = wx.Size(w, h) | |
210 | else: | |
211 | if flag & wx.ALIGN_CENTER_HORIZONTAL: | |
212 | ipt.x = x + (w - isz.width) / 2 | |
213 | elif flag & wx.ALIGN_RIGHT: | |
214 | ipt.x = x + (w - isz.width) | |
215 | ||
216 | if flag & wx.ALIGN_CENTER_VERTICAL: | |
217 | ipt.y = y + (h - isz.height) / 2 | |
218 | elif flag & wx.ALIGN_BOTTOM: | |
219 | ipt.y = y + (h - isz.height) | |
220 | ||
221 | item.SetDimension(ipt, isz) | |
222 | ||
223 | ||
224 | #---------------------------------------------------------------------- | |
225 | #---------------------------------------------------------------------- | |
226 | ||
227 | ||
228 |