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 #---------------------------------------------------------------------------- 
  15 from   wxPython
.wx 
import * 
  16 from   wxPython
.lib
.splashscreen 
import SplashScreen
 
  17 from   wxPython
.html 
import wxHtmlWindow
 
  21 #--------------------------------------------------------------------------- 
  25     ('New since last release', ['ContextHelp', 
  31     ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame', 
  33                  'wxGrid', 'wxSashWindow', 
  34                  'wxScrolledWindow', 'wxSplitterWindow', 
  35                  'wxStatusBar', 'wxNotebook', 
  37                  'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',]), 
  39     ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog', 
  40                         'wxSingleChoiceDialog', 'wxTextEntryDialog', 
  41                         'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog', 
  42                         'wxMessageDialog', 'wxProgressDialog']), 
  44     ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice', 
  45                   'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl', 
  46                   'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText', 
  47                   'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar', 
  48                   'wxCalendarCtrl', 'wxToggleButton', 
  51     ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']), 
  53     ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'FontEnumerator', 
  54                         'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits', 
  55                         'wxImage', 'wxMask', 'PrintFramework', 'wxOGL', 
  56                         'PythonEvents', 'Threads', 
  57                         'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE', 
  58                         'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave", 
  62     ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog', 
  63                           'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar', 
  64                           'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow', 
  65                           'FileBrowseButton', 'GenericButtons', 'wxEditor', 
  66                           'ColourSelect', 'ImageBrowser', 
  67                           'infoframe', 'ColourDB', 'PyCrust', 
  70     ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']), 
  74 #--------------------------------------------------------------------------- 
  76 class wxPythonDemo(wxFrame
): 
  78     def __init__(self
, parent
, id, title
): 
  79         wxFrame
.__init
__(self
, parent
, -1, title
, size 
= (800, 600), 
  80                          style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
) 
  82         self
.cwd 
= os
.getcwd() 
  86             icon 
= wxIconFromXPMData(images
.getMondrianData()) 
  88             # another way to do it 
  89             bmp 
= images
.getMondrianBitmap() 
  91             icon
.CopyFromBitmap(bmp
) 
  95         if wxPlatform 
== '__WXMSW__': 
  96             # setup a taskbar icon, and catch some events from it 
  97             self
.tbicon 
= wxTaskBarIcon() 
  98             self
.tbicon
.SetIcon(icon
, "wxPython Demo") 
  99             EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
) 
 100             EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
) 
 101             EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
) 
 102             EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
) 
 106         EVT_IDLE(self
, self
.OnIdle
) 
 107         EVT_CLOSE(self
, self
.OnCloseWindow
) 
 108         EVT_ICONIZE(self
, self
.OnIconfiy
) 
 109         EVT_MAXIMIZE(self
, self
.OnMaximize
) 
 112         self
.CreateStatusBar(1, wxST_SIZEGRIP
) 
 114         splitter 
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
) 
 115         splitter2 
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
) 
 117         def EmptyHandler(evt
): pass 
 118         EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
) 
 119         EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
) 
 121         # Prevent TreeCtrl from displaying all items after destruction 
 125         self
.mainmenu 
= wxMenuBar() 
 128         menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!') 
 129         EVT_MENU(self
, exitID
, self
.OnFileExit
) 
 130         self
.mainmenu
.Append(menu
, '&File') 
 134         for item 
in _treeList
: 
 136             for childItem 
in item
[1]: 
 138                 submenu
.Append(mID
, childItem
) 
 139                 EVT_MENU(self
, mID
, self
.OnDemoMenu
) 
 140             menu
.AppendMenu(wxNewId(), item
[0], submenu
) 
 141         self
.mainmenu
.Append(menu
, '&Demo') 
 147         menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!') 
 148         EVT_MENU(self
, helpID
, self
.OnHelpAbout
) 
 149         self
.mainmenu
.Append(menu
, '&Help') 
 150         self
.SetMenuBar(self
.mainmenu
) 
 152         # set the menu accellerator table... 
 153         aTable 
= wxAcceleratorTable([(wxACCEL_ALT
,  ord('X'), exitID
), 
 154                                      (wxACCEL_CTRL
, ord('H'), helpID
)]) 
 155         self
.SetAcceleratorTable(aTable
) 
 161         self
.tree 
= wxTreeCtrl(splitter
, tID
, 
 162                                style
=wxTR_HAS_BUTTONS |
 
 164                                wxTR_HAS_VARIABLE_ROW_HEIGHT |
 
 166         #self.tree.SetBackgroundColour(wxNamedColour("Pink")) 
 167         root 
= self
.tree
.AddRoot("Overview") 
 169         for item 
in _treeList
: 
 170             child 
= self
.tree
.AppendItem(root
, item
[0]) 
 171             if not firstChild
: firstChild 
= child
 
 172             for childItem 
in item
[1]: 
 173                 theDemo 
= self
.tree
.AppendItem(child
, childItem
) 
 174                 self
.treeMap
[childItem
] = theDemo
 
 176         self
.tree
.Expand(root
) 
 177         self
.tree
.Expand(firstChild
) 
 178         EVT_TREE_ITEM_EXPANDED   (self
.tree
, tID
, self
.OnItemExpanded
) 
 179         EVT_TREE_ITEM_COLLAPSED  (self
.tree
, tID
, self
.OnItemCollapsed
) 
 180         EVT_TREE_SEL_CHANGED     (self
.tree
, tID
, self
.OnSelChanged
) 
 181         EVT_LEFT_DOWN            (self
.tree
,      self
.OnTreeLeftDown
) 
 184         self
.nb 
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
) 
 186         # Set up a wxHtmlWindow on the Overview Notebook page 
 187         # we put it in a panel first because there seems to be a 
 188         # refresh bug of some sort (wxGTK) when it is directly in 
 191             self
.ovr 
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400)) 
 192             self
.nb
.AddPage(self
.ovr
, "Overview") 
 194         else:  # hopefully I can remove this hacky code soon, see bug #216861 
 195             panel 
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
) 
 196             self
.ovr 
= wxHtmlWindow(panel
, -1, size
=(400, 400)) 
 197             self
.nb
.AddPage(panel
, "Overview") 
 199             def OnOvrSize(evt
, ovr
=self
.ovr
): 
 200                 ovr
.SetSize(evt
.GetSize()) 
 202             EVT_SIZE(panel
, OnOvrSize
) 
 203             EVT_ERASE_BACKGROUND(panel
, EmptyHandler
) 
 206         self
.SetOverview("Overview", overview
) 
 209         # Set up a TextCtrl on the Demo Code Notebook page 
 210         self
.txt 
= wxTextCtrl(self
.nb
, -1, 
 211                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 212         self
.txt
.SetFont(wxFont(9, wxMODERN
, wxNORMAL
, wxNORMAL
, false
)) 
 213         self
.nb
.AddPage(self
.txt
, "Demo Code") 
 216         # Set up a log on the View Log Notebook page 
 217         self
.log 
= wxTextCtrl(splitter2
, -1, 
 218                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 219         # Set the wxWindows log target to be this textctrl 
 220         wxLog_SetActiveTarget(wxLogTextCtrl(self
.log
)) 
 226         # add the windows to the splitter and split it. 
 227         splitter2
.SplitHorizontally(self
.nb
, self
.log
) 
 228         splitter2
.SetSashPosition(450, true
) 
 229         splitter2
.SetMinimumPaneSize(20) 
 231         splitter
.SplitVertically(self
.tree
, splitter2
) 
 232         splitter
.SetSashPosition(180, true
) 
 233         splitter
.SetMinimumPaneSize(20) 
 236         # select initial items 
 237         self
.nb
.SetSelection(0) 
 238         self
.tree
.SelectItem(root
) 
 240         if len(sys
.argv
) == 2: 
 242                 selectedDemo 
= self
.treeMap
[sys
.argv
[1]] 
 246                 self
.tree
.SelectItem(selectedDemo
) 
 247                 self
.tree
.EnsureVisible(selectedDemo
) 
 250         wxLogMessage('window handle: %s' % self
.GetHandle()) 
 253     #--------------------------------------------- 
 254     def WriteText(self
, text
): 
 255         if text
[-1:] == '\n': 
 260     def write(self
, txt
): 
 263     #--------------------------------------------- 
 264     def OnItemExpanded(self
, event
): 
 265         item 
= event
.GetItem() 
 266         wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
)) 
 269     #--------------------------------------------- 
 270     def OnItemCollapsed(self
, event
): 
 271         item 
= event
.GetItem() 
 272         wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
)) 
 275     #--------------------------------------------- 
 276     def OnTreeLeftDown(self
, event
): 
 277         pt 
= event
.GetPosition(); 
 278         item
, flags 
= self
.tree
.HitTest(pt
) 
 279         if item 
== self
.tree
.GetSelection(): 
 280             self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
) 
 283     #--------------------------------------------- 
 284     def OnSelChanged(self
, event
): 
 288         item 
= event
.GetItem() 
 289         itemText 
= self
.tree
.GetItemText(item
) 
 290         self
.RunDemo(itemText
) 
 293     #--------------------------------------------- 
 294     def RunDemo(self
, itemText
): 
 296         if self
.nb
.GetPageCount() == 3: 
 297             if self
.nb
.GetSelection() == 2: 
 298                 self
.nb
.SetSelection(0) 
 299             self
.nb
.DeletePage(2) 
 301         if itemText 
== 'Overview': 
 302             self
.GetDemoFile('Main.py') 
 303             self
.SetOverview('Overview', overview
) 
 308             if os
.path
.exists(itemText 
+ '.py'): 
 310                 wxLogMessage("Running demo %s.py..." % itemText
) 
 312                     self
.GetDemoFile(itemText 
+ '.py') 
 313                     module 
= __import__(itemText
, globals()) 
 314                     self
.SetOverview(itemText
, module
.overview
) 
 318                 # in case runTest is modal, make sure things look right... 
 322                 self
.window 
= module
.runTest(self
, self
.nb
, self
) ### 
 324                     self
.nb
.AddPage(self
.window
, 'Demo') 
 326                     self
.nb
.SetSelection(2) 
 335     #--------------------------------------------- 
 337     def GetDemoFile(self
, filename
): 
 340             self
.txt
.SetValue(open(filename
).read()) 
 342             self
.txt
.WriteText("Cannot open %s file." % filename
) 
 344         self
.txt
.SetInsertionPoint(0) 
 345         self
.txt
.ShowPosition(0) 
 347     #--------------------------------------------- 
 348     def SetOverview(self
, name
, text
): 
 349         self
.curOverview 
= text
 
 351         if lead 
!= '<html>' and lead 
!= '<HTML>': 
 352             text 
= string
.join(string
.split(text
, '\n'), '<br>') 
 353             #text = '<font size="-1"><pre>' + text + '</pre></font>' 
 354         self
.ovr
.SetPage(text
) 
 355         self
.nb
.SetPageText(0, name
) 
 357     #--------------------------------------------- 
 359     def OnFileExit(self
, *event
): 
 363     def OnHelpAbout(self
, event
): 
 364         from About 
import MyAboutBox
 
 365         about 
= MyAboutBox(self
) 
 370     #--------------------------------------------- 
 371     def OnCloseWindow(self
, event
): 
 375         if hasattr(self
, "tbicon"): 
 380     #--------------------------------------------- 
 381     def OnIdle(self
, event
): 
 383             self
.otherWin
.Raise() 
 384             self
.window 
= self
.otherWin
 
 387     #--------------------------------------------- 
 388     def OnDemoMenu(self
, event
): 
 390             selectedDemo 
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())] 
 394             self
.tree
.SelectItem(selectedDemo
) 
 395             self
.tree
.EnsureVisible(selectedDemo
) 
 398     #--------------------------------------------- 
 399     def OnTaskBarActivate(self
, evt
): 
 400         if self
.IsIconized(): 
 402         if not self
.IsShown(): 
 406     #--------------------------------------------- 
 408     TBMENU_RESTORE 
= 1000 
 411     def OnTaskBarMenu(self
, evt
): 
 413         menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo") 
 414         menu
.Append(self
.TBMENU_CLOSE
,   "Close") 
 415         self
.tbicon
.PopupMenu(menu
) 
 418     #--------------------------------------------- 
 419     def OnTaskBarClose(self
, evt
): 
 422         # because of the way wxTaskBarIcon.PopupMenu is implemented we have to 
 423         # prod the main idle handler a bit to get the window to actually close 
 424         wxGetApp().ProcessIdle() 
 427     #--------------------------------------------- 
 428     def OnIconfiy(self
, evt
): 
 429         wxLogMessage("OnIconfiy") 
 432     #--------------------------------------------- 
 433     def OnMaximize(self
, evt
): 
 434         wxLogMessage("OnMaximize") 
 440 #--------------------------------------------------------------------------- 
 441 #--------------------------------------------------------------------------- 
 445         wxInitAllImageHandlers() 
 447         self
.splash 
= SplashScreen(None, bitmapfile
='bitmaps/splash.gif', 
 448                               duration
=4000, callback
=self
.AfterSplash
) 
 449         self
.splash
.Show(true
) 
 454     def AfterSplash(self
): 
 455         self
.splash
.Close(true
) 
 456         frame 
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)") 
 458         self
.SetTopWindow(frame
) 
 462     def ShowTip(self
, frame
): 
 464             showTipText 
= open("data/showTips").read() 
 465             showTip
, index 
= eval(showTipText
) 
 467             showTip
, index 
= (1, 0) 
 468         #print showTip, index 
 470             tp 
= wxCreateFileTipProvider("data/tips.txt", index
) 
 471             showTip 
= wxShowTip(frame
, tp
) 
 472             index 
= tp
.GetCurrentTip() 
 473             open("data/showTips", "w").write(str( (showTip
, index
) )) 
 476 #--------------------------------------------------------------------------- 
 480         demoPath 
= os
.path
.dirname(__file__
) 
 488 #--------------------------------------------------------------------------- 
 492 overview 
= """<html><body> 
 495  Python is an interpreted, interactive, object-oriented programming 
 496  language often compared to Tcl, Perl, Scheme, or Java. 
 498  <p> Python combines remarkable power with very clear syntax. It has 
 499  modules, classes, exceptions, very high level dynamic data types, and 
 500  dynamic typing.  There are interfaces to many system calls and 
 501  libraries, and new built-in modules are easily written in C or 
 502  C++. Python is also usable as an extension language for applications 
 503  that need a programmable interface.  <p> 
 507  wxWindows is a free C++ framework designed to make cross-platform 
 508  programming child's play. Well, almost. wxWindows 2 supports Windows 
 509  3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version 
 510  underway. Other ports are under consideration.  <p> 
 512  wxWindows is a set of libraries that allows C++ applications to 
 513  compile and run on several different types of computers, with minimal 
 514  source code changes.  There is one library per supported GUI (such as 
 515  Motif, or Windows). As well as providing a common API (Application 
 516  Programming Interface) for GUI functionality, it provides 
 517  functionality for accessing some commonly-used operating system 
 518  facilities, such as copying or deleting files. wxWindows is a 
 519  'framework' in the sense that it provides a lot of built-in 
 520  functionality, which the application can use or replace as required, 
 521  thus saving a great deal of coding effort. Basic data structures such 
 522  as strings, linked lists and hash tables are also supported. 
 527  wxPython is a Python extension module that encapsulates the wxWindows 
 528  GUI classes. Currently it is only available for the Win32 and GTK 
 529  ports of wxWindows, but as soon as the other ports are brought up to 
 530  the same level as Win32 and GTK, it should be fairly trivial to 
 531  enable wxPython to be used with the new GUI. 
 535  The wxPython extension module attempts to mirror the class heiarchy 
 536  of wxWindows as closely as possible. This means that there is a 
 537  wxFrame class in wxPython that looks, smells, tastes and acts almost 
 538  the same as the wxFrame class in the C++ version. Unfortunately, 
 539  because of differences in the languages, wxPython doesn't match 
 540  wxWindows exactly, but the differences should be easy to absorb 
 541  because they are natural to Python. For example, some methods that 
 542  return multiple values via argument pointers in C++ will return a 
 543  tuple of values in Python. 
 547  There is still much to be done for wxPython, many classes still need 
 548  to be mirrored. Also, wxWindows is still somewhat of a moving target 
 549  so it is a bit of an effort just keeping wxPython up to date. On the 
 550  other hand, there are enough of the core classes completed that 
 551  useful applications can be written. 
 555  wxPython is close enough to the C++ version that the majority of 
 556  the wxPython documentation is actually just notes attached to the C++ 
 557  documents that describe the places where wxPython is different. There 
 558  is also a series of sample programs included, and a series of 
 559  documentation pages that assist the programmer in getting started 
 565 #---------------------------------------------------------------------------- 
 566 #---------------------------------------------------------------------------- 
 568 if __name__ 
== '__main__': 
 571 #----------------------------------------------------------------------------