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', 
  32                                 'wxFindReplaceDialog', 
  41     ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame', 
  42                  'wxGrid', 'wxSashWindow', 
  43                  'wxScrolledWindow', 'wxSplitterWindow', 
  44                  'wxStatusBar', 'wxNotebook', 
  46                  'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2', 
  50     ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog', 
  51                         'wxSingleChoiceDialog', 'wxTextEntryDialog', 
  52                         'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog', 
  53                         'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog', 
  56     ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice', 
  57                   'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl', 
  58                   'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText', 
  59                   'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar', 
  60                   'wxCalendarCtrl', 'wxToggleButton', 
  63     ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']), 
  65     ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop', 
  67                         'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits', 
  68                         'wxImage', 'wxMask', 'PrintFramework', 'wxOGL', 
  69                         'PythonEvents', 'Threads', 
  70                         'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE', 
  71                         'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave", 
  72                         'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager', 
  75     ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog', 
  76                           'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar', 
  77                           'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow', 
  78                           'FileBrowseButton', 'GenericButtons', 'wxEditor', 
  79                           'ColourSelect', 'ImageBrowser', 
  80                           'infoframe', 'ColourDB', 'PyCrust', 'TablePrint', 
  84     ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']), 
  88 #--------------------------------------------------------------------------- 
  91     def __init__(self
, textCtrl
, logTime
=0): 
  92         wxPyLog
.__init
__(self
) 
  94         self
.logTime 
= logTime
 
  96     def DoLogString(self
, message
, timeStamp
): 
  98             message 
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
 
 100         self
.tc
.AppendText(message 
+ '\n') 
 103 #--------------------------------------------------------------------------- 
 105 class wxPythonDemo(wxFrame
): 
 107     def __init__(self
, parent
, id, title
): 
 108         wxFrame
.__init
__(self
, parent
, -1, title
, size 
= (800, 600), 
 109                          style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
) 
 111         self
.cwd 
= os
.getcwd() 
 112         self
.curOverview 
= "" 
 115             icon 
= wxIconFromXPMData(images
.getMondrianData()) 
 117             # another way to do it 
 118             bmp 
= images
.getMondrianBitmap() 
 120             icon
.CopyFromBitmap(bmp
) 
 124         if wxPlatform 
== '__WXMSW__': 
 125             # setup a taskbar icon, and catch some events from it 
 126             self
.tbicon 
= wxTaskBarIcon() 
 127             self
.tbicon
.SetIcon(icon
, "wxPython Demo") 
 128             EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
) 
 129             EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
) 
 130             EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
) 
 131             EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
) 
 135         EVT_IDLE(self
, self
.OnIdle
) 
 136         EVT_CLOSE(self
, self
.OnCloseWindow
) 
 137         EVT_ICONIZE(self
, self
.OnIconfiy
) 
 138         EVT_MAXIMIZE(self
, self
.OnMaximize
) 
 141         self
.CreateStatusBar(1, wxST_SIZEGRIP
) 
 143         splitter 
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
) 
 144         splitter2 
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
) 
 146         def EmptyHandler(evt
): pass 
 147         EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
) 
 148         EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
) 
 150         # Prevent TreeCtrl from displaying all items after destruction when true 
 154         self
.mainmenu 
= wxMenuBar() 
 157         menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!') 
 158         EVT_MENU(self
, exitID
, self
.OnFileExit
) 
 159         self
.mainmenu
.Append(menu
, '&File') 
 163         for item 
in _treeList
: 
 165             for childItem 
in item
[1]: 
 167                 submenu
.Append(mID
, childItem
) 
 168                 EVT_MENU(self
, mID
, self
.OnDemoMenu
) 
 169             menu
.AppendMenu(wxNewId(), item
[0], submenu
) 
 170         self
.mainmenu
.Append(menu
, '&Demo') 
 176         menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!') 
 177         EVT_MENU(self
, helpID
, self
.OnHelpAbout
) 
 178         self
.mainmenu
.Append(menu
, '&Help') 
 179         self
.SetMenuBar(self
.mainmenu
) 
 181         # set the menu accellerator table... 
 182         aTable 
= wxAcceleratorTable([(wxACCEL_ALT
,  ord('X'), exitID
), 
 183                                      (wxACCEL_CTRL
, ord('H'), helpID
)]) 
 184         self
.SetAcceleratorTable(aTable
) 
 190         self
.tree 
= wxTreeCtrl(splitter
, tID
, 
 191                                style
=wxTR_HAS_BUTTONS |
 
 193                                wxTR_HAS_VARIABLE_ROW_HEIGHT |
 
 195         #self.tree.SetBackgroundColour(wxNamedColour("Pink")) 
 196         root 
= self
.tree
.AddRoot("Overview") 
 198         for item 
in _treeList
: 
 199             child 
= self
.tree
.AppendItem(root
, item
[0]) 
 200             if not firstChild
: firstChild 
= child
 
 201             for childItem 
in item
[1]: 
 202                 theDemo 
= self
.tree
.AppendItem(child
, childItem
) 
 203                 self
.treeMap
[childItem
] = theDemo
 
 205         self
.tree
.Expand(root
) 
 206         self
.tree
.Expand(firstChild
) 
 207         EVT_TREE_ITEM_EXPANDED   (self
.tree
, tID
, self
.OnItemExpanded
) 
 208         EVT_TREE_ITEM_COLLAPSED  (self
.tree
, tID
, self
.OnItemCollapsed
) 
 209         EVT_TREE_SEL_CHANGED     (self
.tree
, tID
, self
.OnSelChanged
) 
 210         EVT_LEFT_DOWN            (self
.tree
,      self
.OnTreeLeftDown
) 
 213         self
.nb 
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
) 
 215         # Set up a wxHtmlWindow on the Overview Notebook page 
 216         # we put it in a panel first because there seems to be a 
 217         # refresh bug of some sort (wxGTK) when it is directly in 
 220             self
.ovr 
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400)) 
 221             self
.nb
.AddPage(self
.ovr
, "Overview") 
 223         else:  # hopefully I can remove this hacky code soon, see bug #216861 
 224             panel 
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
) 
 225             self
.ovr 
= wxHtmlWindow(panel
, -1, size
=(400, 400)) 
 226             self
.nb
.AddPage(panel
, "Overview") 
 228             def OnOvrSize(evt
, ovr
=self
.ovr
): 
 229                 ovr
.SetSize(evt
.GetSize()) 
 231             EVT_SIZE(panel
, OnOvrSize
) 
 232             EVT_ERASE_BACKGROUND(panel
, EmptyHandler
) 
 235         self
.SetOverview("Overview", overview
) 
 238         # Set up a TextCtrl on the Demo Code Notebook page 
 239         self
.txt 
= wxTextCtrl(self
.nb
, -1, 
 240                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 241         self
.nb
.AddPage(self
.txt
, "Demo Code") 
 244         # Set up a log on the View Log Notebook page 
 245         self
.log 
= wxTextCtrl(splitter2
, -1, 
 246                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 247         # Set the wxWindows log target to be this textctrl 
 248         #wxLog_SetActiveTarget(wxLogTextCtrl(self.log)) 
 249         wxLog_SetActiveTarget(MyLog(self
.log
)) 
 255         # add the windows to the splitter and split it. 
 256         splitter2
.SplitHorizontally(self
.nb
, self
.log
) 
 257         splitter2
.SetSashPosition(450, true
) 
 258         splitter2
.SetMinimumPaneSize(20) 
 260         splitter
.SplitVertically(self
.tree
, splitter2
) 
 261         splitter
.SetSashPosition(180, true
) 
 262         splitter
.SetMinimumPaneSize(20) 
 265         # select initial items 
 266         self
.nb
.SetSelection(0) 
 267         self
.tree
.SelectItem(root
) 
 269         if len(sys
.argv
) == 2: 
 271                 selectedDemo 
= self
.treeMap
[sys
.argv
[1]] 
 275                 self
.tree
.SelectItem(selectedDemo
) 
 276                 self
.tree
.EnsureVisible(selectedDemo
) 
 279         wxLogMessage('window handle: %s' % self
.GetHandle()) 
 282     #--------------------------------------------- 
 283     def WriteText(self
, text
): 
 284         if text
[-1:] == '\n': 
 289     def write(self
, txt
): 
 292     #--------------------------------------------- 
 293     def OnItemExpanded(self
, event
): 
 294         item 
= event
.GetItem() 
 295         wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
)) 
 298     #--------------------------------------------- 
 299     def OnItemCollapsed(self
, event
): 
 300         item 
= event
.GetItem() 
 301         wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
)) 
 304     #--------------------------------------------- 
 305     def OnTreeLeftDown(self
, event
): 
 306         pt 
= event
.GetPosition(); 
 307         item
, flags 
= self
.tree
.HitTest(pt
) 
 308         if item 
== self
.tree
.GetSelection(): 
 309             self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
) 
 312     #--------------------------------------------- 
 313     def OnSelChanged(self
, event
): 
 317         item 
= event
.GetItem() 
 318         itemText 
= self
.tree
.GetItemText(item
) 
 319         self
.RunDemo(itemText
) 
 322     #--------------------------------------------- 
 323     def RunDemo(self
, itemText
): 
 325         if self
.nb
.GetPageCount() == 3: 
 326             if self
.nb
.GetSelection() == 2: 
 327                 self
.nb
.SetSelection(0) 
 328             self
.nb
.DeletePage(2) 
 330         if itemText 
== 'Overview': 
 331             self
.GetDemoFile('Main.py') 
 332             self
.SetOverview('Overview', overview
) 
 337             if os
.path
.exists(itemText 
+ '.py'): 
 339                 wxLogMessage("Running demo %s.py..." % itemText
) 
 341                     self
.GetDemoFile(itemText 
+ '.py') 
 342                     module 
= __import__(itemText
, globals()) 
 343                     self
.SetOverview(itemText
, module
.overview
) 
 347                 # in case runTest is modal, make sure things look right... 
 351                 self
.window 
= module
.runTest(self
, self
.nb
, self
) ### 
 353                     self
.nb
.AddPage(self
.window
, 'Demo') 
 355                     self
.nb
.SetSelection(2) 
 364     #--------------------------------------------- 
 366     def GetDemoFile(self
, filename
): 
 369             self
.txt
.SetValue(open(filename
).read()) 
 371             self
.txt
.WriteText("Cannot open %s file." % filename
) 
 373         self
.txt
.SetInsertionPoint(0) 
 374         self
.txt
.ShowPosition(0) 
 376     #--------------------------------------------- 
 377     def SetOverview(self
, name
, text
): 
 378         self
.curOverview 
= text
 
 380         if lead 
!= '<html>' and lead 
!= '<HTML>': 
 381             text 
= string
.join(string
.split(text
, '\n'), '<br>') 
 382             #text = '<font size="-1"><pre>' + text + '</pre></font>' 
 383         self
.ovr
.SetPage(text
) 
 384         self
.nb
.SetPageText(0, name
) 
 386     #--------------------------------------------- 
 388     def OnFileExit(self
, *event
): 
 392     def OnHelpAbout(self
, event
): 
 393         from About 
import MyAboutBox
 
 394         about 
= MyAboutBox(self
) 
 399     #--------------------------------------------- 
 400     def OnCloseWindow(self
, event
): 
 404         if hasattr(self
, "tbicon"): 
 409     #--------------------------------------------- 
 410     def OnIdle(self
, event
): 
 412             self
.otherWin
.Raise() 
 413             self
.window 
= self
.otherWin
 
 416     #--------------------------------------------- 
 417     def OnDemoMenu(self
, event
): 
 419             selectedDemo 
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())] 
 423             self
.tree
.SelectItem(selectedDemo
) 
 424             self
.tree
.EnsureVisible(selectedDemo
) 
 427     #--------------------------------------------- 
 428     def OnTaskBarActivate(self
, evt
): 
 429         if self
.IsIconized(): 
 431         if not self
.IsShown(): 
 435     #--------------------------------------------- 
 437     TBMENU_RESTORE 
= 1000 
 440     def OnTaskBarMenu(self
, evt
): 
 442         menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo") 
 443         menu
.Append(self
.TBMENU_CLOSE
,   "Close") 
 444         self
.tbicon
.PopupMenu(menu
) 
 447     #--------------------------------------------- 
 448     def OnTaskBarClose(self
, evt
): 
 451         # because of the way wxTaskBarIcon.PopupMenu is implemented we have to 
 452         # prod the main idle handler a bit to get the window to actually close 
 453         wxGetApp().ProcessIdle() 
 456     #--------------------------------------------- 
 457     def OnIconfiy(self
, evt
): 
 458         wxLogMessage("OnIconfiy") 
 461     #--------------------------------------------- 
 462     def OnMaximize(self
, evt
): 
 463         wxLogMessage("OnMaximize") 
 469 #--------------------------------------------------------------------------- 
 470 #--------------------------------------------------------------------------- 
 474         wxInitAllImageHandlers() 
 476         self
.splash 
= SplashScreen(None, bitmapfile
='bitmaps/splash.gif', 
 477                               duration
=4000, callback
=self
.AfterSplash
) 
 478         self
.splash
.Show(true
) 
 483     def AfterSplash(self
): 
 484         self
.splash
.Close(true
) 
 485         frame 
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)") 
 487         self
.SetTopWindow(frame
) 
 491     def ShowTip(self
, frame
): 
 493             showTipText 
= open("data/showTips").read() 
 494             showTip
, index 
= eval(showTipText
) 
 496             showTip
, index 
= (1, 0) 
 497         #print showTip, index 
 499             tp 
= wxCreateFileTipProvider("data/tips.txt", index
) 
 500             showTip 
= wxShowTip(frame
, tp
) 
 501             index 
= tp
.GetCurrentTip() 
 502             open("data/showTips", "w").write(str( (showTip
, index
) )) 
 505 #--------------------------------------------------------------------------- 
 509         demoPath 
= os
.path
.dirname(__file__
) 
 517 #--------------------------------------------------------------------------- 
 521 overview 
= """<html><body> 
 524  Python is an interpreted, interactive, object-oriented programming 
 525  language often compared to Tcl, Perl, Scheme, or Java. 
 527  <p> Python combines remarkable power with very clear syntax. It has 
 528  modules, classes, exceptions, very high level dynamic data types, and 
 529  dynamic typing.  There are interfaces to many system calls and 
 530  libraries, and new built-in modules are easily written in C or 
 531  C++. Python is also usable as an extension language for applications 
 532  that need a programmable interface.  <p> 
 536  wxWindows is a free C++ framework designed to make cross-platform 
 537  programming child's play. Well, almost. wxWindows 2 supports Windows 
 538  3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version 
 539  underway. Other ports are under consideration.  <p> 
 541  wxWindows is a set of libraries that allows C++ applications to 
 542  compile and run on several different types of computers, with minimal 
 543  source code changes.  There is one library per supported GUI (such as 
 544  Motif, or Windows). As well as providing a common API (Application 
 545  Programming Interface) for GUI functionality, it provides 
 546  functionality for accessing some commonly-used operating system 
 547  facilities, such as copying or deleting files. wxWindows is a 
 548  'framework' in the sense that it provides a lot of built-in 
 549  functionality, which the application can use or replace as required, 
 550  thus saving a great deal of coding effort. Basic data structures such 
 551  as strings, linked lists and hash tables are also supported. 
 556  wxPython is a Python extension module that encapsulates the wxWindows 
 557  GUI classes. Currently it is only available for the Win32 and GTK 
 558  ports of wxWindows, but as soon as the other ports are brought up to 
 559  the same level as Win32 and GTK, it should be fairly trivial to 
 560  enable wxPython to be used with the new GUI. 
 564  The wxPython extension module attempts to mirror the class heiarchy 
 565  of wxWindows as closely as possible. This means that there is a 
 566  wxFrame class in wxPython that looks, smells, tastes and acts almost 
 567  the same as the wxFrame class in the C++ version. Unfortunately, 
 568  because of differences in the languages, wxPython doesn't match 
 569  wxWindows exactly, but the differences should be easy to absorb 
 570  because they are natural to Python. For example, some methods that 
 571  return multiple values via argument pointers in C++ will return a 
 572  tuple of values in Python. 
 576  There is still much to be done for wxPython, many classes still need 
 577  to be mirrored. Also, wxWindows is still somewhat of a moving target 
 578  so it is a bit of an effort just keeping wxPython up to date. On the 
 579  other hand, there are enough of the core classes completed that 
 580  useful applications can be written. 
 584  wxPython is close enough to the C++ version that the majority of 
 585  the wxPython documentation is actually just notes attached to the C++ 
 586  documents that describe the places where wxPython is different. There 
 587  is also a series of sample programs included, and a series of 
 588  documentation pages that assist the programmer in getting started 
 594 #---------------------------------------------------------------------------- 
 595 #---------------------------------------------------------------------------- 
 597 if __name__ 
== '__main__': 
 600 #----------------------------------------------------------------------------