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