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',
25 ## 'wxImageFromStream',
31 ## ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
32 ## 'wxGrid', 'wxSashWindow',
33 ## 'wxScrolledWindow', 'wxSplitterWindow',
34 ## 'wxStatusBar', 'wxNotebook',
36 ## 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
38 ## 'wxDynamicSashWindow',
41 ## ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
42 ## 'wxSingleChoiceDialog', 'wxTextEntryDialog',
43 ## 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
44 ## 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
47 ## ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
48 ## 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'VirtualListCtrl',
50 ## 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
51 ## 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
52 ## 'wxCalendarCtrl', 'wxToggleButton',
53 ## 'wxEditableListBox', 'wxLEDNumberCtrl',
56 ## ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource',
60 ## ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
62 ## 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
63 ## 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
64 ## 'PythonEvents', 'Threads',
65 ## 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
66 ## 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
67 ## 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
68 ## 'ContextHelp', 'SplitTree', 'Unicode', 'wxFileHistory',
71 ## ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
72 ## 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
73 ## 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
74 ## 'FileBrowseButton', 'GenericButtons', 'wxEditor',
75 ## 'ColourSelect', 'ImageBrowser',
76 ## 'infoframe', 'ColourDB', 'PyCrust', 'PyCrustWithFilling',
81 ## ('Cool Contribs', ['pyTree', 'hangman',
91 ('New since last release', [
99 # managed windows == things with a caption you can close
100 ('Base Frames and Dialogs', [
112 'wxFindReplaceDialog',
118 'wxSingleChoiceDialog',
122 # dialogs form libraries
126 'wxMultipleChoiceDialog',
127 'wxScrolledMessageDialog',
131 ('Core Windows/Controls', [
163 # controls coming from other librairies
164 ('More Windows/Controls', [
171 'PyCrustWithFilling',
176 'wxDynamicSashWindow',
182 'wxMimeTypesManager',
184 'wxStyledTextCtrl_1',
185 'wxStyledTextCtrl_2',
189 # How to lay out the controls in a frame/dialog
195 'wxLayoutConstraints',
200 ('Process and Events', [
210 ('Clipboard and DnD', [
238 # need libs not coming with the demo
239 ('Objects using an external library', [
240 'ActiveXWrapper_Acrobat',
247 # pyTree, hangman, ... in the samples dir
248 ('Check out the samples dir too', [
255 #---------------------------------------------------------------------------
257 class MyLog(wxPyLog
):
258 def __init__(self
, textCtrl
, logTime
=0):
259 wxPyLog
.__init
__(self
)
261 self
.logTime
= logTime
263 def DoLogString(self
, message
, timeStamp
):
265 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
267 self
.tc
.AppendText(message
+ '\n')
270 #---------------------------------------------------------------------------
273 """Convert paths to the platform-specific separator"""
274 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
277 #---------------------------------------------------------------------------
279 class wxPythonDemo(wxFrame
):
280 overviewText
= "wxPython Overview"
282 def __init__(self
, parent
, id, title
):
283 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
284 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
286 self
.cwd
= os
.getcwd()
287 self
.curOverview
= ""
289 icon
= images
.getMondrianIcon()
292 if wxPlatform
== '__WXMSW__':
293 # setup a taskbar icon, and catch some events from it
294 self
.tbicon
= wxTaskBarIcon()
295 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
296 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
297 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
298 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
299 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
304 EVT_IDLE(self
, self
.OnIdle
)
305 EVT_CLOSE(self
, self
.OnCloseWindow
)
306 EVT_ICONIZE(self
, self
.OnIconfiy
)
307 EVT_MAXIMIZE(self
, self
.OnMaximize
)
310 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
312 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
313 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
315 def EmptyHandler(evt
): pass
316 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
317 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
319 # Prevent TreeCtrl from displaying all items after destruction when true
323 self
.mainmenu
= wxMenuBar()
326 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
327 EVT_MENU(self
, exitID
, self
.OnFileExit
)
328 self
.mainmenu
.Append(menu
, '&File')
332 for item
in _treeList
:
334 for childItem
in item
[1]:
336 submenu
.Append(mID
, childItem
)
337 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
338 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
339 self
.mainmenu
.Append(menu
, '&Demo')
345 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
346 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
347 self
.mainmenu
.Append(menu
, '&Help')
348 self
.SetMenuBar(self
.mainmenu
)
350 # set the menu accellerator table...
351 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
352 (wxACCEL_CTRL
, ord('H'), helpID
)])
353 self
.SetAcceleratorTable(aTable
)
359 self
.tree
= wxTreeCtrl(splitter
, tID
,
360 style
=wxTR_HAS_BUTTONS |
362 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
364 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
365 root
= self
.tree
.AddRoot("wxPython Overview")
367 for item
in _treeList
:
368 child
= self
.tree
.AppendItem(root
, item
[0])
369 if not firstChild
: firstChild
= child
370 for childItem
in item
[1]:
371 theDemo
= self
.tree
.AppendItem(child
, childItem
)
372 self
.treeMap
[childItem
] = theDemo
374 self
.tree
.Expand(root
)
375 self
.tree
.Expand(firstChild
)
376 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
377 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
378 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
379 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
382 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
384 # Set up a wxHtmlWindow on the Overview Notebook page
385 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
386 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
388 self
.SetOverview(self
.overviewText
, overview
)
391 # Set up a TextCtrl on the Demo Code Notebook page
392 self
.txt
= wxTextCtrl(self
.nb
, -1,
393 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
394 self
.nb
.AddPage(self
.txt
, "Demo Code")
397 # Set up a log on the View Log Notebook page
398 self
.log
= wxTextCtrl(splitter2
, -1,
399 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
401 # Set the wxWindows log target to be this textctrl
402 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
404 # But instead of the above we want to show how to use our own wxLog class
405 wxLog_SetActiveTarget(MyLog(self
.log
))
411 # add the windows to the splitter and split it.
412 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
413 splitter
.SplitVertically(self
.tree
, splitter2
)
415 splitter
.SetSashPosition(180, true
)
416 splitter
.SetMinimumPaneSize(20)
417 splitter2
.SetSashPosition(450, true
)
418 splitter2
.SetMinimumPaneSize(20)
422 # select initial items
423 self
.nb
.SetSelection(0)
424 self
.tree
.SelectItem(root
)
426 if len(sys
.argv
) == 2:
428 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
432 self
.tree
.SelectItem(selectedDemo
)
433 self
.tree
.EnsureVisible(selectedDemo
)
436 wxLogMessage('window handle: %s' % self
.GetHandle())
439 #---------------------------------------------
440 def WriteText(self
, text
):
441 if text
[-1:] == '\n':
446 def write(self
, txt
):
449 #---------------------------------------------
450 def OnItemExpanded(self
, event
):
451 item
= event
.GetItem()
452 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
455 #---------------------------------------------
456 def OnItemCollapsed(self
, event
):
457 item
= event
.GetItem()
458 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
461 #---------------------------------------------
462 def OnTreeLeftDown(self
, event
):
463 pt
= event
.GetPosition();
464 item
, flags
= self
.tree
.HitTest(pt
)
465 if item
== self
.tree
.GetSelection():
466 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
469 #---------------------------------------------
470 def OnSelChanged(self
, event
):
474 item
= event
.GetItem()
475 itemText
= self
.tree
.GetItemText(item
)
476 self
.RunDemo(itemText
)
479 #---------------------------------------------
480 def RunDemo(self
, itemText
):
482 if self
.nb
.GetPageCount() == 3:
483 if self
.nb
.GetSelection() == 2:
484 self
.nb
.SetSelection(0)
485 self
.nb
.DeletePage(2)
487 if itemText
== self
.overviewText
:
488 self
.GetDemoFile('Main.py')
489 self
.SetOverview(self
.overviewText
, overview
)
494 if os
.path
.exists(itemText
+ '.py'):
496 wxLogMessage("Running demo %s.py..." % itemText
)
498 self
.GetDemoFile(itemText
+ '.py')
499 module
= __import__(itemText
, globals())
500 self
.SetOverview(itemText
+ " Overview", module
.overview
)
504 # in case runTest is modal, make sure things look right...
508 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
510 self
.nb
.AddPage(self
.window
, 'Demo')
512 self
.nb
.SetSelection(2)
521 #---------------------------------------------
523 def GetDemoFile(self
, filename
):
526 self
.txt
.SetValue(open(filename
).read())
528 self
.txt
.WriteText("Cannot open %s file." % filename
)
530 self
.txt
.SetInsertionPoint(0)
531 self
.txt
.ShowPosition(0)
533 #---------------------------------------------
534 def SetOverview(self
, name
, text
):
535 self
.curOverview
= text
537 if lead
!= '<html>' and lead
!= '<HTML>':
538 text
= string
.join(string
.split(text
, '\n'), '<br>')
539 self
.ovr
.SetPage(text
)
540 self
.nb
.SetPageText(0, name
)
542 #---------------------------------------------
544 def OnFileExit(self
, *event
):
548 def OnHelpAbout(self
, event
):
549 from About
import MyAboutBox
550 about
= MyAboutBox(self
)
555 #---------------------------------------------
556 def OnCloseWindow(self
, event
):
560 if hasattr(self
, "tbicon"):
565 #---------------------------------------------
566 def OnIdle(self
, event
):
568 self
.otherWin
.Raise()
569 self
.window
= self
.otherWin
577 #---------------------------------------------
580 showTipText
= open(opj("data/showTips")).read()
581 showTip
, index
= eval(showTipText
)
583 showTip
, index
= (1, 0)
585 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
586 showTip
= wxShowTip(self
, tp
)
587 index
= tp
.GetCurrentTip()
588 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
591 #---------------------------------------------
592 def OnDemoMenu(self
, event
):
594 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
598 self
.tree
.SelectItem(selectedDemo
)
599 self
.tree
.EnsureVisible(selectedDemo
)
602 #---------------------------------------------
603 def OnTaskBarActivate(self
, evt
):
604 if self
.IsIconized():
606 if not self
.IsShown():
610 #---------------------------------------------
612 TBMENU_RESTORE
= 1000
615 def OnTaskBarMenu(self
, evt
):
617 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
618 menu
.Append(self
.TBMENU_CLOSE
, "Close")
619 self
.tbicon
.PopupMenu(menu
)
622 #---------------------------------------------
623 def OnTaskBarClose(self
, evt
):
626 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
627 # prod the main idle handler a bit to get the window to actually close
628 wxGetApp().ProcessIdle()
631 #---------------------------------------------
632 def OnIconfiy(self
, evt
):
633 wxLogMessage("OnIconfiy")
636 #---------------------------------------------
637 def OnMaximize(self
, evt
):
638 wxLogMessage("OnMaximize")
644 #---------------------------------------------------------------------------
645 #---------------------------------------------------------------------------
647 class MySplashScreen(wxSplashScreen
):
649 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
650 wxSplashScreen
.__init
__(self
, bmp
,
651 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
653 EVT_CLOSE(self
, self
.OnClose
)
655 def OnClose(self
, evt
):
656 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
658 evt
.Skip() # Make sure the default handler runs too...
664 Create and show the splash screen. It will then create and show
665 the main frame when it is time to do so.
667 wxInitAllImageHandlers()
668 splash
= MySplashScreen()
674 #---------------------------------------------------------------------------
678 demoPath
= os
.path
.dirname(__file__
)
686 #---------------------------------------------------------------------------
690 overview
= """<html><body>
693 Python is an interpreted, interactive, object-oriented programming
694 language often compared to Tcl, Perl, Scheme, or Java.
696 <p> Python combines remarkable power with very clear syntax. It has
697 modules, classes, exceptions, very high level dynamic data types, and
698 dynamic typing. There are interfaces to many system calls and
699 libraries, and new built-in modules are easily written in C or
700 C++. Python is also usable as an extension language for applications
701 that need a programmable interface. <p>
705 wxWindows is a free C++ framework designed to make cross-platform
706 programming child's play. Well, almost. wxWindows 2 supports Windows
707 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
708 underway. Other ports are under consideration. <p>
710 wxWindows is a set of libraries that allows C++ applications to
711 compile and run on several different types of computers, with minimal
712 source code changes. There is one library per supported GUI (such as
713 Motif, or Windows). As well as providing a common API (Application
714 Programming Interface) for GUI functionality, it provides
715 functionality for accessing some commonly-used operating system
716 facilities, such as copying or deleting files. wxWindows is a
717 'framework' in the sense that it provides a lot of built-in
718 functionality, which the application can use or replace as required,
719 thus saving a great deal of coding effort. Basic data structures such
720 as strings, linked lists and hash tables are also supported.
725 wxPython is a Python extension module that encapsulates the wxWindows
726 GUI classes. Currently it is only available for the Win32 and GTK
727 ports of wxWindows, but as soon as the other ports are brought up to
728 the same level as Win32 and GTK, it should be fairly trivial to
729 enable wxPython to be used with the new GUI.
733 The wxPython extension module attempts to mirror the class heiarchy
734 of wxWindows as closely as possible. This means that there is a
735 wxFrame class in wxPython that looks, smells, tastes and acts almost
736 the same as the wxFrame class in the C++ version. Unfortunately,
737 because of differences in the languages, wxPython doesn't match
738 wxWindows exactly, but the differences should be easy to absorb
739 because they are natural to Python. For example, some methods that
740 return multiple values via argument pointers in C++ will return a
741 tuple of values in Python.
745 There is still much to be done for wxPython, many classes still need
746 to be mirrored. Also, wxWindows is still somewhat of a moving target
747 so it is a bit of an effort just keeping wxPython up to date. On the
748 other hand, there are enough of the core classes completed that
749 useful applications can be written.
753 wxPython is close enough to the C++ version that the majority of
754 the wxPython documentation is actually just notes attached to the C++
755 documents that describe the places where wxPython is different. There
756 is also a series of sample programs included, and a series of
757 documentation pages that assist the programmer in getting started
763 #----------------------------------------------------------------------------
764 #----------------------------------------------------------------------------
766 if __name__
== '__main__':
769 #----------------------------------------------------------------------------