]>
Commit | Line | Data |
---|---|---|
d14a1e28 RD |
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 | ||
1fded56b | 202 | |
1fded56b | 203 |