]> git.saurik.com Git - wxWidgets.git/blame - wxPython/misc/widgetLayoutTest.py
blit implemented using dc.GetAsBitmap with subrect
[wxWidgets.git] / wxPython / misc / widgetLayoutTest.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
RD
16
17class 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
a24dc1a8 24 self.testHistory = wx.ListBox(p, -1, size=(150, 300))
a8d55739
RD
25 self.moduleName = wx.TextCtrl(p, -1, "wx")
26 self.className = wx.TextCtrl(p, -1, "")
27 self.parameters = wx.TextCtrl(p, -1, "")
a24dc1a8
RD
28 self.postCreate = wx.TextCtrl(p, -1, "", size=(1,75),
29 style=wx.TE_MULTILINE|wx.TE_DONTWRAP)
a8d55739 30 self.expression = wx.TextCtrl(p, -1, "", style=wx.TE_READONLY)
a24dc1a8 31 self.docstring = wx.TextCtrl(p, -1, "", size=(1,75),
a8d55739 32 style=wx.TE_READONLY|wx.TE_MULTILINE|wx.TE_DONTWRAP)
a24dc1a8
RD
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))
49bffb14 38
a8d55739
RD
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")
7d9f33e2 52 bottomPanel.SetMinSize((640,240))
a39c03f9 53 bottomPanel.SetOwnBackgroundColour("light blue")
a8d55739
RD
54
55 self.testPanel = wx.Panel(bottomPanel, name="testPanel")
a39c03f9 56 self.testPanel.SetOwnBackgroundColour((205, 183, 181)) # mistyrose3
a8d55739
RD
57 self.testWidget = None
58
49bffb14 59 self.infoPane = InfoPane(p)
a8d55739
RD
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)
49bffb14 78
0bdcd2f5
RD
79 if 'wxMac' in wx.PlatformInfo or 'wxGTK' in wx.PlatformInfo:
80 self.testHistory.Bind(wx.EVT_KEY_DOWN, self.OnHistoryKey)
81
a8d55739
RD
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)
a8d55739 89
49bffb14 90 topSizer.Add(self.testHistory, 0, wx.RIGHT, 30)
a24dc1a8 91
a8d55739
RD
92 ctlsSizer.Add(wx.StaticText(p, -1, "Module name:"),
93 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
a24dc1a8
RD
94 mcSizer = wx.BoxSizer(wx.HORIZONTAL)
95 mcSizer.Add(self.moduleName, 0, 0)
96 mcSizer.Add(wx.StaticText(p, -1, "Class name:"),
0bdcd2f5 97 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL |wx.LEFT|wx.RIGHT, 10)
a24dc1a8
RD
98 mcSizer.Add(self.className, 1, 0)
99 ctlsSizer.Add(mcSizer, 0, wx.EXPAND)
100
a8d55739
RD
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)
a24dc1a8 104 ctlsSizer.Add(wx.StaticText(p, -1, "Create Expr:"),
a8d55739
RD
105 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
106 ctlsSizer.Add(self.expression, 0, wx.EXPAND)
a24dc1a8
RD
107 ctlsSizer.Add(wx.StaticText(p, -1, "Post create:"), 0, wx.ALIGN_RIGHT)
108 ctlsSizer.Add(self.postCreate, 0, wx.EXPAND)
a8d55739
RD
109 ctlsSizer.Add(wx.StaticText(p, -1, "DocString:"), 0, wx.ALIGN_RIGHT)
110 ctlsSizer.Add(self.docstring, 0, wx.EXPAND)
49bffb14 111 ctlsSizer.AddGrowableRow(4)
a24dc1a8 112 topSizer.Add(ctlsSizer, 1, wx.EXPAND)
49bffb14 113
a8d55739
RD
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
49bffb14
RD
130 mainSizer.Add(self.infoPane, 0, wx.EXPAND)
131
a8d55739
RD
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)
49bffb14 137
a8d55739
RD
138 p.SetSizerAndFit(mainSizer)
139 self.Fit()
140
141 self.PopulateHistory()
142
143
49bffb14 144
a8d55739
RD
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()
49bffb14 159
a8d55739
RD
160 for idx in range(len(self.history)):
161 item = self.history[idx]
162 # check if it is too short
a24dc1a8 163 while len(item) < 4:
a8d55739
RD
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()
a24dc1a8 189 postCreate = self.postCreate.GetValue()
a8d55739 190
a24dc1a8 191 item = [str(moduleName), str(className), str(parameters), str(postCreate)]
a8d55739
RD
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
a24dc1a8 205 self.OnClear(None)
49bffb14 206
a8d55739
RD
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()
a24dc1a8 214 postCreate = self.postCreate.GetValue()
a8d55739 215
a24dc1a8 216 item = [str(moduleName), str(className), str(parameters), str(postCreate)]
a8d55739
RD
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):
0bdcd2f5
RD
223 #idx = self.testHistory.GetSelection()
224 idx = evt.GetInt()
a8d55739
RD
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])
a24dc1a8 230 self.postCreate.SetValue(item[3])
0bdcd2f5
RD
231 if 'wxMac' in wx.PlatformInfo:
232 self.OnUpdate(None)
a8d55739
RD
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)
49bffb14 240
a8d55739 241
0bdcd2f5
RD
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
a8d55739
RD
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()
49bffb14 255
a24dc1a8 256 expr = "w = %s.%s( testPanel, %s )" % (moduleName, className, parameters)
a8d55739
RD
257 self.expression.SetValue(expr)
258
2f1189cf 259 docstring = None
a8d55739
RD
260 try:
261 docstring = eval("%s.%s.__init__.__doc__" % (moduleName, className))
262 except:
263 pass
2f1189cf
RD
264 if docstring is not None:
265 self.docstring.SetValue(docstring)
266 else:
267 self.docstring.SetValue("")
a8d55739
RD
268
269 def OnEnableDestroy(self, evt):
270 evt.Enable(self.testWidget is not None)
271
272 def OnEnableCreate(self, evt):
273 evt.Enable(self.testWidget is None)
274
275
276 def OnCreateWidget(self, evt):
277 if self.testWidget is not None:
278 return
a24dc1a8
RD
279
280 testPanel = self.testPanel
49bffb14 281
a8d55739
RD
282 # get the details from the form
283 moduleName = self.moduleName.GetValue()
284 className = self.className.GetValue()
285 parameters = self.parameters.GetValue()
a24dc1a8
RD
286 expr = self.expression.GetValue()[4:]
287 postCreate = self.postCreate.GetValue()
0bdcd2f5
RD
288 if 'wxMac' in wx.PlatformInfo:
289 postCreate = postCreate.replace('\r', '\n')
a8d55739
RD
290
291 # make sure the module is imported already
292 if not sys.modules.has_key(moduleName):
293 try:
294 m = __import__(moduleName)
295 except importError:
296 wx.MessageBox("Unable to import module!", "Error")
297 return
298
299 # create the widget
300 try:
301 w = eval(expr)
302 except Exception, e:
303 wx.MessageBox("Got a '%s' Exception!" % e.__class__.__name__, "Error")
304 import traceback
305 traceback.print_exc()
306 return
3bcdbe52 307
a24dc1a8
RD
308 # Is there postCreate code?
309 if postCreate:
310 ns = {}
311 ns.update(globals())
312 ns.update(locals())
313 try:
314 exec postCreate in ns
315 except Exception, e:
316 wx.MessageBox("Got a '%s' Exception!" % e.__class__.__name__, "Error")
317 import traceback
318 traceback.print_exc()
98c09285 319 w.Destroy()
a24dc1a8 320 return
49bffb14 321
a8d55739
RD
322 # Put the widget in a sizer and the sizer in the testPanel
323 sizer = wx.BoxSizer(wx.VERTICAL)
324 sizer.Add(w, 0, wx.ALL, 5)
325 self.testPanel.SetSizer(sizer)
326 self.testWidget = w
327 self.bottomSizer.Layout()
328
329 # make the destroy button be default now
330 self.destroyBtn.SetDefault()
331
49bffb14
RD
332 self.infoPane.Update(w, testPanel)
333
a8d55739
RD
334
335 def OnDestroyWidget(self, evt):
336 self.testWidget.Destroy()
337 self.testWidget = None
338 self.testPanel.SetSizer(None, True)
d1bb3e12 339 self.testPanel.Refresh()
49bffb14 340
7d9f33e2
RD
341 # ensure the panel shrinks again now that it has no sizer
342 self.testPanel.SetMinSize((20,20))
3bcdbe52 343 self.bottomSizer.Layout()
7d9f33e2 344 self.testPanel.SetMinSize(wx.DefaultSize)
49bffb14 345
a8d55739
RD
346 # make the create button be default now
347 self.createBtn.SetDefault()
348
49bffb14
RD
349 self.infoPane.Clear()
350
351
a8d55739
RD
352 def OnClear(self, evt):
353 self.moduleName.SetValue("")
354 self.className.SetValue("")
355 self.parameters.SetValue("")
356 self.expression.SetValue("")
357 self.docstring.SetValue("")
a24dc1a8 358 self.postCreate.SetValue("")
49bffb14
RD
359
360
361
362
363
364
365class InfoPane(wx.Panel):
366 """
367 This class is used to display details of various properties of the
368 widget and the testPanel to aid with debugging.
369 """
370 def __init__(self, parent):
371 wx.Panel.__init__(self, parent)
372
373 # create subwidgets
374 self.wPane = SizeInfoPane(self, "Widget")
375 self.tpPane= SizeInfoPane(self, "testPanel")
376 self.cPane = ColourInfoPanel(self, "Widget colours")
377
378 # Setup the layout
379 sizer = wx.BoxSizer(wx.HORIZONTAL)
380 sizer.Add(self.wPane, 0, wx.EXPAND|wx.ALL, 5)
381 sizer.Add(self.tpPane, 0, wx.EXPAND|wx.ALL, 5)
382 sizer.Add(self.cPane, 0, wx.EXPAND|wx.ALL, 5)
383
384 self.SetSizer(sizer)
385
386
387 def Update(self, w, tp):
388 self.wPane.Update(w)
389 self.tpPane.Update(tp)
390 self.cPane.Update(w)
391
392 def Clear(self):
393 self.wPane.Clear()
394 self.tpPane.Clear()
395 self.cPane.Clear()
396
397
398
399class SizeInfoPane(wx.Panel):
400 """
401 A component of the InfoPane that shows vaious window size attributes.
402 """
403 def __init__(self, parent, label):
404 wx.Panel.__init__(self, parent)
405
406 # create subwidgets
407 sb = wx.StaticBox(self, -1, label)
408 self._size = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
409 self._minsize = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
410 self._bestsize = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
411 self._adjbstsize = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
7d9f33e2 412 self._bestfit = 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
430 fgs.Add(wx.StaticText(self, -1, "AdjustedBestSize:"),
431 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
432 fgs.Add(self._adjbstsize, 0, wx.EXPAND)
433
7d9f33e2
RD
434 fgs.Add(wx.StaticText(self, -1, "BestFittingSize:"),
435 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
436 fgs.Add(self._bestfit, 0, wx.EXPAND)
437
49bffb14
RD
438 sbs = wx.StaticBoxSizer(sb, wx.VERTICAL)
439 sbs.Add(fgs, 0, wx.EXPAND|wx.ALL, 4)
440
441 self.SetSizer(sbs)
442
443
444 def Update(self, win):
445 self._size.SetValue( str(win.GetSize()) )
446 self._minsize.SetValue( str(win.GetMinSize()) )
447 self._bestsize.SetValue( str(win.GetBestSize()) )
448 self._adjbstsize.SetValue( str(win.GetAdjustedBestSize()) )
7d9f33e2 449 self._bestfit.SetValue( str(win.GetBestFittingSize()) )
49bffb14
RD
450
451 def Clear(self):
452 self._size.SetValue("")
453 self._minsize.SetValue("")
454 self._bestsize.SetValue("")
455 self._adjbstsize.SetValue("")
7d9f33e2 456 self._bestfit.SetValue("")
49bffb14
RD
457
458
459
460class ColourInfoPanel(wx.Panel):
461 """
462 A component of the InfoPane that shows fg and bg colour attributes.
463 """
464 def __init__(self, parent, label):
465 wx.Panel.__init__(self, parent)
466
467 # create subwidgets
468 sb = wx.StaticBox(self, -1, label)
469 self._fgtxt = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
470 self._fgclr = wx.Panel(self, style=wx.SIMPLE_BORDER)
32070021 471 self._fgclr.SetMinSize((20,20))
49bffb14
RD
472 self._bgtxt = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY)
473 self._bgclr = wx.Panel(self, style=wx.SIMPLE_BORDER)
32070021 474 self._bgclr.SetMinSize((20,20))
49bffb14
RD
475
476 # setup the layout
477 fgs = wx.FlexGridSizer(2, 3, 5, 5)
478 fgs.AddGrowableCol(1)
479
480 fgs.Add(wx.StaticText(self, -1, "FG colour:"),
481 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
482 fgs.Add(self._fgtxt, 0, wx.EXPAND)
483 fgs.Add(self._fgclr)
484
485 fgs.Add(wx.StaticText(self, -1, "BG colour:"),
486 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
487 fgs.Add(self._bgtxt, 0, wx.EXPAND)
488 fgs.Add(self._bgclr)
489
490 sbs = wx.StaticBoxSizer(sb, wx.VERTICAL)
491 sbs.Add(fgs, 0, wx.EXPAND|wx.ALL, 4)
492
493 self.SetSizer(sbs)
494
495
496 def Update(self, win):
497 def clr2hex(c, cp):
498 cp.SetBackgroundColour(c)
499 cp.Refresh()
500 return "#%02X%02X%02X" % c.Get()
a8d55739 501
49bffb14
RD
502 self._fgtxt.SetValue( clr2hex(win.GetForegroundColour(), self._fgclr) )
503 self._bgtxt.SetValue( clr2hex(win.GetBackgroundColour(), self._bgclr) )
504
505
506 def Clear(self):
507 self._fgtxt.SetValue("")
508 self._bgtxt.SetValue("")
509 self._fgclr.SetBackgroundColour(self.GetBackgroundColour())
510 self._bgclr.SetBackgroundColour(self.GetBackgroundColour())
511 self._fgclr.Refresh()
512 self._bgclr.Refresh()
a8d55739
RD
513
514
49bffb14
RD
515
516
0bdcd2f5 517app = wx.PySimpleApp(redirect=False)
a8d55739
RD
518frame = LayoutTestFrame()
519app.SetTopWindow(frame)
520frame.Show()
521app.MainLoop()
522