]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/layoutf.py
Updated layout test
[wxWidgets.git] / wxPython / wx / lib / layoutf.py
CommitLineData
b881fc78
RD
1# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
2#
3# o Updated for wx namespace
4#
33785d9f
RD
5# 12/18/2003 - Jeff Grimmett (grimmtooth@softhome.net)
6#
7# o wxScrolledMessageDialog -> ScrolledMessageDialog
8#
d14a1e28 9
b881fc78
RD
10import re
11import wx
12
13class Layoutf(wx.LayoutConstraints):
d14a1e28
RD
14 """
15The class Layoutf(wxLayoutConstraints) presents a simplification
16of the wxLayoutConstraints syntax. The name Layoutf is choosen
17because of the similarity with C's printf function.
18
19Quick Example:
20
21 lc = Layoutf('t=t#1;l=r10#2;r!100;h%h50#1', (self, self.panel))
22
23is 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
31Usage:
32
33 You can give a constraint string to the Layoutf constructor,
34or 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
38and
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
44constraints, but prints traditional wxLayoutConstraint calls to
45stdout.
46
47 The calls to the Layoutf constructor and pack methods have
48the following argument list:
49
50 (constraint_string, objects_tuple)
51
52Constraint String syntax:
53
54 Constraint directives are separated by semi-colons. You
55generally (always?) need four directives to completely describe a
56subwindow'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>
75type. The following take type 1 (no object to compare with):
76
77 '!': 'Absolute', '?': 'Unconstrained', '*': 'AsIs'
78
79These take type 2 (need to be compared with another object)
80
81 '<': 'LeftOf', '>': 'RightOf', '^': 'Above', '_': 'Below'
82
83These take type 3 (need to be compared to another object
84attribute)
85
86 '=': 'SameAs', '%': 'PercentOf'
87
88For 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
94If the operation takes an (optional) numerical argument, place it
95in [numerical argument]. For type 3 directives, the <compare
96attribute> 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
102Note that these are the same letters as used for <own attribute>,
103so you'll only need to remember one set. Finally, the object
104whose attribute is refered to, is specified by #<compare object
105nr>, where <compare object nr> is the 1-based (stupid, I know,
106but I've gotten used to it) index of the object in the
107objects_tuple argument.
108
109Bugs:
110
111Not entirely happy about the logic in the order of arguments
112after the <compare operation> character.
113
114Not all wxLayoutConstraint methods are included in the
115syntax. However, the type 3 directives are generally the most
116used. Further excuse: wxWindows layout constraints are at the
117time 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' }
b881fc78
RD
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' }
d14a1e28
RD
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):
b881fc78 135 wx.LayoutConstraints.__init__(self)
d14a1e28
RD
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
203if __name__=='__main__':
d14a1e28 204
b881fc78 205 class TestLayoutf(wx.Frame):
d14a1e28 206 def __init__(self, parent):
b881fc78
RD
207 wx.Frame.__init__(self, parent, -1, 'Test Layout Constraints',
208 wx.DefaultPosition, (500, 300))
209 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
d14a1e28
RD
210
211 self.SetAutoLayout(True)
d14a1e28 212
b881fc78
RD
213 self.panelA = wx.Window(self, -1, style=wx.SIMPLE_BORDER)
214 self.panelA.SetBackgroundColour(wx.BLUE)
d14a1e28
RD
215 self.panelA.SetConstraints(Layoutf('t=t10#1;l=l10#1;b=b10#1;r%r50#1',(self,)))
216
b881fc78
RD
217 self.panelB = wx.Window(self, -1, style=wx.SIMPLE_BORDER)
218 self.panelB.SetBackgroundColour(wx.RED)
d14a1e28
RD
219 self.panelB.SetConstraints(Layoutf('t=t10#1;r=r10#1;b%b30#1;l>10#2', (self,self.panelA)))
220
b881fc78
RD
221 self.panelC = wx.Window(self, -1, style=wx.SIMPLE_BORDER)
222 self.panelC.SetBackgroundColour(wx.WHITE)
d14a1e28
RD
223 self.panelC.SetConstraints(Layoutf('t_10#3;r=r10#1;b=b10#1;l>10#2', (self,self.panelA,self.panelB)))
224
b881fc78 225 b = wx.Button(self.panelA, -1, ' About: ')
d14a1e28 226 b.SetConstraints(Layoutf('X=X#1;Y=Y#1;h*;w%w50#1', (self.panelA,)))
b881fc78 227 self.Bind(wx.EVT_BUTTON, self.OnAbout, b)
d14a1e28 228
b881fc78 229 b = wx.Button(self.panelB, 100, ' Panel B ')
d14a1e28
RD
230 b.SetConstraints(Layoutf('t=t2#1;r=r4#1;h*;w*', (self.panelB,)))
231
b881fc78
RD
232 self.panelD = wx.Window(self.panelC, -1, style=wx.SIMPLE_BORDER)
233 self.panelD.SetBackgroundColour(wx.GREEN)
d14a1e28
RD
234 self.panelD.SetConstraints(Layoutf('b%h50#1;r%w50#1;h=h#2;w=w#2', (self.panelC, b)))
235
b881fc78 236 b = wx.Button(self.panelC, -1, ' Panel C ')
d14a1e28 237 b.SetConstraints(Layoutf('t_#1;l>#1;h*;w*', (self.panelD,)))
b881fc78 238 self.Bind(wx.EVT_BUTTON, self.OnButton, b)
d14a1e28 239
b881fc78 240 wx.StaticText(self.panelD, -1, "Panel D", (4, 4)).SetBackgroundColour(wx.GREEN)
d14a1e28
RD
241
242 def OnButton(self, event):
243 self.Close(True)
244
245 def OnAbout(self, event):
b881fc78 246 import wx.lib.dialogs
33785d9f 247 msg = wx.lib.dialogs.ScrolledMessageDialog(self, Layoutf.__doc__, "about")
b881fc78
RD
248 msg.ShowModal()
249 msg.Destroy()
d14a1e28
RD
250
251 def OnCloseWindow(self, event):
252 self.Destroy()
253
b881fc78 254 class TestApp(wx.App):
d14a1e28 255 def OnInit(self):
b881fc78 256 frame = TestLayoutf(None)
d14a1e28
RD
257 frame.Show(1)
258 self.SetTopWindow(frame)
259 return 1
260
261 app = TestApp(0)
262 app.MainLoop()
263
264
265
1fded56b 266
1fded56b 267