]> git.saurik.com Git - wxWidgets.git/blame - wxPython/tests/test_widgetLayout.py
use CPPUNIT_ASSERT_EQUAL instead of CPPUNIT_ASSERT as this gives more detailed inform...
[wxWidgets.git] / wxPython / tests / test_widgetLayout.py
CommitLineData
a8d55739
RD
1"""
2This test app is meant to help check if a widget has a good
3DoGetBestSize method (in C++) by allowing the user to dynamically
4create any non-toplevel widget which will be placed in a Sizer
5designed to show how the widget will be sized naturally.
6"""
7
8import wx
9import sys
10import os
11
6dc779e8
RD
12# stuff for debugging
13print "wx.VERSION_STRING = ", wx.VERSION_STRING
14print "pid:", os.getpid()
9e70f342 15##raw_input("Press Enter...")
a8d55739 16
0b0849b5
RD
17testImage = os.path.join(os.path.dirname(sys.argv[0]), 'image.png')
18
19
a8d55739
RD
20class 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
a24dc1a8 27 self.testHistory = wx.ListBox(p, -1, size=(150, 300))
a8d55739
RD
28 self.moduleName = wx.TextCtrl(p, -1, "wx")
29 self.className = wx.TextCtrl(p, -1, "")
30 self.parameters = wx.TextCtrl(p, -1, "")
a24dc1a8
RD
31 self.postCreate = wx.TextCtrl(p, -1, "", size=(1,75),
32 style=wx.TE_MULTILINE|wx.TE_DONTWRAP)
a8d55739 33 self.expression = wx.TextCtrl(p, -1, "", style=wx.TE_READONLY)
a24dc1a8 34 self.docstring = wx.TextCtrl(p, -1, "", size=(1,75),
a8d55739 35 style=wx.TE_READONLY|wx.TE_MULTILINE|wx.TE_DONTWRAP)
a24dc1a8
RD
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))
49bffb14 41
a8d55739
RD
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")
7d9f33e2 55 bottomPanel.SetMinSize((640,240))
a39c03f9 56 bottomPanel.SetOwnBackgroundColour("light blue")
a8d55739
RD
57
58 self.testPanel = wx.Panel(bottomPanel, name="testPanel")
a39c03f9 59 self.testPanel.SetOwnBackgroundColour((205, 183, 181)) # mistyrose3
a8d55739
RD
60 self.testWidget = None
61
49bffb14 62 self.infoPane = InfoPane(p)
a8d55739
RD
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)
49bffb14 81
0bdcd2f5
RD
82 if 'wxMac' in wx.PlatformInfo or 'wxGTK' in wx.PlatformInfo:
83 self.testHistory.Bind(wx.EVT_KEY_DOWN, self.OnHistoryKey)
84
a8d55739
RD
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)
a8d55739 92
49bffb14 93 topSizer.Add(self.testHistory, 0, wx.RIGHT, 30)
a24dc1a8 94
a8d55739
RD
95 ctlsSizer.Add(wx.StaticText(p, -1, "Module name:"),
96 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
a24dc1a8
RD
97 mcSizer = wx.BoxSizer(wx.HORIZONTAL)
98 mcSizer.Add(self.moduleName, 0, 0)
99 mcSizer.Add(wx.StaticText(p, -1, "Class name:"),
0bdcd2f5 100 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL |wx.LEFT|wx.RIGHT, 10)
a24dc1a8
RD
101 mcSizer.Add(self.className, 1, 0)
102 ctlsSizer.Add(mcSizer, 0, wx.EXPAND)
103
a8d55739
RD
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)
a24dc1a8 107 ctlsSizer.Add(wx.StaticText(p, -1, "Create Expr:"),
a8d55739
RD
108 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
109 ctlsSizer.Add(self.expression, 0, wx.EXPAND)
a24dc1a8
RD
110 ctlsSizer.Add(wx.StaticText(p, -1, "Post create:"), 0, wx.ALIGN_RIGHT)
111 ctlsSizer.Add(self.postCreate, 0, wx.EXPAND)
a8d55739
RD
112 ctlsSizer.Add(wx.StaticText(p, -1, "DocString:"), 0, wx.ALIGN_RIGHT)
113 ctlsSizer.Add(self.docstring, 0, wx.EXPAND)
49bffb14 114 ctlsSizer.AddGrowableRow(4)
a24dc1a8 115 topSizer.Add(ctlsSizer, 1, wx.EXPAND)
49bffb14 116
a8d55739
RD
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
49bffb14
RD
133 mainSizer.Add(self.infoPane, 0, wx.EXPAND)
134
a8d55739
RD
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)
49bffb14 140
a8d55739
RD
141 p.SetSizerAndFit(mainSizer)
142 self.Fit()
143
144 self.PopulateHistory()
145
146
49bffb14 147
a8d55739
RD
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 """
0b0849b5 154 fname = os.path.join(os.path.dirname(sys.argv[0]), 'widgets.cfg')
a8d55739
RD
155 try:
156 self.history = eval(open(fname).read())
157 except:
158 self.history = []
159
160 self.testHistory.Clear()
49bffb14 161
a8d55739
RD
162 for idx in range(len(self.history)):
163 item = self.history[idx]
164 # check if it is too short
a24dc1a8 165 while len(item) < 4:
a8d55739
RD
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:
0b0849b5 176 fname = os.path.join(os.path.dirname(sys.argv[0]), 'widgets.cfg')
a8d55739
RD
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()
a24dc1a8 190 postCreate = self.postCreate.GetValue()
a8d55739 191
a24dc1a8 192 item = [str(moduleName), str(className), str(parameters), str(postCreate)]
a8d55739
RD
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
a24dc1a8 206 self.OnClear(None)
49bffb14 207
a8d55739
RD
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()
a24dc1a8 215 postCreate = self.postCreate.GetValue()
a8d55739 216
a24dc1a8 217 item = [str(moduleName), str(className), str(parameters), str(postCreate)]
a8d55739
RD
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):
0bdcd2f5
RD
224 #idx = self.testHistory.GetSelection()
225 idx = evt.GetInt()
a8d55739
RD
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])
a24dc1a8 231 self.postCreate.SetValue(item[3])
0bdcd2f5
RD
232 if 'wxMac' in wx.PlatformInfo:
233 self.OnUpdate(None)
a8d55739
RD
234
235
236 def OnHistoryActivate(self, evt):
0b0849b5 237 btn = self.testHistory.GetTopLevelParent().GetDefaultItem()
a8d55739
RD
238 if btn is not None:
239 e = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, btn.GetId())
240 btn.Command(e)
49bffb14 241
a8d55739 242
0bdcd2f5
RD
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
a8d55739
RD
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()
49bffb14 256
a24dc1a8 257 expr = "w = %s.%s( testPanel, %s )" % (moduleName, className, parameters)
a8d55739
RD
258 self.expression.SetValue(expr)
259
2f1189cf 260 docstring = None
a8d55739
RD
261 try:
262 docstring = eval("%s.%s.__init__.__doc__" % (moduleName, className))
263 except:
264 pass
2f1189cf
RD
265 if docstring is not None:
266 self.docstring.SetValue(docstring)
267 else:
268 self.docstring.SetValue("")
a8d55739
RD
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
a24dc1a8
RD
280
281 testPanel = self.testPanel
49bffb14 282
a8d55739
RD
283 # get the details from the form
284 moduleName = self.moduleName.GetValue()
285 className = self.className.GetValue()
286 parameters = self.parameters.GetValue()
a24dc1a8
RD
287 expr = self.expression.GetValue()[4:]
288 postCreate = self.postCreate.GetValue()
0bdcd2f5
RD
289 if 'wxMac' in wx.PlatformInfo:
290 postCreate = postCreate.replace('\r', '\n')
a8d55739
RD
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
3bcdbe52 308
a24dc1a8
RD
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()
98c09285 320 w.Destroy()
a24dc1a8 321 return
49bffb14 322
a8d55739
RD
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
49bffb14
RD
333 self.infoPane.Update(w, testPanel)
334
a8d55739
RD
335
336 def OnDestroyWidget(self, evt):
337 self.testWidget.Destroy()
338 self.testWidget = None
339 self.testPanel.SetSizer(None, True)
d1bb3e12 340 self.testPanel.Refresh()
49bffb14 341
7d9f33e2
RD
342 # ensure the panel shrinks again now that it has no sizer
343 self.testPanel.SetMinSize((20,20))
3bcdbe52 344 self.bottomSizer.Layout()
7d9f33e2 345 self.testPanel.SetMinSize(wx.DefaultSize)
49bffb14 346
a8d55739
RD
347 # make the create button be default now
348 self.createBtn.SetDefault()
349
49bffb14
RD
350 self.infoPane.Clear()
351
352
a8d55739
RD
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("")
a24dc1a8 359 self.postCreate.SetValue("")
49bffb14
RD
360
361
362
363
364
365
366class 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
400class 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)
0b0849b5 412 self._effmin = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
49bffb14
RD
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
0b0849b5 430 fgs.Add(wx.StaticText(self, -1, "EffectiveMinSize:"),
7d9f33e2 431 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
0b0849b5 432 fgs.Add(self._effmin, 0, wx.EXPAND)
7d9f33e2 433
49bffb14
RD
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()) )
0b0849b5 444 self._effmin.SetValue( str(win.GetEffectiveMinSize()) )
49bffb14
RD
445
446 def Clear(self):
447 self._size.SetValue("")
448 self._minsize.SetValue("")
449 self._bestsize.SetValue("")
0b0849b5 450 self._effmin.SetValue("")
49bffb14
RD
451
452
453
454class 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)
32070021 465 self._fgclr.SetMinSize((20,20))
49bffb14
RD
466 self._bgtxt = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
467 self._bgclr = wx.Panel(self, style=wx.SIMPLE_BORDER)
32070021 468 self._bgclr.SetMinSize((20,20))
49bffb14
RD
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()
a8d55739 495
49bffb14
RD
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()
a8d55739
RD
507
508
49bffb14
RD
509
510
0bdcd2f5 511app = wx.PySimpleApp(redirect=False)
a8d55739
RD
512frame = LayoutTestFrame()
513app.SetTopWindow(frame)
514frame.Show()
515app.MainLoop()
516