]> git.saurik.com Git - wxWidgets.git/blob - wxPython/misc/widgetLayoutTest.py
22706ac42fa1cc1468bb02598ec27d3f5cc4ed33
[wxWidgets.git] / wxPython / misc / widgetLayoutTest.py
1 """
2 This test app is meant to help check if a widget has a good
3 DoGetBestSize method (in C++) by allowing the user to dynamically
4 create any non-toplevel widget which will be placed in a Sizer
5 designed to show how the widget will be sized naturally.
6 """
7
8 import wx
9 import sys
10 import os
11
12
13 class LayoutTestFrame(wx.Frame):
14 def __init__(self):
15 wx.Frame.__init__(self, None, -1, "Widget Layout Tester")
16
17 p = wx.Panel(self)
18
19 # Create control widgets
20 self.testHistory = wx.ListBox(p, -1, size=(150, 300))
21 self.moduleName = wx.TextCtrl(p, -1, "wx")
22 self.className = wx.TextCtrl(p, -1, "")
23 self.parameters = wx.TextCtrl(p, -1, "")
24 self.postCreate = wx.TextCtrl(p, -1, "", size=(1,75),
25 style=wx.TE_MULTILINE|wx.TE_DONTWRAP)
26 self.expression = wx.TextCtrl(p, -1, "", style=wx.TE_READONLY)
27 self.docstring = wx.TextCtrl(p, -1, "", size=(1,75),
28 style=wx.TE_READONLY|wx.TE_MULTILINE|wx.TE_DONTWRAP)
29
30 self.expression.SetBackgroundColour(
31 wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK))
32 self.docstring.SetBackgroundColour(
33 wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK))
34
35
36 addBtn = wx.Button(p, -1, "Add")
37 remBtn = wx.Button(p, -1, "Remove")
38 repBtn = wx.Button(p, -1, "Replace")
39 createBtn = wx.Button(p, -1, " Create Widget ")
40 createBtn.SetDefault()
41 destroyBtn = wx.Button(p, -1, "Destroy Widget")
42 clearBtn = wx.Button(p, -1, "Clear")
43
44 self.createBtn = createBtn
45 self.destroyBtn = destroyBtn
46
47 bottomPanel = wx.Panel(p, style=wx.SUNKEN_BORDER, name="bottomPanel")
48 bottomPanel.SetSizeHints((640,240))
49 bottomPanel.SetDefaultBackgroundColour("light blue")
50
51 self.testPanel = wx.Panel(bottomPanel, name="testPanel")
52 self.testPanel.SetDefaultBackgroundColour((205, 183, 181)) # mistyrose3
53 self.testWidget = None
54
55 self.infoPane = InfoPane(p)
56
57 # setup event bindings
58 self.Bind(wx.EVT_TEXT, self.OnUpdate, self.moduleName)
59 self.Bind(wx.EVT_TEXT, self.OnUpdate, self.className)
60 self.Bind(wx.EVT_TEXT, self.OnUpdate, self.parameters)
61 self.Bind(wx.EVT_UPDATE_UI, self.OnEnableCreate, createBtn)
62 self.Bind(wx.EVT_UPDATE_UI, self.OnEnableDestroy, destroyBtn)
63 self.Bind(wx.EVT_BUTTON, self.OnCreateWidget, createBtn)
64 self.Bind(wx.EVT_BUTTON, self.OnDestroyWidget, destroyBtn)
65 self.Bind(wx.EVT_BUTTON, self.OnClear, clearBtn)
66
67 self.Bind(wx.EVT_CLOSE, self.OnSaveHistory)
68
69 self.Bind(wx.EVT_BUTTON, self.OnAddHistory, addBtn)
70 self.Bind(wx.EVT_BUTTON, self.OnRemoveHistory, remBtn)
71 self.Bind(wx.EVT_BUTTON, self.OnReplaceHistory, repBtn)
72 self.Bind(wx.EVT_LISTBOX, self.OnHistorySelect, self.testHistory)
73 self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnHistoryActivate, self.testHistory)
74
75
76 # setup the layout
77 mainSizer = wx.BoxSizer(wx.VERTICAL)
78 topSizer = wx.BoxSizer(wx.HORIZONTAL)
79 ctlsSizer = wx.FlexGridSizer(2, 2, 5, 5)
80 ctlsSizer.AddGrowableCol(1)
81 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
82
83 topSizer.Add(self.testHistory, 0, wx.RIGHT, 30)
84
85 ctlsSizer.Add(wx.StaticText(p, -1, "Module name:"),
86 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
87 mcSizer = wx.BoxSizer(wx.HORIZONTAL)
88 mcSizer.Add(self.moduleName, 0, 0)
89 mcSizer.Add(wx.StaticText(p, -1, "Class name:"),
90 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL |wx.LEFT, 10)
91 mcSizer.Add(self.className, 1, 0)
92 ctlsSizer.Add(mcSizer, 0, wx.EXPAND)
93
94 ctlsSizer.Add(wx.StaticText(p, -1, "Parameters:"),
95 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
96 ctlsSizer.Add(self.parameters, 0, wx.EXPAND)
97 ctlsSizer.Add(wx.StaticText(p, -1, "Create Expr:"),
98 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
99 ctlsSizer.Add(self.expression, 0, wx.EXPAND)
100 ctlsSizer.Add(wx.StaticText(p, -1, "Post create:"), 0, wx.ALIGN_RIGHT)
101 ctlsSizer.Add(self.postCreate, 0, wx.EXPAND)
102 ctlsSizer.Add(wx.StaticText(p, -1, "DocString:"), 0, wx.ALIGN_RIGHT)
103 ctlsSizer.Add(self.docstring, 0, wx.EXPAND)
104 ctlsSizer.AddGrowableRow(4)
105 topSizer.Add(ctlsSizer, 1, wx.EXPAND)
106
107 btnSizer.Add((5,5))
108 btnSizer.Add(addBtn, 0, wx.RIGHT, 5)
109 btnSizer.Add(remBtn, 0, wx.RIGHT, 5)
110 btnSizer.Add(repBtn, 0, wx.RIGHT, 5)
111 btnSizer.Add((0,0), 1)
112 btnSizer.Add(createBtn, 0, wx.RIGHT, 5)
113 btnSizer.Add(destroyBtn, 0, wx.RIGHT, 5)
114 btnSizer.Add(clearBtn, 0, wx.RIGHT, 5)
115 btnSizer.Add((0,0), 1)
116
117 mainSizer.Add(topSizer, 0, wx.EXPAND|wx.ALL, 10)
118 mainSizer.Add(btnSizer, 0, wx.EXPAND)
119 mainSizer.Add((10,10))
120 ##mainSizer.Add(wx.StaticLine(p, -1), 0, wx.EXPAND)
121 mainSizer.Add(bottomPanel, 1, wx.EXPAND)
122
123 mainSizer.Add(self.infoPane, 0, wx.EXPAND)
124
125 self.bottomSizer = sz = wx.BoxSizer(wx.VERTICAL)
126 sz.Add((0,0), 1)
127 sz.Add(self.testPanel, 0, wx.ALIGN_CENTER)
128 sz.Add((0,0), 1)
129 bottomPanel.SetSizer(sz)
130
131 p.SetSizerAndFit(mainSizer)
132 self.Fit()
133
134 self.PopulateHistory()
135
136
137
138
139 def PopulateHistory(self):
140 """
141 Load and eval a list of lists from a file, load the contents
142 into self.testHistory
143 """
144 fname = os.path.join(os.path.dirname(sys.argv[0]),
145 'widgetLayoutTest.cfg')
146 try:
147 self.history = eval(open(fname).read())
148 except:
149 self.history = []
150
151 self.testHistory.Clear()
152
153 for idx in range(len(self.history)):
154 item = self.history[idx]
155 # check if it is too short
156 while len(item) < 4:
157 item.append('')
158
159 # add it to the listbox
160 self.testHistory.Append(item[0] + '.' + item[1])
161
162 self.needSaved = False
163
164
165 def OnSaveHistory(self, evt):
166 if self.needSaved:
167 fname = os.path.join(os.path.dirname(sys.argv[0]),
168 'widgetLayoutTest.cfg')
169 f = open(fname, 'wb')
170 f.write('[\n')
171 for item in self.history:
172 f.write(str(item) + ',\n')
173 f.write(']\n')
174 f.close()
175 evt.Skip()
176
177
178 def OnAddHistory(self, evt):
179 moduleName = self.moduleName.GetValue()
180 className = self.className.GetValue()
181 parameters = self.parameters.GetValue()
182 postCreate = self.postCreate.GetValue()
183
184 item = [str(moduleName), str(className), str(parameters), str(postCreate)]
185 self.history.append(item)
186 self.testHistory.Append(item[0] + '.' + item[1])
187
188 self.testHistory.SetSelection(len(self.history)-1)
189 self.needSaved = True
190
191
192 def OnRemoveHistory(self, evt):
193 idx = self.testHistory.GetSelection()
194 if idx != wx.NOT_FOUND:
195 del self.history[idx]
196 self.testHistory.Delete(idx)
197 self.needSaved = True
198 self.OnClear(None)
199
200
201 def OnReplaceHistory(self, evt):
202 idx = self.testHistory.GetSelection()
203 if idx != wx.NOT_FOUND:
204 moduleName = self.moduleName.GetValue()
205 className = self.className.GetValue()
206 parameters = self.parameters.GetValue()
207 postCreate = self.postCreate.GetValue()
208
209 item = [str(moduleName), str(className), str(parameters), str(postCreate)]
210 self.history[idx] = item
211 self.testHistory.SetString(idx, item[0] + '.' + item[1])
212 self.needSaved = True
213
214
215 def OnHistorySelect(self, evt):
216 idx = self.testHistory.GetSelection()
217 if idx != wx.NOT_FOUND:
218 item = self.history[idx]
219 self.moduleName.SetValue(item[0])
220 self.className.SetValue(item[1])
221 self.parameters.SetValue(item[2])
222 self.postCreate.SetValue(item[3])
223
224
225 def OnHistoryActivate(self, evt):
226 btn = self.testHistory.GetParent().GetDefaultItem()
227 if btn is not None:
228 e = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, btn.GetId())
229 btn.Command(e)
230
231
232
233 def OnUpdate(self, evt):
234 # get the details from the form
235 moduleName = self.moduleName.GetValue()
236 className = self.className.GetValue()
237 parameters = self.parameters.GetValue()
238
239 expr = "w = %s.%s( testPanel, %s )" % (moduleName, className, parameters)
240 self.expression.SetValue(expr)
241
242 docstring = ""
243 try:
244 docstring = eval("%s.%s.__init__.__doc__" % (moduleName, className))
245 except:
246 pass
247 self.docstring.SetValue(docstring)
248
249
250 def OnEnableDestroy(self, evt):
251 evt.Enable(self.testWidget is not None)
252
253 def OnEnableCreate(self, evt):
254 evt.Enable(self.testWidget is None)
255
256
257 def OnCreateWidget(self, evt):
258 if self.testWidget is not None:
259 return
260
261 testPanel = self.testPanel
262
263 # get the details from the form
264 moduleName = self.moduleName.GetValue()
265 className = self.className.GetValue()
266 parameters = self.parameters.GetValue()
267 expr = self.expression.GetValue()[4:]
268 postCreate = self.postCreate.GetValue()
269
270 # make sure the module is imported already
271 if not sys.modules.has_key(moduleName):
272 try:
273 m = __import__(moduleName)
274 except importError:
275 wx.MessageBox("Unable to import module!", "Error")
276 return
277
278 # create the widget
279 try:
280 w = eval(expr)
281 except Exception, e:
282 wx.MessageBox("Got a '%s' Exception!" % e.__class__.__name__, "Error")
283 import traceback
284 traceback.print_exc()
285 return
286
287 # Is there postCreate code?
288 if postCreate:
289 ns = {}
290 ns.update(globals())
291 ns.update(locals())
292 try:
293 exec postCreate in ns
294 except Exception, e:
295 wx.MessageBox("Got a '%s' Exception!" % e.__class__.__name__, "Error")
296 import traceback
297 traceback.print_exc()
298 w.Destroy()
299 return
300
301 # Put the widget in a sizer and the sizer in the testPanel
302 sizer = wx.BoxSizer(wx.VERTICAL)
303 sizer.Add(w, 0, wx.ALL, 5)
304 self.testPanel.SetSizer(sizer)
305 self.testWidget = w
306 self.bottomSizer.Layout()
307
308 # make the destroy button be default now
309 self.destroyBtn.SetDefault()
310
311 self.infoPane.Update(w, testPanel)
312
313 if False:
314 print 'w size', w.GetSize()
315 print 'w minsize', w.GetMinSize()
316 print 'w bestsize', w.GetBestSize()
317 print 'w abstsize', w.GetAdjustedBestSize()
318
319 tp = self.testPanel
320 #print tp.GetSizer()
321 print 'tp size', tp.GetSize()
322 print 'tp minsize', tp.GetMinSize()
323 print 'tp bestsize', tp.GetBestSize()
324 print 'tp abstsize', tp.GetAdjustedBestSize()
325
326
327
328 def OnDestroyWidget(self, evt):
329 self.testWidget.Destroy()
330 self.testWidget = None
331 self.testPanel.SetSizer(None, True)
332 self.testPanel.Refresh()
333
334 # ensure the panel shrinks again
335 self.testPanel.SetSizeHints((20,20))
336 self.bottomSizer.Layout()
337 self.testPanel.SetSizeHints(wx.DefaultSize)
338
339 # make the create button be default now
340 self.createBtn.SetDefault()
341
342 self.infoPane.Clear()
343
344
345
346 def OnClear(self, evt):
347 self.moduleName.SetValue("")
348 self.className.SetValue("")
349 self.parameters.SetValue("")
350 self.expression.SetValue("")
351 self.docstring.SetValue("")
352 self.postCreate.SetValue("")
353
354
355
356
357
358
359 class InfoPane(wx.Panel):
360 """
361 This class is used to display details of various properties of the
362 widget and the testPanel to aid with debugging.
363 """
364 def __init__(self, parent):
365 wx.Panel.__init__(self, parent)
366
367 # create subwidgets
368 self.wPane = SizeInfoPane(self, "Widget")
369 self.tpPane= SizeInfoPane(self, "testPanel")
370 self.cPane = ColourInfoPanel(self, "Widget colours")
371
372 # Setup the layout
373 sizer = wx.BoxSizer(wx.HORIZONTAL)
374 sizer.Add(self.wPane, 0, wx.EXPAND|wx.ALL, 5)
375 sizer.Add(self.tpPane, 0, wx.EXPAND|wx.ALL, 5)
376 sizer.Add(self.cPane, 0, wx.EXPAND|wx.ALL, 5)
377
378 self.SetSizer(sizer)
379
380
381 def Update(self, w, tp):
382 self.wPane.Update(w)
383 self.tpPane.Update(tp)
384 self.cPane.Update(w)
385
386 def Clear(self):
387 self.wPane.Clear()
388 self.tpPane.Clear()
389 self.cPane.Clear()
390
391
392
393 class SizeInfoPane(wx.Panel):
394 """
395 A component of the InfoPane that shows vaious window size attributes.
396 """
397 def __init__(self, parent, label):
398 wx.Panel.__init__(self, parent)
399
400 # create subwidgets
401 sb = wx.StaticBox(self, -1, label)
402 self._size = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
403 self._minsize = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
404 self._bestsize = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
405 self._adjbstsize = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
406
407 # setup the layout
408 fgs = wx.FlexGridSizer(2, 2, 5, 5)
409 fgs.AddGrowableCol(1)
410
411 fgs.Add(wx.StaticText(self, -1, "Size:"),
412 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
413 fgs.Add(self._size, 0, wx.EXPAND)
414
415 fgs.Add(wx.StaticText(self, -1, "MinSize:"),
416 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
417 fgs.Add(self._minsize, 0, wx.EXPAND)
418
419 fgs.Add(wx.StaticText(self, -1, "BestSize:"),
420 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
421 fgs.Add(self._bestsize, 0, wx.EXPAND)
422
423 fgs.Add(wx.StaticText(self, -1, "AdjustedBestSize:"),
424 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
425 fgs.Add(self._adjbstsize, 0, wx.EXPAND)
426
427 sbs = wx.StaticBoxSizer(sb, wx.VERTICAL)
428 sbs.Add(fgs, 0, wx.EXPAND|wx.ALL, 4)
429
430 self.SetSizer(sbs)
431
432
433 def Update(self, win):
434 self._size.SetValue( str(win.GetSize()) )
435 self._minsize.SetValue( str(win.GetMinSize()) )
436 self._bestsize.SetValue( str(win.GetBestSize()) )
437 self._adjbstsize.SetValue( str(win.GetAdjustedBestSize()) )
438
439
440 def Clear(self):
441 self._size.SetValue("")
442 self._minsize.SetValue("")
443 self._bestsize.SetValue("")
444 self._adjbstsize.SetValue("")
445
446
447
448 class ColourInfoPanel(wx.Panel):
449 """
450 A component of the InfoPane that shows fg and bg colour attributes.
451 """
452 def __init__(self, parent, label):
453 wx.Panel.__init__(self, parent)
454
455 # create subwidgets
456 sb = wx.StaticBox(self, -1, label)
457 self._fgtxt = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
458 self._fgclr = wx.Panel(self, style=wx.SIMPLE_BORDER)
459 self._fgclr.SetSizeHints((20,20))
460 self._bgtxt = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
461 self._bgclr = wx.Panel(self, style=wx.SIMPLE_BORDER)
462 self._bgclr.SetSizeHints((20,20))
463
464 # setup the layout
465 fgs = wx.FlexGridSizer(2, 3, 5, 5)
466 fgs.AddGrowableCol(1)
467
468 fgs.Add(wx.StaticText(self, -1, "FG colour:"),
469 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
470 fgs.Add(self._fgtxt, 0, wx.EXPAND)
471 fgs.Add(self._fgclr)
472
473 fgs.Add(wx.StaticText(self, -1, "BG colour:"),
474 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
475 fgs.Add(self._bgtxt, 0, wx.EXPAND)
476 fgs.Add(self._bgclr)
477
478 sbs = wx.StaticBoxSizer(sb, wx.VERTICAL)
479 sbs.Add(fgs, 0, wx.EXPAND|wx.ALL, 4)
480
481 self.SetSizer(sbs)
482
483
484 def Update(self, win):
485 def clr2hex(c, cp):
486 cp.SetBackgroundColour(c)
487 cp.Refresh()
488 return "#%02X%02X%02X" % c.Get()
489
490 self._fgtxt.SetValue( clr2hex(win.GetForegroundColour(), self._fgclr) )
491 self._bgtxt.SetValue( clr2hex(win.GetBackgroundColour(), self._bgclr) )
492
493
494 def Clear(self):
495 self._fgtxt.SetValue("")
496 self._bgtxt.SetValue("")
497 self._fgclr.SetBackgroundColour(self.GetBackgroundColour())
498 self._bgclr.SetBackgroundColour(self.GetBackgroundColour())
499 self._fgclr.Refresh()
500 self._bgclr.Refresh()
501
502
503
504
505 app = wx.PySimpleApp(redirect=True)
506 frame = LayoutTestFrame()
507 app.SetTopWindow(frame)
508 frame.Show()
509 app.MainLoop()
510