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