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