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', [ 
  35     # managed windows == things with a caption you can close 
  36     ('Base Frames and Dialogs', [ 
  48         'wxFindReplaceDialog', 
  54         'wxSingleChoiceDialog', 
  58     # dialogs form libraries 
  62         'wxMultipleChoiceDialog', 
  63         'wxScrolledMessageDialog', 
  67     ('Core Windows/Controls', [ 
  98     # controls coming from other librairies 
  99     ('More Windows/Controls', [ 
 106         'PyCrustWithFilling', 
 111         'wxDynamicSashWindow', 
 117         'wxMimeTypesManager', 
 119         'wxStyledTextCtrl_1', 
 120         'wxStyledTextCtrl_2', 
 124     # How to lay out the controls in a frame/dialog 
 130         'wxLayoutConstraints', 
 135     ('Process and Events', [ 
 145     ('Clipboard and DnD', [ 
 173     # need libs not coming with the demo 
 174     ('Objects using an external library', [ 
 175         'ActiveXWrapper_Acrobat', 
 181     # pyTree, hangman, ... in the samples dir 
 182     ('Check out the samples dir too', [ 
 189 #--------------------------------------------------------------------------- 
 191 class MyLog(wxPyLog
): 
 192     def __init__(self
, textCtrl
, logTime
=0): 
 193         wxPyLog
.__init
__(self
) 
 195         self
.logTime 
= logTime
 
 197     def DoLogString(self
, message
, timeStamp
): 
 199             message 
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
 
 201         self
.tc
.AppendText(message 
+ '\n') 
 204 #--------------------------------------------------------------------------- 
 207     """Convert paths to the platform-specific separator""" 
 208     return apply(os
.path
.join
, tuple(string
.split(path
, '/'))) 
 211 #--------------------------------------------------------------------------- 
 213 class wxPythonDemo(wxFrame
): 
 214     overviewText 
= "wxPython Overview" 
 216     def __init__(self
, parent
, id, title
): 
 217         wxFrame
.__init
__(self
, parent
, -1, title
, size 
= (800, 600), 
 218                          style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
) 
 220         self
.cwd 
= os
.getcwd() 
 221         self
.curOverview 
= "" 
 223         icon 
= images
.getMondrianIcon() 
 226         if wxPlatform 
== '__WXMSW__': 
 227             # setup a taskbar icon, and catch some events from it 
 228             self
.tbicon 
= wxTaskBarIcon() 
 229             self
.tbicon
.SetIcon(icon
, "wxPython Demo") 
 230             EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
) 
 231             EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
) 
 232             EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
) 
 233             EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
) 
 238         EVT_IDLE(self
, self
.OnIdle
) 
 239         EVT_CLOSE(self
, self
.OnCloseWindow
) 
 240         EVT_ICONIZE(self
, self
.OnIconfiy
) 
 241         EVT_MAXIMIZE(self
, self
.OnMaximize
) 
 244         self
.CreateStatusBar(1, wxST_SIZEGRIP
) 
 246         splitter 
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
) 
 247         splitter2 
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
) 
 249         def EmptyHandler(evt
): pass 
 250         EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
) 
 251         EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
) 
 253         # Prevent TreeCtrl from displaying all items after destruction when true 
 257         self
.mainmenu 
= wxMenuBar() 
 260         menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!') 
 261         EVT_MENU(self
, exitID
, self
.OnFileExit
) 
 262         self
.mainmenu
.Append(menu
, '&File') 
 266         for item 
in _treeList
: 
 268             for childItem 
in item
[1]: 
 270                 submenu
.Append(mID
, childItem
) 
 271                 EVT_MENU(self
, mID
, self
.OnDemoMenu
) 
 272             menu
.AppendMenu(wxNewId(), item
[0], submenu
) 
 273         self
.mainmenu
.Append(menu
, '&Demo') 
 279         menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!') 
 280         EVT_MENU(self
, helpID
, self
.OnHelpAbout
) 
 281         self
.mainmenu
.Append(menu
, '&Help') 
 282         self
.SetMenuBar(self
.mainmenu
) 
 284         # set the menu accellerator table... 
 285         aTable 
= wxAcceleratorTable([(wxACCEL_ALT
,  ord('X'), exitID
), 
 286                                      (wxACCEL_CTRL
, ord('H'), helpID
)]) 
 287         self
.SetAcceleratorTable(aTable
) 
 293         self
.tree 
= wxTreeCtrl(splitter
, tID
, 
 294                                style
=wxTR_HAS_BUTTONS |
 
 296                                wxTR_HAS_VARIABLE_ROW_HEIGHT
) 
 298         #self.tree.SetBackgroundColour(wxNamedColour("Pink")) 
 299         root 
= self
.tree
.AddRoot("wxPython Overview") 
 301         for item 
in _treeList
: 
 302             child 
= self
.tree
.AppendItem(root
, item
[0]) 
 303             if not firstChild
: firstChild 
= child
 
 304             for childItem 
in item
[1]: 
 305                 theDemo 
= self
.tree
.AppendItem(child
, childItem
) 
 306                 self
.treeMap
[childItem
] = theDemo
 
 308         self
.tree
.Expand(root
) 
 309         self
.tree
.Expand(firstChild
) 
 310         EVT_TREE_ITEM_EXPANDED   (self
.tree
, tID
, self
.OnItemExpanded
) 
 311         EVT_TREE_ITEM_COLLAPSED  (self
.tree
, tID
, self
.OnItemCollapsed
) 
 312         EVT_TREE_SEL_CHANGED     (self
.tree
, tID
, self
.OnSelChanged
) 
 313         EVT_LEFT_DOWN            (self
.tree
,      self
.OnTreeLeftDown
) 
 316         self
.nb 
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
) 
 318         # Set up a wxHtmlWindow on the Overview Notebook page 
 319         # we put it in a panel first because there seems to be a 
 320         # refresh bug of some sort (wxGTK) when it is directly in 
 323             self
.ovr 
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400)) 
 324             self
.nb
.AddPage(self
.ovr
, self
.overviewText
) 
 326         else:  # hopefully I can remove this hacky code soon, see bug #216861 
 327             panel 
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
) 
 328             self
.ovr 
= wxHtmlWindow(panel
, -1, size
=(400, 400)) 
 329             self
.nb
.AddPage(panel
, self
.overviewText
) 
 331             def OnOvrSize(evt
, ovr
=self
.ovr
): 
 332                 ovr
.SetSize(evt
.GetSize()) 
 334             EVT_SIZE(panel
, OnOvrSize
) 
 335             EVT_ERASE_BACKGROUND(panel
, EmptyHandler
) 
 338         self
.SetOverview(self
.overviewText
, overview
) 
 341         # Set up a TextCtrl on the Demo Code Notebook page 
 342         self
.txt 
= wxTextCtrl(self
.nb
, -1, 
 343                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 344         self
.nb
.AddPage(self
.txt
, "Demo Code") 
 347         # Set up a log on the View Log Notebook page 
 348         self
.log 
= wxTextCtrl(splitter2
, -1, 
 349                               style 
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
) 
 351         # Set the wxWindows log target to be this textctrl 
 352         #wxLog_SetActiveTarget(wxLogTextCtrl(self.log)) 
 354         # But instead of the above we want to show how to use our own wxLog class 
 355         wxLog_SetActiveTarget(MyLog(self
.log
)) 
 361         # add the windows to the splitter and split it. 
 362         splitter2
.SplitHorizontally(self
.nb
, self
.log
) 
 363         splitter
.SplitVertically(self
.tree
, splitter2
) 
 365         splitter
.SetSashPosition(180, true
) 
 366         splitter
.SetMinimumPaneSize(20) 
 367         splitter2
.SetSashPosition(450, true
) 
 368         splitter2
.SetMinimumPaneSize(20) 
 372         # select initial items 
 373         self
.nb
.SetSelection(0) 
 374         self
.tree
.SelectItem(root
) 
 376         if len(sys
.argv
) == 2: 
 378                 selectedDemo 
= self
.treeMap
[sys
.argv
[1]] 
 382                 self
.tree
.SelectItem(selectedDemo
) 
 383                 self
.tree
.EnsureVisible(selectedDemo
) 
 386         wxLogMessage('window handle: %s' % self
.GetHandle()) 
 389     #--------------------------------------------- 
 390     def WriteText(self
, text
): 
 391         if text
[-1:] == '\n': 
 396     def write(self
, txt
): 
 399     #--------------------------------------------- 
 400     def OnItemExpanded(self
, event
): 
 401         item 
= event
.GetItem() 
 402         wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
)) 
 405     #--------------------------------------------- 
 406     def OnItemCollapsed(self
, event
): 
 407         item 
= event
.GetItem() 
 408         wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
)) 
 411     #--------------------------------------------- 
 412     def OnTreeLeftDown(self
, event
): 
 413         pt 
= event
.GetPosition(); 
 414         item
, flags 
= self
.tree
.HitTest(pt
) 
 415         if item 
== self
.tree
.GetSelection(): 
 416             self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
) 
 419     #--------------------------------------------- 
 420     def OnSelChanged(self
, event
): 
 424         item 
= event
.GetItem() 
 425         itemText 
= self
.tree
.GetItemText(item
) 
 426         self
.RunDemo(itemText
) 
 429     #--------------------------------------------- 
 430     def RunDemo(self
, itemText
): 
 432         if self
.nb
.GetPageCount() == 3: 
 433             if self
.nb
.GetSelection() == 2: 
 434                 self
.nb
.SetSelection(0) 
 435             self
.nb
.DeletePage(2) 
 437         if itemText 
== self
.overviewText
: 
 438             self
.GetDemoFile('Main.py') 
 439             self
.SetOverview(self
.overviewText
, overview
) 
 444             if os
.path
.exists(itemText 
+ '.py'): 
 446                 wxLogMessage("Running demo %s.py..." % itemText
) 
 448                     self
.GetDemoFile(itemText 
+ '.py') 
 449                     module 
= __import__(itemText
, globals()) 
 450                     self
.SetOverview(itemText 
+ " Overview", module
.overview
) 
 455                 # in case runTest is modal, make sure things look right... 
 459                 self
.window 
= module
.runTest(self
, self
.nb
, self
) ### 
 461                     self
.nb
.AddPage(self
.window
, 'Demo') 
 462                     self
.nb
.SetSelection(2) 
 463                     self
.nb
.Refresh()  # without this wxMac has troubles showing the just added page 
 472     #--------------------------------------------- 
 474     def GetDemoFile(self
, filename
): 
 477             self
.txt
.SetValue(open(filename
).read()) 
 479             self
.txt
.WriteText("Cannot open %s file." % filename
) 
 481         self
.txt
.SetInsertionPoint(0) 
 482         self
.txt
.ShowPosition(0) 
 484     #--------------------------------------------- 
 485     def SetOverview(self
, name
, text
): 
 486         self
.curOverview 
= text
 
 488         if lead 
!= '<html>' and lead 
!= '<HTML>': 
 489             text 
= string
.join(string
.split(text
, '\n'), '<br>') 
 490         self
.ovr
.SetPage(text
) 
 491         self
.nb
.SetPageText(0, name
) 
 493     #--------------------------------------------- 
 495     def OnFileExit(self
, *event
): 
 499     def OnHelpAbout(self
, event
): 
 500         from About 
import MyAboutBox
 
 501         about 
= MyAboutBox(self
) 
 506     #--------------------------------------------- 
 507     def OnCloseWindow(self
, event
): 
 511         if hasattr(self
, "tbicon"): 
 516     #--------------------------------------------- 
 517     def OnIdle(self
, event
): 
 519             self
.otherWin
.Raise() 
 520             self
.window 
= self
.otherWin
 
 528     #--------------------------------------------- 
 531             showTipText 
= open(opj("data/showTips")).read() 
 532             showTip
, index 
= eval(showTipText
) 
 534             showTip
, index 
= (1, 0) 
 536             tp 
= wxCreateFileTipProvider(opj("data/tips.txt"), index
) 
 537             showTip 
= wxShowTip(self
, tp
) 
 538             index 
= tp
.GetCurrentTip() 
 539             open(opj("data/showTips"), "w").write(str( (showTip
, index
) )) 
 542     #--------------------------------------------- 
 543     def OnDemoMenu(self
, event
): 
 545             selectedDemo 
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())] 
 549             self
.tree
.SelectItem(selectedDemo
) 
 550             self
.tree
.EnsureVisible(selectedDemo
) 
 553     #--------------------------------------------- 
 554     def OnTaskBarActivate(self
, evt
): 
 555         if self
.IsIconized(): 
 557         if not self
.IsShown(): 
 561     #--------------------------------------------- 
 563     TBMENU_RESTORE 
= 1000 
 566     def OnTaskBarMenu(self
, evt
): 
 568         menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo") 
 569         menu
.Append(self
.TBMENU_CLOSE
,   "Close") 
 570         self
.tbicon
.PopupMenu(menu
) 
 573     #--------------------------------------------- 
 574     def OnTaskBarClose(self
, evt
): 
 577         # because of the way wxTaskBarIcon.PopupMenu is implemented we have to 
 578         # prod the main idle handler a bit to get the window to actually close 
 579         wxGetApp().ProcessIdle() 
 582     #--------------------------------------------- 
 583     def OnIconfiy(self
, evt
): 
 584         wxLogMessage("OnIconfiy") 
 587     #--------------------------------------------- 
 588     def OnMaximize(self
, evt
): 
 589         wxLogMessage("OnMaximize") 
 595 #--------------------------------------------------------------------------- 
 596 #--------------------------------------------------------------------------- 
 598 class MySplashScreen(wxSplashScreen
): 
 600         bmp 
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap() 
 601         wxSplashScreen
.__init
__(self
, bmp
, 
 602                                 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
, 
 604                                 style 
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
) 
 605         EVT_CLOSE(self
, self
.OnClose
) 
 607     def OnClose(self
, evt
): 
 608         frame 
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)") 
 610         evt
.Skip()  # Make sure the default handler runs too... 
 616         Create and show the splash screen.  It will then create and show 
 617         the main frame when it is time to do so. 
 619         wxInitAllImageHandlers() 
 620         splash 
= MySplashScreen() 
 626 #--------------------------------------------------------------------------- 
 630         demoPath 
= os
.path
.dirname(__file__
) 
 634     app 
= MyApp(wxPlatform 
== "__WXMAC__") 
 638 #--------------------------------------------------------------------------- 
 642 overview 
= """<html><body> 
 645  Python is an interpreted, interactive, object-oriented programming 
 646  language often compared to Tcl, Perl, Scheme, or Java. 
 648  <p> Python combines remarkable power with very clear syntax. It has 
 649  modules, classes, exceptions, very high level dynamic data types, and 
 650  dynamic typing.  There are interfaces to many system calls and 
 651  libraries, and new built-in modules are easily written in C or 
 652  C++. Python is also usable as an extension language for applications 
 653  that need a programmable interface.  <p> 
 657  wxWindows is a free C++ framework designed to make cross-platform 
 658  programming child's play. Well, almost. wxWindows 2 supports Windows 
 659  3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version 
 660  underway. Other ports are under consideration.  <p> 
 662  wxWindows is a set of libraries that allows C++ applications to 
 663  compile and run on several different types of computers, with minimal 
 664  source code changes.  There is one library per supported GUI (such as 
 665  Motif, or Windows). As well as providing a common API (Application 
 666  Programming Interface) for GUI functionality, it provides 
 667  functionality for accessing some commonly-used operating system 
 668  facilities, such as copying or deleting files. wxWindows is a 
 669  'framework' in the sense that it provides a lot of built-in 
 670  functionality, which the application can use or replace as required, 
 671  thus saving a great deal of coding effort. Basic data structures such 
 672  as strings, linked lists and hash tables are also supported. 
 677  wxPython is a Python extension module that encapsulates the wxWindows 
 678  GUI classes. Currently it is only available for the Win32 and GTK 
 679  ports of wxWindows, but as soon as the other ports are brought up to 
 680  the same level as Win32 and GTK, it should be fairly trivial to 
 681  enable wxPython to be used with the new GUI. 
 685  The wxPython extension module attempts to mirror the class heiarchy 
 686  of wxWindows as closely as possible. This means that there is a 
 687  wxFrame class in wxPython that looks, smells, tastes and acts almost 
 688  the same as the wxFrame class in the C++ version. Unfortunately, 
 689  because of differences in the languages, wxPython doesn't match 
 690  wxWindows exactly, but the differences should be easy to absorb 
 691  because they are natural to Python. For example, some methods that 
 692  return multiple values via argument pointers in C++ will return a 
 693  tuple of values in Python. 
 697  There is still much to be done for wxPython, many classes still need 
 698  to be mirrored. Also, wxWindows is still somewhat of a moving target 
 699  so it is a bit of an effort just keeping wxPython up to date. On the 
 700  other hand, there are enough of the core classes completed that 
 701  useful applications can be written. 
 705  wxPython is close enough to the C++ version that the majority of 
 706  the wxPython documentation is actually just notes attached to the C++ 
 707  documents that describe the places where wxPython is different. There 
 708  is also a series of sample programs included, and a series of 
 709  documentation pages that assist the programmer in getting started 
 715 #---------------------------------------------------------------------------- 
 716 #---------------------------------------------------------------------------- 
 718 if __name__ 
== '__main__': 
 721 #----------------------------------------------------------------------------