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
 
  18 ##from wxPython.stc import * 
  22 #--------------------------------------------------------------------------- 
  27     ('New since last release', [ 
  38     # managed windows == things with a caption you can close 
  39     ('Base Frames and Dialogs', [ 
  51         'wxFindReplaceDialog', 
  57         'wxSingleChoiceDialog', 
  61     # dialogs form libraries 
  65         'wxMultipleChoiceDialog', 
  66         'wxScrolledMessageDialog', 
  70     ('Core Windows/Controls', [ 
 102     # controls coming from other librairies 
 103     ('More Windows/Controls', [ 
 110         'PyCrustWithFilling', 
 115         'wxDynamicSashWindow', 
 121         'wxMimeTypesManager', 
 123         'wxStyledTextCtrl_1', 
 124         'wxStyledTextCtrl_2', 
 128     # How to lay out the controls in a frame/dialog 
 135         'wxLayoutConstraints', 
 140     ('Process and Events', [ 
 150     ('Clipboard and DnD', [ 
 179     # need libs not coming with the demo 
 180     ('Objects using an external library', [ 
 181         'ActiveXWrapper_Acrobat', 
 187     # pyTree, hangman, ... in the samples dir 
 188     ('Check out the samples dir too', [ 
 195 #--------------------------------------------------------------------------- 
 197 class MyLog(wxPyLog
): 
 198     def __init__(self
, textCtrl
, logTime
=0): 
 199         wxPyLog
.__init
__(self
) 
 201         self
.logTime 
= logTime
 
 203     def DoLogString(self
, message
, timeStamp
): 
 205             message 
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
 
 207         self
.tc
.AppendText(message 
+ '\n') 
 210 #--------------------------------------------------------------------------- 
 213     """Convert paths to the platform-specific separator""" 
 214     return apply(os
.path
.join
, tuple(string
.split(path
, '/'))) 
 217 #--------------------------------------------------------------------------- 
 219 class wxPythonDemo(wxFrame
): 
 220     overviewText 
= "wxPython Overview" 
 222     def __init__(self
, parent
, id, title
): 
 223         wxFrame
.__init
__(self
, parent
, -1, title
, size 
= (800, 600), 
 224                          style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
) 
 226         self
.cwd 
= os
.getcwd() 
 227         self
.curOverview 
= "" 
 229         icon 
= images
.getMondrianIcon() 
 232         if wxPlatform 
== '__WXMSW__': 
 233             # setup a taskbar icon, and catch some events from it 
 234             self
.tbicon 
= wxTaskBarIcon() 
 235             self
.tbicon
.SetIcon(icon
, "wxPython Demo") 
 236             EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
) 
 237             EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
) 
 238             EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
) 
 239             EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
) 
 244         EVT_IDLE(self
, self
.OnIdle
) 
 245         EVT_CLOSE(self
, self
.OnCloseWindow
) 
 246         EVT_ICONIZE(self
, self
.OnIconfiy
) 
 247         EVT_MAXIMIZE(self
, self
.OnMaximize
) 
 250         self
.CreateStatusBar(1, wxST_SIZEGRIP
) 
 252         splitter 
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
) 
 253         splitter2 
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
) 
 255         def EmptyHandler(evt
): pass 
 256         EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
) 
 257         EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
) 
 259         # Prevent TreeCtrl from displaying all items after destruction when true 
 263         self
.mainmenu 
= wxMenuBar() 
 266         menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!') 
 267         EVT_MENU(self
, exitID
, self
.OnFileExit
) 
 268         self
.mainmenu
.Append(menu
, '&File') 
 272         for item 
in _treeList
: 
 274             for childItem 
in item
[1]: 
 276                 submenu
.Append(mID
, childItem
) 
 277                 EVT_MENU(self
, mID
, self
.OnDemoMenu
) 
 278             menu
.AppendMenu(wxNewId(), item
[0], submenu
) 
 279         self
.mainmenu
.Append(menu
, '&Demo') 
 285         menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!') 
 286         EVT_MENU(self
, helpID
, self
.OnHelpAbout
) 
 287         self
.mainmenu
.Append(menu
, '&Help') 
 288         self
.SetMenuBar(self
.mainmenu
) 
 290         # set the menu accellerator table... 
 291         aTable 
= wxAcceleratorTable([(wxACCEL_ALT
,  ord('X'), exitID
), 
 292                                      (wxACCEL_CTRL
, ord('H'), helpID
)]) 
 293         self
.SetAcceleratorTable(aTable
) 
 299         self
.tree 
= wxTreeCtrl(splitter
, tID
, 
 300                                style
=wxTR_HAS_BUTTONS |
 
 302                                wxTR_HAS_VARIABLE_ROW_HEIGHT
) 
 304         #self.tree.SetBackgroundColour(wxNamedColour("Pink")) 
 305         root 
= self
.tree
.AddRoot("wxPython Overview") 
 307         for item 
in _treeList
: 
 308             child 
= self
.tree
.AppendItem(root
, item
[0]) 
 309             if not firstChild
: firstChild 
= child
 
 310             for childItem 
in item
[1]: 
 311                 theDemo 
= self
.tree
.AppendItem(child
, childItem
) 
 312                 self
.treeMap
[childItem
] = theDemo
 
 314         self
.tree
.Expand(root
) 
 315         self
.tree
.Expand(firstChild
) 
 316         EVT_TREE_ITEM_EXPANDED   (self
.tree
, tID
, self
.OnItemExpanded
) 
 317         EVT_TREE_ITEM_COLLAPSED  (self
.tree
, tID
, self
.OnItemCollapsed
) 
 318         EVT_TREE_SEL_CHANGED     (self
.tree
, tID
, self
.OnSelChanged
) 
 319         EVT_LEFT_DOWN            (self
.tree
,      self
.OnTreeLeftDown
) 
 322         self
.nb 
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
) 
 324         # Set up a wxHtmlWindow on the Overview Notebook page 
 325         # we put it in a panel first because there seems to be a 
 326         # refresh bug of some sort (wxGTK) when it is directly in 
 329             self
.ovr 
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400)) 
 330             self
.nb
.AddPage(self
.ovr
, self
.overviewText
) 
 332         else:  # hopefully I can remove this hacky code soon, see bug #216861 
 333             panel 
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
) 
 334             self
.ovr 
= wxHtmlWindow(panel
, -1, size
=(400, 400)) 
 335             self
.nb
.AddPage(panel
, self
.overviewText
) 
 337             def OnOvrSize(evt
, ovr
=self
.ovr
): 
 338                 ovr
.SetSize(evt
.GetSize()) 
 340             EVT_SIZE(panel
, OnOvrSize
) 
 341             EVT_ERASE_BACKGROUND(panel
, EmptyHandler
) 
 344         self
.SetOverview(self
.overviewText
, overview
) 
 347         # Set up a TextCtrl on the Demo Code Notebook page 
 348         self
.txt 
= wxTextCtrl(self
.nb
, -1, 
 349                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 350         self
.nb
.AddPage(self
.txt
, "Demo Code") 
 353         # Set up a log on the View Log Notebook page 
 354         self
.log 
= wxTextCtrl(splitter2
, -1, 
 355                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 357         # Set the wxWindows log target to be this textctrl 
 358         #wxLog_SetActiveTarget(wxLogTextCtrl(self.log)) 
 360         # But instead of the above we want to show how to use our own wxLog class 
 361         wxLog_SetActiveTarget(MyLog(self
.log
)) 
 363         # for serious debugging 
 364         #wxLog_SetActiveTarget(wxLogStderr()) 
 365         #wxLog_SetTraceMask(wxTraceMessages) 
 370         # add the windows to the splitter and split it. 
 371         splitter2
.SplitHorizontally(self
.nb
, self
.log
) 
 372         splitter
.SplitVertically(self
.tree
, splitter2
) 
 374         splitter
.SetSashPosition(180, true
) 
 375         splitter
.SetMinimumPaneSize(20) 
 376         splitter2
.SetSashPosition(450, true
) 
 377         splitter2
.SetMinimumPaneSize(20) 
 381         # select initial items 
 382         self
.nb
.SetSelection(0) 
 383         self
.tree
.SelectItem(root
) 
 385         if len(sys
.argv
) == 2: 
 387                 selectedDemo 
= self
.treeMap
[sys
.argv
[1]] 
 391                 self
.tree
.SelectItem(selectedDemo
) 
 392                 self
.tree
.EnsureVisible(selectedDemo
) 
 395         wxLogMessage('window handle: %s' % self
.GetHandle()) 
 398     #--------------------------------------------- 
 399     def WriteText(self
, text
): 
 400         if text
[-1:] == '\n': 
 405     def write(self
, txt
): 
 408     #--------------------------------------------- 
 409     def OnItemExpanded(self
, event
): 
 410         item 
= event
.GetItem() 
 411         wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
)) 
 414     #--------------------------------------------- 
 415     def OnItemCollapsed(self
, event
): 
 416         item 
= event
.GetItem() 
 417         wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
)) 
 420     #--------------------------------------------- 
 421     def OnTreeLeftDown(self
, event
): 
 422         pt 
= event
.GetPosition(); 
 423         item
, flags 
= self
.tree
.HitTest(pt
) 
 424         if item 
== self
.tree
.GetSelection(): 
 425             self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
) 
 428     #--------------------------------------------- 
 429     def OnSelChanged(self
, event
): 
 433         item 
= event
.GetItem() 
 434         itemText 
= self
.tree
.GetItemText(item
) 
 435         self
.RunDemo(itemText
) 
 438     #--------------------------------------------- 
 439     def RunDemo(self
, itemText
): 
 441         if self
.nb
.GetPageCount() == 3: 
 442             if self
.nb
.GetSelection() == 2: 
 443                 self
.nb
.SetSelection(0) 
 444             self
.nb
.DeletePage(2) 
 446         if itemText 
== self
.overviewText
: 
 447             self
.GetDemoFile('Main.py') 
 448             self
.SetOverview(self
.overviewText
, overview
) 
 453             if os
.path
.exists(itemText 
+ '.py'): 
 455                 wxLogMessage("Running demo %s.py..." % itemText
) 
 457                     self
.GetDemoFile(itemText 
+ '.py') 
 458                     module 
= __import__(itemText
, globals()) 
 459                     self
.SetOverview(itemText 
+ " Overview", module
.overview
) 
 464                 # in case runTest is modal, make sure things look right... 
 468                 self
.window 
= module
.runTest(self
, self
.nb
, self
) ### 
 470                     self
.nb
.AddPage(self
.window
, 'Demo') 
 471                     self
.nb
.SetSelection(2) 
 472                     self
.nb
.Refresh()  # without this wxMac has troubles showing the just added page 
 481     #--------------------------------------------- 
 483     def GetDemoFile(self
, filename
): 
 486             self
.txt
.SetValue(open(filename
).read()) 
 488             self
.txt
.WriteText("Cannot open %s file." % filename
) 
 490         self
.txt
.SetInsertionPoint(0) 
 491         self
.txt
.ShowPosition(0) 
 493     #--------------------------------------------- 
 494     def SetOverview(self
, name
, text
): 
 495         self
.curOverview 
= text
 
 497         if lead 
!= '<html>' and lead 
!= '<HTML>': 
 498             text 
= string
.join(string
.split(text
, '\n'), '<br>') 
 499         self
.ovr
.SetPage(text
) 
 500         self
.nb
.SetPageText(0, name
) 
 502     #--------------------------------------------- 
 504     def OnFileExit(self
, *event
): 
 508     def OnHelpAbout(self
, event
): 
 509         from About 
import MyAboutBox
 
 510         about 
= MyAboutBox(self
) 
 515     #--------------------------------------------- 
 516     def OnCloseWindow(self
, event
): 
 520         if hasattr(self
, "tbicon"): 
 525     #--------------------------------------------- 
 526     def OnIdle(self
, event
): 
 528             self
.otherWin
.Raise() 
 529             self
.window 
= self
.otherWin
 
 537     #--------------------------------------------- 
 540             showTipText 
= open(opj("data/showTips")).read() 
 541             showTip
, index 
= eval(showTipText
) 
 543             showTip
, index 
= (1, 0) 
 545             tp 
= wxCreateFileTipProvider(opj("data/tips.txt"), index
) 
 546             showTip 
= wxShowTip(self
, tp
) 
 547             index 
= tp
.GetCurrentTip() 
 548             open(opj("data/showTips"), "w").write(str( (showTip
, index
) )) 
 551     #--------------------------------------------- 
 552     def OnDemoMenu(self
, event
): 
 554             selectedDemo 
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())] 
 558             self
.tree
.SelectItem(selectedDemo
) 
 559             self
.tree
.EnsureVisible(selectedDemo
) 
 562     #--------------------------------------------- 
 563     def OnTaskBarActivate(self
, evt
): 
 564         if self
.IsIconized(): 
 566         if not self
.IsShown(): 
 570     #--------------------------------------------- 
 572     TBMENU_RESTORE 
= 1000 
 575     def OnTaskBarMenu(self
, evt
): 
 577         menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo") 
 578         menu
.Append(self
.TBMENU_CLOSE
,   "Close") 
 579         self
.tbicon
.PopupMenu(menu
) 
 582     #--------------------------------------------- 
 583     def OnTaskBarClose(self
, evt
): 
 586         # because of the way wxTaskBarIcon.PopupMenu is implemented we have to 
 587         # prod the main idle handler a bit to get the window to actually close 
 588         wxGetApp().ProcessIdle() 
 591     #--------------------------------------------- 
 592     def OnIconfiy(self
, evt
): 
 593         wxLogMessage("OnIconfiy") 
 596     #--------------------------------------------- 
 597     def OnMaximize(self
, evt
): 
 598         wxLogMessage("OnMaximize") 
 604 #--------------------------------------------------------------------------- 
 605 #--------------------------------------------------------------------------- 
 607 class MySplashScreen(wxSplashScreen
): 
 609         bmp 
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap() 
 610         wxSplashScreen
.__init
__(self
, bmp
, 
 611                                 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
, 
 613                                 style 
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
) 
 614         EVT_CLOSE(self
, self
.OnClose
) 
 616     def OnClose(self
, evt
): 
 617         frame 
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)") 
 619         evt
.Skip()  # Make sure the default handler runs too... 
 625         Create and show the splash screen.  It will then create and show 
 626         the main frame when it is time to do so. 
 628         wxInitAllImageHandlers() 
 629         splash 
= MySplashScreen() 
 635 #--------------------------------------------------------------------------- 
 639         demoPath 
= os
.path
.dirname(__file__
) 
 643     app 
= MyApp(wxPlatform 
== "__WXMAC__") 
 647 #--------------------------------------------------------------------------- 
 651 overview 
= """<html><body> 
 654  Python is an interpreted, interactive, object-oriented programming 
 655  language often compared to Tcl, Perl, Scheme, or Java. 
 657  <p> Python combines remarkable power with very clear syntax. It has 
 658  modules, classes, exceptions, very high level dynamic data types, and 
 659  dynamic typing.  There are interfaces to many system calls and 
 660  libraries, and new built-in modules are easily written in C or 
 661  C++. Python is also usable as an extension language for applications 
 662  that need a programmable interface.  <p> 
 666  wxWindows is a free C++ framework designed to make cross-platform 
 667  programming child's play. Well, almost. wxWindows 2 supports Windows 
 668  3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version 
 669  underway. Other ports are under consideration.  <p> 
 671  wxWindows is a set of libraries that allows C++ applications to 
 672  compile and run on several different types of computers, with minimal 
 673  source code changes.  There is one library per supported GUI (such as 
 674  Motif, or Windows). As well as providing a common API (Application 
 675  Programming Interface) for GUI functionality, it provides 
 676  functionality for accessing some commonly-used operating system 
 677  facilities, such as copying or deleting files. wxWindows is a 
 678  'framework' in the sense that it provides a lot of built-in 
 679  functionality, which the application can use or replace as required, 
 680  thus saving a great deal of coding effort. Basic data structures such 
 681  as strings, linked lists and hash tables are also supported. 
 686  wxPython is a Python extension module that encapsulates the wxWindows 
 687  GUI classes. Currently it is only available for the Win32 and GTK 
 688  ports of wxWindows, but as soon as the other ports are brought up to 
 689  the same level as Win32 and GTK, it should be fairly trivial to 
 690  enable wxPython to be used with the new GUI. 
 694  The wxPython extension module attempts to mirror the class heiarchy 
 695  of wxWindows as closely as possible. This means that there is a 
 696  wxFrame class in wxPython that looks, smells, tastes and acts almost 
 697  the same as the wxFrame class in the C++ version. Unfortunately, 
 698  because of differences in the languages, wxPython doesn't match 
 699  wxWindows exactly, but the differences should be easy to absorb 
 700  because they are natural to Python. For example, some methods that 
 701  return multiple values via argument pointers in C++ will return a 
 702  tuple of values in Python. 
 706  There is still much to be done for wxPython, many classes still need 
 707  to be mirrored. Also, wxWindows is still somewhat of a moving target 
 708  so it is a bit of an effort just keeping wxPython up to date. On the 
 709  other hand, there are enough of the core classes completed that 
 710  useful applications can be written. 
 714  wxPython is close enough to the C++ version that the majority of 
 715  the wxPython documentation is actually just notes attached to the C++ 
 716  documents that describe the places where wxPython is different. There 
 717  is also a series of sample programs included, and a series of 
 718  documentation pages that assist the programmer in getting started 
 724 #---------------------------------------------------------------------------- 
 725 #---------------------------------------------------------------------------- 
 727 if __name__ 
== '__main__': 
 730 #----------------------------------------------------------------------------