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