2 #---------------------------------------------------------------------------- 
   4 # Purpose:      Testing lots of stuff, controls, window types, etc. 
   8 # Created:      A long time ago, in a galaxy far, far away... 
  10 # Copyright:    (c) 1999 by Total Control Software 
  11 # Licence:      wxWindows license 
  12 #---------------------------------------------------------------------------- 
  14 import sys
, os
, time
, string
 
  15 from   wxPython
.wx 
import * 
  16 from   wxPython
.html 
import wxHtmlWindow
 
  20 #--------------------------------------------------------------------------- 
  24     ('New since last release', ['wxGenericDirCtrl', 
  28     ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame', 
  29                  'wxGrid', 'wxSashWindow', 
  30                  'wxScrolledWindow', 'wxSplitterWindow', 
  31                  'wxStatusBar', 'wxNotebook', 
  33                  'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2', 
  35                  'wxDynamicSashWindow', 
  38     ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog', 
  39                         'wxSingleChoiceDialog', 'wxTextEntryDialog', 
  40                         'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog', 
  41                         'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog', 
  44     ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice', 
  45                   'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'VirtualListCtrl', 
  47                   'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText', 
  48                   'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar', 
  49                   'wxCalendarCtrl', 'wxToggleButton', 
  50                   'wxEditableListBox', 'wxLEDNumberCtrl', 
  53     ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']), 
  55     ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop', 
  57                         'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits', 
  58                         'wxImage', 'wxMask', 'PrintFramework', 'wxOGL', 
  59                         'PythonEvents', 'Threads', 
  60                         'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE', 
  61                         'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave", 
  62                         'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager', 
  63                         'ContextHelp', 'SplitTree', 
  66     ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog', 
  67                           'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar', 
  68                           'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow', 
  69                           'FileBrowseButton', 'GenericButtons', 'wxEditor', 
  70                           'ColourSelect', 'ImageBrowser', 
  71                           'infoframe', 'ColourDB', 'PyCrust', 'PyCrustWithFilling', 
  76     ('Cool Contribs', ['pyTree', 'hangman', 
  83 #--------------------------------------------------------------------------- 
  86     def __init__(self
, textCtrl
, logTime
=0): 
  87         wxPyLog
.__init
__(self
) 
  89         self
.logTime 
= logTime
 
  91     def DoLogString(self
, message
, timeStamp
): 
  93             message 
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
 
  95         self
.tc
.AppendText(message 
+ '\n') 
  98 #--------------------------------------------------------------------------- 
 101     """Convert paths to the platform-specific separator""" 
 102     return apply(os
.path
.join
, tuple(string
.split(path
, '/'))) 
 105 #--------------------------------------------------------------------------- 
 107 class wxPythonDemo(wxFrame
): 
 109     def __init__(self
, parent
, id, title
): 
 110         wxFrame
.__init
__(self
, parent
, -1, title
, size 
= (800, 600), 
 111                          style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
) 
 113         self
.cwd 
= os
.getcwd() 
 114         self
.curOverview 
= "" 
 116         icon 
= images
.getMondrianIcon() 
 119         if wxPlatform 
== '__WXMSW__': 
 120             # setup a taskbar icon, and catch some events from it 
 121             self
.tbicon 
= wxTaskBarIcon() 
 122             self
.tbicon
.SetIcon(icon
, "wxPython Demo") 
 123             EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
) 
 124             EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
) 
 125             EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
) 
 126             EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
) 
 130         EVT_IDLE(self
, self
.OnIdle
) 
 131         EVT_CLOSE(self
, self
.OnCloseWindow
) 
 132         EVT_ICONIZE(self
, self
.OnIconfiy
) 
 133         EVT_MAXIMIZE(self
, self
.OnMaximize
) 
 136         self
.CreateStatusBar(1, wxST_SIZEGRIP
) 
 138         splitter 
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
) 
 139         splitter2 
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
) 
 141         def EmptyHandler(evt
): pass 
 142         EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
) 
 143         EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
) 
 145         # Prevent TreeCtrl from displaying all items after destruction when true 
 149         self
.mainmenu 
= wxMenuBar() 
 152         menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!') 
 153         EVT_MENU(self
, exitID
, self
.OnFileExit
) 
 154         self
.mainmenu
.Append(menu
, '&File') 
 158         for item 
in _treeList
: 
 160             for childItem 
in item
[1]: 
 162                 submenu
.Append(mID
, childItem
) 
 163                 EVT_MENU(self
, mID
, self
.OnDemoMenu
) 
 164             menu
.AppendMenu(wxNewId(), item
[0], submenu
) 
 165         self
.mainmenu
.Append(menu
, '&Demo') 
 171         menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!') 
 172         EVT_MENU(self
, helpID
, self
.OnHelpAbout
) 
 173         self
.mainmenu
.Append(menu
, '&Help') 
 174         self
.SetMenuBar(self
.mainmenu
) 
 176         # set the menu accellerator table... 
 177         aTable 
= wxAcceleratorTable([(wxACCEL_ALT
,  ord('X'), exitID
), 
 178                                      (wxACCEL_CTRL
, ord('H'), helpID
)]) 
 179         self
.SetAcceleratorTable(aTable
) 
 185         self
.tree 
= wxTreeCtrl(splitter
, tID
, 
 186                                style
=wxTR_HAS_BUTTONS |
 
 188                                wxTR_HAS_VARIABLE_ROW_HEIGHT
) 
 190         #self.tree.SetBackgroundColour(wxNamedColour("Pink")) 
 191         root 
= self
.tree
.AddRoot("Overview") 
 193         for item 
in _treeList
: 
 194             child 
= self
.tree
.AppendItem(root
, item
[0]) 
 195             if not firstChild
: firstChild 
= child
 
 196             for childItem 
in item
[1]: 
 197                 theDemo 
= self
.tree
.AppendItem(child
, childItem
) 
 198                 self
.treeMap
[childItem
] = theDemo
 
 200         self
.tree
.Expand(root
) 
 201         self
.tree
.Expand(firstChild
) 
 202         EVT_TREE_ITEM_EXPANDED   (self
.tree
, tID
, self
.OnItemExpanded
) 
 203         EVT_TREE_ITEM_COLLAPSED  (self
.tree
, tID
, self
.OnItemCollapsed
) 
 204         EVT_TREE_SEL_CHANGED     (self
.tree
, tID
, self
.OnSelChanged
) 
 205         EVT_LEFT_DOWN            (self
.tree
,      self
.OnTreeLeftDown
) 
 208         self
.nb 
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
) 
 210         # Set up a wxHtmlWindow on the Overview Notebook page 
 211         # we put it in a panel first because there seems to be a 
 212         # refresh bug of some sort (wxGTK) when it is directly in 
 215             self
.ovr 
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400)) 
 216             self
.nb
.AddPage(self
.ovr
, "Overview") 
 218         else:  # hopefully I can remove this hacky code soon, see bug #216861 
 219             panel 
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
) 
 220             self
.ovr 
= wxHtmlWindow(panel
, -1, size
=(400, 400)) 
 221             self
.nb
.AddPage(panel
, "Overview") 
 223             def OnOvrSize(evt
, ovr
=self
.ovr
): 
 224                 ovr
.SetSize(evt
.GetSize()) 
 226             EVT_SIZE(panel
, OnOvrSize
) 
 227             EVT_ERASE_BACKGROUND(panel
, EmptyHandler
) 
 230         self
.SetOverview("Overview", overview
) 
 233         # Set up a TextCtrl on the Demo Code Notebook page 
 234         self
.txt 
= wxTextCtrl(self
.nb
, -1, 
 235                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 236         self
.nb
.AddPage(self
.txt
, "Demo Code") 
 239         # Set up a log on the View Log Notebook page 
 240         self
.log 
= wxTextCtrl(splitter2
, -1, 
 241                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 242         # Set the wxWindows log target to be this textctrl 
 243         #wxLog_SetActiveTarget(wxLogTextCtrl(self.log)) 
 244         wxLog_SetActiveTarget(MyLog(self
.log
)) 
 250         # add the windows to the splitter and split it. 
 251         splitter2
.SplitHorizontally(self
.nb
, self
.log
) 
 252         splitter
.SplitVertically(self
.tree
, splitter2
) 
 254         splitter
.SetSashPosition(180, true
) 
 255         splitter
.SetMinimumPaneSize(20) 
 256         splitter2
.SetSashPosition(450, true
) 
 257         splitter2
.SetMinimumPaneSize(20) 
 261         # select initial items 
 262         self
.nb
.SetSelection(0) 
 263         self
.tree
.SelectItem(root
) 
 265         if len(sys
.argv
) == 2: 
 267                 selectedDemo 
= self
.treeMap
[sys
.argv
[1]] 
 271                 self
.tree
.SelectItem(selectedDemo
) 
 272                 self
.tree
.EnsureVisible(selectedDemo
) 
 275         wxLogMessage('window handle: %s' % self
.GetHandle()) 
 278     #--------------------------------------------- 
 279     def WriteText(self
, text
): 
 280         if text
[-1:] == '\n': 
 285     def write(self
, txt
): 
 288     #--------------------------------------------- 
 289     def OnItemExpanded(self
, event
): 
 290         item 
= event
.GetItem() 
 291         wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
)) 
 294     #--------------------------------------------- 
 295     def OnItemCollapsed(self
, event
): 
 296         item 
= event
.GetItem() 
 297         wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
)) 
 300     #--------------------------------------------- 
 301     def OnTreeLeftDown(self
, event
): 
 302         pt 
= event
.GetPosition(); 
 303         item
, flags 
= self
.tree
.HitTest(pt
) 
 304         if item 
== self
.tree
.GetSelection(): 
 305             self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
) 
 308     #--------------------------------------------- 
 309     def OnSelChanged(self
, event
): 
 313         item 
= event
.GetItem() 
 314         itemText 
= self
.tree
.GetItemText(item
) 
 315         self
.RunDemo(itemText
) 
 318     #--------------------------------------------- 
 319     def RunDemo(self
, itemText
): 
 321         if self
.nb
.GetPageCount() == 3: 
 322             if self
.nb
.GetSelection() == 2: 
 323                 self
.nb
.SetSelection(0) 
 324             self
.nb
.DeletePage(2) 
 326         if itemText 
== 'Overview': 
 327             self
.GetDemoFile('Main.py') 
 328             self
.SetOverview('Overview', overview
) 
 333             if os
.path
.exists(itemText 
+ '.py'): 
 335                 wxLogMessage("Running demo %s.py..." % itemText
) 
 337                     self
.GetDemoFile(itemText 
+ '.py') 
 338                     module 
= __import__(itemText
, globals()) 
 339                     self
.SetOverview(itemText
, module
.overview
) 
 343                 # in case runTest is modal, make sure things look right... 
 347                 self
.window 
= module
.runTest(self
, self
.nb
, self
) ### 
 349                     self
.nb
.AddPage(self
.window
, 'Demo') 
 351                     self
.nb
.SetSelection(2) 
 360     #--------------------------------------------- 
 362     def GetDemoFile(self
, filename
): 
 365             self
.txt
.SetValue(open(filename
).read()) 
 367             self
.txt
.WriteText("Cannot open %s file." % filename
) 
 369         self
.txt
.SetInsertionPoint(0) 
 370         self
.txt
.ShowPosition(0) 
 372     #--------------------------------------------- 
 373     def SetOverview(self
, name
, text
): 
 374         self
.curOverview 
= text
 
 376         if lead 
!= '<html>' and lead 
!= '<HTML>': 
 377             text 
= string
.join(string
.split(text
, '\n'), '<br>') 
 378         self
.ovr
.SetPage(text
) 
 379         self
.nb
.SetPageText(0, name
) 
 381     #--------------------------------------------- 
 383     def OnFileExit(self
, *event
): 
 387     def OnHelpAbout(self
, event
): 
 388         from About 
import MyAboutBox
 
 389         about 
= MyAboutBox(self
) 
 394     #--------------------------------------------- 
 395     def OnCloseWindow(self
, event
): 
 399         if hasattr(self
, "tbicon"): 
 404     #--------------------------------------------- 
 405     def OnIdle(self
, event
): 
 407             self
.otherWin
.Raise() 
 408             self
.window 
= self
.otherWin
 
 411     #--------------------------------------------- 
 412     def OnDemoMenu(self
, event
): 
 414             selectedDemo 
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())] 
 418             self
.tree
.SelectItem(selectedDemo
) 
 419             self
.tree
.EnsureVisible(selectedDemo
) 
 422     #--------------------------------------------- 
 423     def OnTaskBarActivate(self
, evt
): 
 424         if self
.IsIconized(): 
 426         if not self
.IsShown(): 
 430     #--------------------------------------------- 
 432     TBMENU_RESTORE 
= 1000 
 435     def OnTaskBarMenu(self
, evt
): 
 437         menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo") 
 438         menu
.Append(self
.TBMENU_CLOSE
,   "Close") 
 439         self
.tbicon
.PopupMenu(menu
) 
 442     #--------------------------------------------- 
 443     def OnTaskBarClose(self
, evt
): 
 446         # because of the way wxTaskBarIcon.PopupMenu is implemented we have to 
 447         # prod the main idle handler a bit to get the window to actually close 
 448         wxGetApp().ProcessIdle() 
 451     #--------------------------------------------- 
 452     def OnIconfiy(self
, evt
): 
 453         wxLogMessage("OnIconfiy") 
 456     #--------------------------------------------- 
 457     def OnMaximize(self
, evt
): 
 458         wxLogMessage("OnMaximize") 
 464 #--------------------------------------------------------------------------- 
 465 #--------------------------------------------------------------------------- 
 467 class MySplashScreen(wxSplashScreen
): 
 469         bmp 
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap() 
 470         wxSplashScreen
.__init
__(self
, bmp
, 
 471                                 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
, 
 473         EVT_CLOSE(self
, self
.OnClose
) 
 475     def OnClose(self
, evt
): 
 476         frame 
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)") 
 481     def ShowTip(self
, frame
): 
 483             showTipText 
= open(opj("data/showTips")).read() 
 484             showTip
, index 
= eval(showTipText
) 
 486             showTip
, index 
= (1, 0) 
 488             tp 
= wxCreateFileTipProvider(opj("data/tips.txt"), index
) 
 489             showTip 
= wxShowTip(frame
, tp
) 
 490             index 
= tp
.GetCurrentTip() 
 491             open(opj("data/showTips"), "w").write(str( (showTip
, index
) )) 
 498         Create and show the splash screen.  It will then create and show 
 499         the main frame when it is time to do so. 
 501         wxInitAllImageHandlers() 
 502         splash 
= MySplashScreen() 
 509 #--------------------------------------------------------------------------- 
 513         demoPath 
= os
.path
.dirname(__file__
) 
 521 #--------------------------------------------------------------------------- 
 525 overview 
= """<html><body> 
 528  Python is an interpreted, interactive, object-oriented programming 
 529  language often compared to Tcl, Perl, Scheme, or Java. 
 531  <p> Python combines remarkable power with very clear syntax. It has 
 532  modules, classes, exceptions, very high level dynamic data types, and 
 533  dynamic typing.  There are interfaces to many system calls and 
 534  libraries, and new built-in modules are easily written in C or 
 535  C++. Python is also usable as an extension language for applications 
 536  that need a programmable interface.  <p> 
 540  wxWindows is a free C++ framework designed to make cross-platform 
 541  programming child's play. Well, almost. wxWindows 2 supports Windows 
 542  3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version 
 543  underway. Other ports are under consideration.  <p> 
 545  wxWindows is a set of libraries that allows C++ applications to 
 546  compile and run on several different types of computers, with minimal 
 547  source code changes.  There is one library per supported GUI (such as 
 548  Motif, or Windows). As well as providing a common API (Application 
 549  Programming Interface) for GUI functionality, it provides 
 550  functionality for accessing some commonly-used operating system 
 551  facilities, such as copying or deleting files. wxWindows is a 
 552  'framework' in the sense that it provides a lot of built-in 
 553  functionality, which the application can use or replace as required, 
 554  thus saving a great deal of coding effort. Basic data structures such 
 555  as strings, linked lists and hash tables are also supported. 
 560  wxPython is a Python extension module that encapsulates the wxWindows 
 561  GUI classes. Currently it is only available for the Win32 and GTK 
 562  ports of wxWindows, but as soon as the other ports are brought up to 
 563  the same level as Win32 and GTK, it should be fairly trivial to 
 564  enable wxPython to be used with the new GUI. 
 568  The wxPython extension module attempts to mirror the class heiarchy 
 569  of wxWindows as closely as possible. This means that there is a 
 570  wxFrame class in wxPython that looks, smells, tastes and acts almost 
 571  the same as the wxFrame class in the C++ version. Unfortunately, 
 572  because of differences in the languages, wxPython doesn't match 
 573  wxWindows exactly, but the differences should be easy to absorb 
 574  because they are natural to Python. For example, some methods that 
 575  return multiple values via argument pointers in C++ will return a 
 576  tuple of values in Python. 
 580  There is still much to be done for wxPython, many classes still need 
 581  to be mirrored. Also, wxWindows is still somewhat of a moving target 
 582  so it is a bit of an effort just keeping wxPython up to date. On the 
 583  other hand, there are enough of the core classes completed that 
 584  useful applications can be written. 
 588  wxPython is close enough to the C++ version that the majority of 
 589  the wxPython documentation is actually just notes attached to the C++ 
 590  documents that describe the places where wxPython is different. There 
 591  is also a series of sample programs included, and a series of 
 592  documentation pages that assist the programmer in getting started 
 598 #---------------------------------------------------------------------------- 
 599 #---------------------------------------------------------------------------- 
 601 if __name__ 
== '__main__': 
 604 #----------------------------------------------------------------------------