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