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. 
  13 print "wx.VERSION_STRING = ", wx
.VERSION_STRING
 
  14 print "pid:", os
.getpid() 
  15 ##raw_input("Press Enter...") 
  17 class LayoutTestFrame(wx
.Frame
): 
  19         wx
.Frame
.__init
__(self
, None, -1, "Widget Layout Tester") 
  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
) 
  34         self
.expression
.SetBackgroundColour( 
  35             wx
.SystemSettings
.GetColour(wx
.SYS_COLOUR_INFOBK
)) 
  36         self
.docstring
.SetBackgroundColour( 
  37             wx
.SystemSettings
.GetColour(wx
.SYS_COLOUR_INFOBK
)) 
  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") 
  48         self
.createBtn 
= createBtn
 
  49         self
.destroyBtn 
= destroyBtn
 
  51         bottomPanel 
= wx
.Panel(p
, style
=wx
.SUNKEN_BORDER
, name
="bottomPanel") 
  52         bottomPanel
.SetSizeHints((640,240)) 
  53         bottomPanel
.SetDefaultBackgroundColour("light blue") 
  55         self
.testPanel 
= wx
.Panel(bottomPanel
, name
="testPanel") 
  56         self
.testPanel
.SetDefaultBackgroundColour((205, 183, 181)) # mistyrose3 
  57         self
.testWidget 
= None 
  59         self
.infoPane 
= InfoPane(p
) 
  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
) 
  71         self
.Bind(wx
.EVT_CLOSE
, self
.OnSaveHistory
) 
  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
) 
  79         if 'wxMac' in wx
.PlatformInfo 
or 'wxGTK' in wx
.PlatformInfo
: 
  80             self
.testHistory
.Bind(wx
.EVT_KEY_DOWN
, self
.OnHistoryKey
) 
  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
) 
  90         topSizer
.Add(self
.testHistory
, 0, wx
.RIGHT
, 30) 
  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
) 
 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
) 
 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) 
 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
) 
 130         mainSizer
.Add(self
.infoPane
, 0, wx
.EXPAND
) 
 132         self
.bottomSizer 
= sz 
= wx
.BoxSizer(wx
.VERTICAL
) 
 134         sz
.Add(self
.testPanel
, 0, wx
.ALIGN_CENTER
) 
 136         bottomPanel
.SetSizer(sz
) 
 138         p
.SetSizerAndFit(mainSizer
) 
 141         self
.PopulateHistory() 
 146     def PopulateHistory(self
): 
 148         Load and eval a list of lists from a file, load the contents 
 149         into self.testHistory 
 151         fname 
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]), 
 152                              'widgetLayoutTest.cfg') 
 154             self
.history 
= eval(open(fname
).read()) 
 158         self
.testHistory
.Clear() 
 160         for idx 
in range(len(self
.history
)): 
 161             item 
= self
.history
[idx
] 
 162             # check if it is too short 
 166             # add it to the listbox 
 167             self
.testHistory
.Append(item
[0] + '.' + item
[1]) 
 169         self
.needSaved 
= False 
 172     def OnSaveHistory(self
, evt
): 
 174             fname 
= os
.path
.join(os
.path
.dirname(sys
.argv
[0]), 
 175                                  'widgetLayoutTest.cfg') 
 176             f 
= open(fname
, 'wb') 
 178             for item 
in self
.history
: 
 179                 f
.write(str(item
) + ',\n') 
 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() 
 191         item 
= [str(moduleName
), str(className
), str(parameters
), str(postCreate
)] 
 192         self
.history
.append(item
) 
 193         self
.testHistory
.Append(item
[0] + '.' + item
[1]) 
 195         self
.testHistory
.SetSelection(len(self
.history
)-1) 
 196         self
.needSaved 
= True 
 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 
 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() 
 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 
 222     def OnHistorySelect(self
, evt
): 
 223         #idx = self.testHistory.GetSelection() 
 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
: 
 235     def OnHistoryActivate(self
, evt
): 
 236         btn 
= self
.testHistory
.GetParent().GetDefaultItem() 
 238             e 
= wx
.CommandEvent(wx
.wxEVT_COMMAND_BUTTON_CLICKED
, btn
.GetId()) 
 242     def OnHistoryKey(self
, evt
): 
 243         key 
= evt
.GetKeyCode() 
 244         if key 
== wx
.WXK_RETURN
: 
 245             self
.OnHistoryActivate(None) 
 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() 
 256         expr 
= "w = %s.%s( testPanel, %s )" % (moduleName
, className
, parameters
) 
 257         self
.expression
.SetValue(expr
) 
 261             docstring 
= eval("%s.%s.__init__.__doc__" % (moduleName
, className
)) 
 264         if docstring 
is not None: 
 265             self
.docstring
.SetValue(docstring
) 
 267             self
.docstring
.SetValue("") 
 269     def OnEnableDestroy(self
, evt
): 
 270         evt
.Enable(self
.testWidget 
is not None) 
 272     def OnEnableCreate(self
, evt
): 
 273         evt
.Enable(self
.testWidget 
is None) 
 276     def OnCreateWidget(self
, evt
): 
 277         if self
.testWidget 
is not None: 
 280         testPanel 
= self
.testPanel
 
 282         # get the details from the form 
 283         moduleName 
= self
.moduleName
.GetValue() 
 284         className  
= self
.className
.GetValue() 
 285         parameters 
= self
.parameters
.GetValue() 
 286         expr       
= self
.expression
.GetValue()[4:] 
 287         postCreate 
= self
.postCreate
.GetValue() 
 288         if 'wxMac' in wx
.PlatformInfo
: 
 289             postCreate 
= postCreate
.replace('\r', '\n') 
 291         # make sure the module is imported already 
 292         if not sys
.modules
.has_key(moduleName
): 
 294                 m 
= __import__(moduleName
) 
 296                 wx
.MessageBox("Unable to import module!", "Error") 
 303             wx
.MessageBox("Got a '%s' Exception!" % e
.__class
__.__name
__, "Error") 
 305             traceback
.print_exc() 
 308         # Is there postCreate code? 
 314                 exec postCreate 
in ns
 
 316                 wx
.MessageBox("Got a '%s' Exception!" % e
.__class
__.__name
__, "Error") 
 318                 traceback
.print_exc() 
 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
) 
 327         self
.bottomSizer
.Layout() 
 329         # make the destroy button be default now 
 330         self
.destroyBtn
.SetDefault() 
 332         self
.infoPane
.Update(w
, testPanel
) 
 335     def OnDestroyWidget(self
, evt
): 
 336         self
.testWidget
.Destroy() 
 337         self
.testWidget 
= None 
 338         self
.testPanel
.SetSizer(None, True) 
 339         self
.testPanel
.Refresh() 
 341         # ensure the panel shrinks again 
 342         self
.testPanel
.SetSizeHints((20,20)) 
 343         self
.bottomSizer
.Layout() 
 344         self
.testPanel
.SetSizeHints(wx
.DefaultSize
) 
 346         # make the create button be default now 
 347         self
.createBtn
.SetDefault() 
 349         self
.infoPane
.Clear() 
 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("") 
 358         self
.postCreate
.SetValue("") 
 365 class InfoPane(wx
.Panel
): 
 367     This class is used to display details of various properties of the 
 368     widget and the testPanel to aid with debugging. 
 370     def __init__(self
, parent
): 
 371         wx
.Panel
.__init
__(self
, parent
) 
 374         self
.wPane 
= SizeInfoPane(self
, "Widget") 
 375         self
.tpPane
= SizeInfoPane(self
, "testPanel") 
 376         self
.cPane 
= ColourInfoPanel(self
, "Widget colours") 
 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) 
 387     def Update(self
, w
, tp
): 
 389         self
.tpPane
.Update(tp
) 
 399 class SizeInfoPane(wx
.Panel
): 
 401     A component of the InfoPane that shows vaious window size attributes. 
 403     def __init__(self
, parent
, label
): 
 404         wx
.Panel
.__init
__(self
, parent
) 
 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
) 
 414         fgs 
= wx
.FlexGridSizer(2, 2, 5, 5) 
 415         fgs
.AddGrowableCol(1) 
 417         fgs
.Add(wx
.StaticText(self
, -1, "Size:"), 
 418                 0, wx
.ALIGN_RIGHT|wx
.ALIGN_CENTER_VERTICAL
) 
 419         fgs
.Add(self
._size
, 0, wx
.EXPAND
) 
 421         fgs
.Add(wx
.StaticText(self
, -1, "MinSize:"), 
 422                 0, wx
.ALIGN_RIGHT|wx
.ALIGN_CENTER_VERTICAL
) 
 423         fgs
.Add(self
._minsize
, 0, wx
.EXPAND
) 
 425         fgs
.Add(wx
.StaticText(self
, -1, "BestSize:"), 
 426                 0, wx
.ALIGN_RIGHT|wx
.ALIGN_CENTER_VERTICAL
) 
 427         fgs
.Add(self
._bestsize
, 0, wx
.EXPAND
) 
 429         fgs
.Add(wx
.StaticText(self
, -1, "AdjustedBestSize:"), 
 430                 0, wx
.ALIGN_RIGHT|wx
.ALIGN_CENTER_VERTICAL
) 
 431         fgs
.Add(self
._adjbstsize
, 0, wx
.EXPAND
) 
 433         sbs 
= wx
.StaticBoxSizer(sb
, wx
.VERTICAL
) 
 434         sbs
.Add(fgs
, 0, wx
.EXPAND|wx
.ALL
, 4) 
 439     def Update(self
, win
): 
 440         self
._size
.SetValue(       str(win
.GetSize()) ) 
 441         self
._minsize
.SetValue(    str(win
.GetMinSize()) ) 
 442         self
._bestsize
.SetValue(   str(win
.GetBestSize()) ) 
 443         self
._adjbstsize
.SetValue( str(win
.GetAdjustedBestSize()) ) 
 447         self
._size
.SetValue("") 
 448         self
._minsize
.SetValue("") 
 449         self
._bestsize
.SetValue("") 
 450         self
._adjbstsize
.SetValue("") 
 454 class ColourInfoPanel(wx
.Panel
): 
 456     A component of the InfoPane that shows fg and bg colour attributes.     
 458     def __init__(self
, parent
, label
): 
 459         wx
.Panel
.__init
__(self
, parent
) 
 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
.SetSizeHints((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
.SetSizeHints((20,20)) 
 471         fgs 
= wx
.FlexGridSizer(2, 3, 5, 5) 
 472         fgs
.AddGrowableCol(1) 
 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
) 
 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
) 
 484         sbs 
= wx
.StaticBoxSizer(sb
, wx
.VERTICAL
) 
 485         sbs
.Add(fgs
, 0, wx
.EXPAND|wx
.ALL
, 4) 
 490     def Update(self
, win
): 
 492             cp
.SetBackgroundColour(c
) 
 494             return "#%02X%02X%02X" % c
.Get() 
 496         self
._fgtxt
.SetValue( clr2hex(win
.GetForegroundColour(), self
._fgclr
) ) 
 497         self
._bgtxt
.SetValue( clr2hex(win
.GetBackgroundColour(), self
._bgclr
) ) 
 500 ##         print f.GetNativeFontInfo().ToString() 
 504         self
._fgtxt
.SetValue("") 
 505         self
._bgtxt
.SetValue("") 
 506         self
._fgclr
.SetBackgroundColour(self
.GetBackgroundColour()) 
 507         self
._bgclr
.SetBackgroundColour(self
.GetBackgroundColour()) 
 508         self
._fgclr
.Refresh() 
 509         self
._bgclr
.Refresh() 
 514 app 
= wx
.PySimpleApp(redirect
=False) 
 515 frame 
= LayoutTestFrame() 
 516 app
.SetTopWindow(frame
)