]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/layoutf.py
1 # 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
3 # o Updated for wx namespace
9 class Layoutf(wx
.LayoutConstraints
):
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.
17 lc = Layoutf('t=t#1;l=r10#2;r!100;h%h50#1', (self, self.panel))
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)
29 You can give a constraint string to the Layoutf constructor,
30 or use the 'pack' method. The following are equivalent:
32 lc = Layoutf('t=t#1;l=r#2;r!100;h%h50#1', (self, self.panel))
37 lc.pack('t=t#1;l=r#2;r!100;h%h50#1', (self, self.panel))
39 Besides 'pack' there's also 'debug_pack' which does not set
40 constraints, but prints traditional wxLayoutConstraint calls to
43 The calls to the Layoutf constructor and pack methods have
44 the following argument list:
46 (constraint_string, objects_tuple)
48 Constraint String syntax:
50 Constraint directives are separated by semi-colons. You
51 generally (always?) need four directives to completely describe a
54 A single directive has either of the following forms:
56 1. <own attribute><compare operation>[numerical argument]
57 for example r!100 -> lc.right.Absolute(100) )
58 and w* -> lc.width.AsIs()
60 2. <own attribute><compare operation>[numerical argument]
62 for example t_10#2 (lc.top.Below(<second obj>, 10)
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>,
70 Which one you need is defined by the <compare operation>
71 type. The following take type 1 (no object to compare with):
73 '!': 'Absolute', '?': 'Unconstrained', '*': 'AsIs'
75 These take type 2 (need to be compared with another object)
77 '<': 'LeftOf', '>': 'RightOf', '^': 'Above', '_': 'Below'
79 These take type 3 (need to be compared to another object
82 '=': 'SameAs', '%': 'PercentOf'
84 For all types, the <own attribute> letter can be any of
86 't': 'top', 'l': 'left', 'b': 'bottom',
87 'r': 'right', 'h': 'height', 'w': 'width',
88 'x': 'centreX', 'y': 'centreY'
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
94 't': 'wxTop', 'l': 'wxLeft', 'b': 'wxBottom'
95 'r': 'wxRight', 'h': 'wxHeight', 'w': 'wxWidth',
96 'x': 'wxCentreX', 'y': 'wxCentreY'
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.
107 Not entirely happy about the logic in the order of arguments
108 after the <compare operation> character.
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.
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' }
127 rexp1
= re
.compile('^\s*([tlrbhwxy])\s*([!\?\*])\s*(\d*)\s*$')
128 rexp2
= re
.compile('^\s*([tlrbhwxy])\s*([=%<>^_])\s*([tlrbhwxy]?)\s*(\d*)\s*#(\d+)\s*$')
130 def __init__(self
,pstr
=None,winlist
=None):
131 wx
.LayoutConstraints
.__init
__(self
)
133 self
.pack(pstr
,winlist
)
135 def pack(self
, pstr
, winlist
):
137 for item
in pstr
.split(';'):
138 m
= self
.rexp1
.match(item
)
141 attr
= getattr(self
, self
.attr_d
[g
[0]])
142 func
= getattr(attr
, self
.op_d
[g
[1]])
148 m
= self
.rexp2
.match(item
)
149 if not m
: raise ValueError
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])
157 if g
[3]: func(winlist
[g
[4]], g
[3])
158 else: func(winlist
[g
[4]])
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)
164 def debug_pack(self
, pstr
, winlist
):
166 for item
in pstr
.split(';'):
167 m
= self
.rexp1
.match(item
)
170 attr
= getattr(self
, self
.attr_d
[g
[0]])
171 func
= getattr(attr
, self
.op_d
[g
[1]])
173 print "%s.%s.%s(%s)" % \
174 ('self',self
.attr_d
[g
[0]],self
.op_d
[g
[1]],g
[2])
176 print "%s.%s.%s()" % \
177 ('self',self
.attr_d
[g
[0]],self
.op_d
[g
[1]])
179 m
= self
.rexp2
.match(item
)
180 if not m
: raise ValueError
182 if g
[3]: g
[3] = int(g
[3])
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]],
189 else: print "%s.%s.%s(%s)" % \
190 ('self',self
.attr_d
[g
[0]],self
.op_d
[g
[1]],winlist
[g
[4]])
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]],
199 if __name__
=='__main__':
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
)
207 self
.SetAutoLayout(True)
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
,)))
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
)))
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
)))
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
)
225 b
= wx
.Button(self
.panelB
, 100, ' Panel B ')
226 b
.SetConstraints(Layoutf('t=t2#1;r=r4#1;h*;w*', (self
.panelB
,)))
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
)))
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
)
236 wx
.StaticText(self
.panelD
, -1, "Panel D", (4, 4)).SetBackgroundColour(wx
.GREEN
)
238 def OnButton(self
, event
):
241 def OnAbout(self
, event
):
242 import wx
.lib
.dialogs
243 msg
= wx
.lib
.dialogs
.wxScrolledMessageDialog(self
, Layoutf
.__doc
__, "about")
247 def OnCloseWindow(self
, event
):
250 class TestApp(wx
.App
):
252 frame
= TestLayoutf(None)
254 self
.SetTopWindow(frame
)