]> git.saurik.com Git - wxWidgets.git/blob - utils/wxPython/lib/layoutf.py
Added wrapper for wxListCtrl.SortItems. Added column sorting to the
[wxWidgets.git] / utils / wxPython / lib / layoutf.py
1 from wxPython.wx import wxLayoutConstraints,\
2 wxTop, wxLeft, wxBottom, wxRight, \
3 wxHeight, wxWidth, wxCentreX, wxCentreY
4 import re,string
5
6 class Layoutf(wxLayoutConstraints):
7 """
8 The class Layoutf(wxLayoutConstraints) presents a simplification
9 of the wxLayoutConstraints syntax. The name Layoutf is choosen
10 because of the similarity with C's printf function.
11
12 Quick Example:
13
14 lc = Layoutf('t=t#1;l=r10#2;r!100;h%h50#1', (self, self.panel))
15
16 is equivalent to
17
18 lc = wxLayoutContraints()
19 lc.top.SameAs(self, wxTop)
20 lc.left.SameAs(self.panel, wxRight, 10)
21 lc.right.Absolute(100)
22 lc.height.PercentOf(self, wxHeight, 50)
23
24 Usage:
25
26 You can give a constraint string to the Layoutf constructor,
27 or use the 'pack' method. The following are equivalent:
28
29 lc = Layoutf('t=t#1;l=r#2;r!100;h%h50#1', (self, self.panel))
30
31 and
32
33 lc = Layoutf()
34 lc.pack('t=t#1;l=r#2;r!100;h%h50#1', (self, self.panel))
35
36 Besides 'pack' there's also 'debug_pack' which does not set
37 constraints, but prints traditional wxLayoutConstraint calls to
38 stdout.
39
40 The calls to the Layoutf constructor and pack methods have
41 the following argument list:
42
43 (constraint_string, objects_tuple)
44
45 Constraint String syntax:
46
47 Constraint directives are separated by semi-colons. You
48 generally (always?) need four directives to completely describe a
49 subwindow's location.
50
51 A single directive has either of the following forms:
52
53 1. <own attribute><compare operation>[numerical argument]
54 for example r!100 -> lc.right.Absolute(100) )
55 and w* -> lc.width.AsIs()
56
57 2. <own attribute><compare operation>[numerical argument]
58 #<compare object nr.>
59 for example t_10#2 (lc.top.Below(<second obj>, 10)
60
61 3. <own attribute><compare operation><compare attribute>
62 [numerical argument]#<compare object nr.>
63 for example w%h50#2 ( lc.width.PercentOf(<second obj>,
64 wxHeight, 50) and t=b#1 ( lc.top.SameAs(<first obj>,
65 wxBottom) )
66
67 Which one you need is defined by the <compare operation>
68 type. The following take type 1 (no object to compare with):
69
70 '!': 'Absolute', '?': 'Unconstrained', '*': 'AsIs'
71
72 These take type 2 (need to be compared with another object)
73
74 '<': 'LeftOf', '>': 'RightOf', '^': 'Above', '_': 'Below'
75
76 These take type 3 (need to be compared to another object
77 attribute)
78
79 '=': 'SameAs', '%': 'PercentOf'
80
81 For all types, the <own attribute> letter can be any of
82
83 't': 'top', 'l': 'left', 'b': 'bottom',
84 'r': 'right', 'h': 'height', 'w': 'width',
85 'x': 'centreX', 'y': 'centreY'
86
87 If the operation takes an (optional) numerical argument, place it
88 in [numerical argument]. For type 3 directives, the <compare
89 attribute> letter can be any of
90
91 't': 'wxTop', 'l': 'wxLeft', 'b': 'wxBottom'
92 'r': 'wxRight', 'h': 'wxHeight', 'w': 'wxWidth',
93 'x': 'wxCentreX', 'y': 'wxCentreY'
94
95 Note that these are the same letters as used for <own attribute>,
96 so you'll only need to remember one set. Finally, the object
97 whose attribute is refered to, is specified by #<compare object
98 nr>, where <compare object nr> is the 1-based (stupid, I know,
99 but I've gotten used to it) index of the object in the
100 objects_tuple argument.
101
102 Bugs:
103
104 Not entirely happy about the logic in the order of arguments
105 after the <compare operation> character.
106
107 Not all wxLayoutConstraint methods are included in the
108 syntax. However, the type 3 directives are generally the most
109 used. Further excuse: wxWindows layout constraints are at the
110 time of this writing not documented.
111
112 """
113
114 attr_d = { 't': 'top', 'l': 'left', 'b': 'bottom',
115 'r': 'right', 'h': 'height', 'w': 'width',
116 'x': 'centreX', 'y': 'centreY' }
117 op_d = { '=': 'SameAs', '%': 'PercentOf', '<': 'LeftOf',
118 '>': 'RightOf', '^': 'Above', '_': 'Below',
119 '!': 'Absolute', '?': 'Unconstrained', '*': 'AsIs' }
120 cmp_d = { 't': 'wxTop', 'l': 'wxLeft', 'b': 'wxBottom',
121 'r': 'wxRight', 'h': 'wxHeight', 'w': 'wxWidth',
122 'x': 'wxCentreX', 'y': 'wxCentreY' }
123
124 rexp1 = re.compile('^\s*([tlrbhwxy])\s*([!\?\*])\s*(\d*)\s*$')
125 rexp2 = re.compile('^\s*([tlrbhwxy])\s*([=%<>^_])\s*([tlrbhwxy]?)\s*(\d*)\s*#(\d+)\s*$')
126
127 def __init__(self,pstr=None,winlist=None):
128 wxLayoutConstraints.__init__(self)
129 if pstr:
130 self.pack(pstr,winlist)
131
132 def pack(self, pstr, winlist):
133 pstr = string.lower(pstr)
134 for item in string.split(pstr,';'):
135 m = self.rexp1.match(item)
136 if m:
137 g = list(m.groups())
138 attr = getattr(self, self.attr_d[g[0]])
139 func = getattr(attr, self.op_d[g[1]])
140 if g[1] == '!':
141 func(int(g[2]))
142 else:
143 func()
144 continue
145 m = self.rexp2.match(item)
146 if not m: raise ValueError
147 g = list(m.groups())
148 attr = getattr(self, self.attr_d[g[0]])
149 func = getattr(attr, self.op_d[g[1]])
150 if g[3]: g[3] = int(g[3])
151 else: g[3] = None;
152 g[4] = int(g[4]) - 1
153 if g[1] in '<>^_':
154 if g[3]: func(winlist[g[4]], g[3])
155 else: func(winlist[g[4]])
156 else:
157 cmp = eval(self.cmp_d[g[2]])
158 if g[3]: func(winlist[g[4]], cmp, g[3])
159 else: func(winlist[g[4]], cmp)
160
161 def debug_pack(self, pstr, winlist):
162 pstr = string.lower(pstr)
163 for item in string.split(pstr,';'):
164 m = self.rexp1.match(item)
165 if m:
166 g = list(m.groups())
167 attr = getattr(self, self.attr_d[g[0]])
168 func = getattr(attr, self.op_d[g[1]])
169 if g[1] == '!':
170 print "%s.%s.%s(%s)" % \
171 ('self',self.attr_d[g[0]],self.op_d[g[1]],g[2])
172 else:
173 print "%s.%s.%s()" % \
174 ('self',self.attr_d[g[0]],self.op_d[g[1]])
175 continue
176 m = self.rexp2.match(item)
177 if not m: raise ValueError
178 g = list(m.groups())
179 if g[3]: g[3] = int(g[3])
180 else: g[3] = 0;
181 g[4] = int(g[4]) - 1
182 if g[1] in '<>^_':
183 if g[3]: print "%s.%s.%s(%s,%d)" % \
184 ('self',self.attr_d[g[0]],self.op_d[g[1]],winlist[g[4]],
185 g[3])
186 else: print "%s.%s.%s(%s)" % \
187 ('self',self.attr_d[g[0]],self.op_d[g[1]],winlist[g[4]])
188 else:
189 if g[3]: print "%s.%s.%s(%s,%s,%d)" % \
190 ('self',self.attr_d[g[0]],self.op_d[g[1]],winlist[g[4]],
191 self.cmp_d[g[2]],g[3])
192 else: print "%s.%s.%s(%s,%s)" % \
193 ('self',self.attr_d[g[0]],self.op_d[g[1]],winlist[g[4]],
194 self.cmp_d[g[2]])
195
196 if __name__=='__main__':
197 from wxPython.wx import *
198
199 class TestLayoutf(wxFrame):
200 def __init__(self, parent):
201 wxFrame.__init__(self, parent, -1, 'Test Layout Constraints',
202 wxPyDefaultPosition, wxSize(500, 300))
203
204 self.SetAutoLayout(true)
205 EVT_BUTTON(self, 100, self.OnButton)
206 EVT_BUTTON(self, 101, self.OnAbout)
207
208 self.panelA = wxWindow(self, -1, wxPyDefaultPosition, wxPyDefaultSize, wxSIMPLE_BORDER)
209 self.panelA.SetBackgroundColour(wxBLUE)
210 self.panelA.SetConstraints(Layoutf('t=t10#1;l=l10#1;b=b10#1;r%r50#1',(self,)))
211
212 self.panelB = wxWindow(self, -1, wxPyDefaultPosition, wxPyDefaultSize, wxSIMPLE_BORDER)
213 self.panelB.SetBackgroundColour(wxRED)
214 self.panelB.SetConstraints(Layoutf('t=t10#1;r=r10#1;b%b30#1;l>10#2', (self,self.panelA)))
215
216 self.panelC = wxWindow(self, -1, wxPyDefaultPosition, wxPyDefaultSize, wxSIMPLE_BORDER)
217 self.panelC.SetBackgroundColour(wxWHITE)
218 self.panelC.SetConstraints(Layoutf('t_10#3;r=r10#1;b=b10#1;l>10#2', (self,self.panelA,self.panelB)))
219
220 b = wxButton(self.panelA, 101, ' About: ')
221 b.SetConstraints(Layoutf('X=X#1;Y=Y#1;h*;w%w50#1', (self.panelA,)))
222
223 b = wxButton(self.panelB, 100, ' Panel B ')
224 b.SetConstraints(Layoutf('t=t2#1;r=r4#1;h*;w*', (self.panelB,)))
225
226 self.panelD = wxWindow(self.panelC, -1, wxPyDefaultPosition, wxPyDefaultSize, wxSIMPLE_BORDER)
227 self.panelD.SetBackgroundColour(wxGREEN)
228 self.panelD.SetConstraints(Layoutf('b%h50#1;r%w50#1;h=h#2;w=w#2', (self.panelC, b)))
229
230 b = wxButton(self.panelC, 100, ' Panel C ')
231 b.SetConstraints(Layoutf('t_#1;l>#1;h*;w*', (self.panelD,)))
232
233 wxStaticText(self.panelD, -1, "Panel D", wxPoint(4, 4)).SetBackgroundColour(wxGREEN)
234
235 def OnButton(self, event):
236 self.Close(true)
237
238 def OnAbout(self, event):
239 try:
240 from dialogs import wxScrolledMessageDialog
241 msg = wxScrolledMessageDialog(self, Layoutf.__doc__, "about")
242 msg.ShowModal()
243 except:
244 print msg
245
246 def OnCloseWindow(self, event):
247 self.Destroy()
248
249 class TestApp(wxApp):
250 def OnInit(self):
251 frame = TestLayoutf(NULL)
252 frame.Show(1)
253 self.SetTopWindow(frame)
254 return 1
255
256 app = TestApp(0)
257 app.MainLoop()
258
259
260
261
262