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