]>
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
5 # 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
7 # o wxScrolledMessageDialog -> ScrolledMessageDialog
13 class Layoutf(wx
.LayoutConstraints
):
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.
21 lc = Layoutf('t=t#1;l=r10#2;r!100;h%h50#1', (self, self.panel))
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)
33 You can give a constraint string to the Layoutf constructor,
34 or use the 'pack' method. The following are equivalent:
36 lc = Layoutf('t=t#1;l=r#2;r!100;h%h50#1', (self, self.panel))
41 lc.pack('t=t#1;l=r#2;r!100;h%h50#1', (self, self.panel))
43 Besides 'pack' there's also 'debug_pack' which does not set
44 constraints, but prints traditional wxLayoutConstraint calls to
47 The calls to the Layoutf constructor and pack methods have
48 the following argument list:
50 (constraint_string, objects_tuple)
52 Constraint String syntax:
54 Constraint directives are separated by semi-colons. You
55 generally (always?) need four directives to completely describe a
58 A single directive has either of the following forms:
60 1. <own attribute><compare operation>[numerical argument]
61 for example r!100 -> lc.right.Absolute(100) )
62 and w* -> lc.width.AsIs()
64 2. <own attribute><compare operation>[numerical argument]
66 for example t_10#2 (lc.top.Below(<second obj>, 10)
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>,
74 Which one you need is defined by the <compare operation>
75 type. The following take type 1 (no object to compare with):
77 '!': 'Absolute', '?': 'Unconstrained', '*': 'AsIs'
79 These take type 2 (need to be compared with another object)
81 '<': 'LeftOf', '>': 'RightOf', '^': 'Above', '_': 'Below'
83 These take type 3 (need to be compared to another object
86 '=': 'SameAs', '%': 'PercentOf'
88 For all types, the <own attribute> letter can be any of
90 't': 'top', 'l': 'left', 'b': 'bottom',
91 'r': 'right', 'h': 'height', 'w': 'width',
92 'x': 'centreX', 'y': 'centreY'
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
98 't': 'wxTop', 'l': 'wxLeft', 'b': 'wxBottom'
99 'r': 'wxRight', 'h': 'wxHeight', 'w': 'wxWidth',
100 'x': 'wxCentreX', 'y': 'wxCentreY'
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.
111 Not entirely happy about the logic in the order of arguments
112 after the <compare operation> character.
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.
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' }
131 rexp1
= re
.compile('^\s*([tlrbhwxy])\s*([!\?\*])\s*(\d*)\s*$')
132 rexp2
= re
.compile('^\s*([tlrbhwxy])\s*([=%<>^_])\s*([tlrbhwxy]?)\s*(\d*)\s*#(\d+)\s*$')
134 def __init__(self
,pstr
=None,winlist
=None):
135 wx
.LayoutConstraints
.__init
__(self
)
137 self
.pack(pstr
,winlist
)
139 def pack(self
, pstr
, winlist
):
141 for item
in pstr
.split(';'):
142 m
= self
.rexp1
.match(item
)
145 attr
= getattr(self
, self
.attr_d
[g
[0]])
146 func
= getattr(attr
, self
.op_d
[g
[1]])
152 m
= self
.rexp2
.match(item
)
153 if not m
: raise ValueError
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])
161 if g
[3]: func(winlist
[g
[4]], g
[3])
162 else: func(winlist
[g
[4]])
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)
168 def debug_pack(self
, pstr
, winlist
):
170 for item
in pstr
.split(';'):
171 m
= self
.rexp1
.match(item
)
174 attr
= getattr(self
, self
.attr_d
[g
[0]])
175 func
= getattr(attr
, self
.op_d
[g
[1]])
177 print "%s.%s.%s(%s)" % \
178 ('self',self
.attr_d
[g
[0]],self
.op_d
[g
[1]],g
[2])
180 print "%s.%s.%s()" % \
181 ('self',self
.attr_d
[g
[0]],self
.op_d
[g
[1]])
183 m
= self
.rexp2
.match(item
)
184 if not m
: raise ValueError
186 if g
[3]: g
[3] = int(g
[3])
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]],
193 else: print "%s.%s.%s(%s)" % \
194 ('self',self
.attr_d
[g
[0]],self
.op_d
[g
[1]],winlist
[g
[4]])
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]],
203 if __name__
=='__main__':
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
)
211 self
.SetAutoLayout(True)
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
,)))
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
)))
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
)))
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
)
229 b
= wx
.Button(self
.panelB
, 100, ' Panel B ')
230 b
.SetConstraints(Layoutf('t=t2#1;r=r4#1;h*;w*', (self
.panelB
,)))
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
)))
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
)
240 wx
.StaticText(self
.panelD
, -1, "Panel D", (4, 4)).SetBackgroundColour(wx
.GREEN
)
242 def OnButton(self
, event
):
245 def OnAbout(self
, event
):
246 import wx
.lib
.dialogs
247 msg
= wx
.lib
.dialogs
.ScrolledMessageDialog(self
, Layoutf
.__doc
__, "about")
251 def OnCloseWindow(self
, event
):
254 class TestApp(wx
.App
):
256 frame
= TestLayoutf(None)
258 self
.SetTopWindow(frame
)