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',
28 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
29 'wxGrid', 'wxSashWindow',
30 'wxScrolledWindow', 'wxSplitterWindow',
31 'wxStatusBar', 'wxNotebook',
33 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
35 'wxDynamicSashWindow',
38 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
39 'wxSingleChoiceDialog', 'wxTextEntryDialog',
40 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
41 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
44 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
45 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'VirtualListCtrl',
47 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
48 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
49 'wxCalendarCtrl', 'wxToggleButton',
50 'wxEditableListBox', 'wxLEDNumberCtrl',
53 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
55 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
57 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
58 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
59 'PythonEvents', 'Threads',
60 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
61 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
62 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
63 'ContextHelp', 'SplitTree',
66 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
67 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
68 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
69 'FileBrowseButton', 'GenericButtons', 'wxEditor',
70 'ColourSelect', 'ImageBrowser',
71 'infoframe', 'ColourDB', 'PyCrust', 'PyCrustWithFilling',
76 ('Cool Contribs', ['pyTree', 'hangman',
83 #---------------------------------------------------------------------------
86 def __init__(self
, textCtrl
, logTime
=0):
87 wxPyLog
.__init
__(self
)
89 self
.logTime
= logTime
91 def DoLogString(self
, message
, timeStamp
):
93 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
95 self
.tc
.AppendText(message
+ '\n')
98 #---------------------------------------------------------------------------
101 """Convert paths to the platform-specific separator"""
102 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
105 #---------------------------------------------------------------------------
107 class wxPythonDemo(wxFrame
):
109 def __init__(self
, parent
, id, title
):
110 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
111 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
113 self
.cwd
= os
.getcwd()
114 self
.curOverview
= ""
116 icon
= images
.getMondrianIcon()
119 if wxPlatform
== '__WXMSW__':
120 # setup a taskbar icon, and catch some events from it
121 self
.tbicon
= wxTaskBarIcon()
122 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
123 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
124 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
125 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
126 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
130 EVT_IDLE(self
, self
.OnIdle
)
131 EVT_CLOSE(self
, self
.OnCloseWindow
)
132 EVT_ICONIZE(self
, self
.OnIconfiy
)
133 EVT_MAXIMIZE(self
, self
.OnMaximize
)
136 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
138 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
139 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
141 def EmptyHandler(evt
): pass
142 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
143 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
145 # Prevent TreeCtrl from displaying all items after destruction when true
149 self
.mainmenu
= wxMenuBar()
152 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
153 EVT_MENU(self
, exitID
, self
.OnFileExit
)
154 self
.mainmenu
.Append(menu
, '&File')
158 for item
in _treeList
:
160 for childItem
in item
[1]:
162 submenu
.Append(mID
, childItem
)
163 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
164 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
165 self
.mainmenu
.Append(menu
, '&Demo')
171 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
172 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
173 self
.mainmenu
.Append(menu
, '&Help')
174 self
.SetMenuBar(self
.mainmenu
)
176 # set the menu accellerator table...
177 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
178 (wxACCEL_CTRL
, ord('H'), helpID
)])
179 self
.SetAcceleratorTable(aTable
)
185 self
.tree
= wxTreeCtrl(splitter
, tID
,
186 style
=wxTR_HAS_BUTTONS |
188 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
190 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
191 root
= self
.tree
.AddRoot("Overview")
193 for item
in _treeList
:
194 child
= self
.tree
.AppendItem(root
, item
[0])
195 if not firstChild
: firstChild
= child
196 for childItem
in item
[1]:
197 theDemo
= self
.tree
.AppendItem(child
, childItem
)
198 self
.treeMap
[childItem
] = theDemo
200 self
.tree
.Expand(root
)
201 self
.tree
.Expand(firstChild
)
202 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
203 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
204 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
205 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
208 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
210 # Set up a wxHtmlWindow on the Overview Notebook page
211 # we put it in a panel first because there seems to be a
212 # refresh bug of some sort (wxGTK) when it is directly in
215 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
216 self
.nb
.AddPage(self
.ovr
, "Overview")
218 else: # hopefully I can remove this hacky code soon, see bug #216861
219 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
220 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
221 self
.nb
.AddPage(panel
, "Overview")
223 def OnOvrSize(evt
, ovr
=self
.ovr
):
224 ovr
.SetSize(evt
.GetSize())
226 EVT_SIZE(panel
, OnOvrSize
)
227 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
230 self
.SetOverview("Overview", overview
)
233 # Set up a TextCtrl on the Demo Code Notebook page
234 self
.txt
= wxTextCtrl(self
.nb
, -1,
235 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
236 self
.nb
.AddPage(self
.txt
, "Demo Code")
239 # Set up a log on the View Log Notebook page
240 self
.log
= wxTextCtrl(splitter2
, -1,
241 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
242 # Set the wxWindows log target to be this textctrl
243 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
244 wxLog_SetActiveTarget(MyLog(self
.log
))
250 # add the windows to the splitter and split it.
251 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
252 splitter
.SplitVertically(self
.tree
, splitter2
)
254 splitter
.SetSashPosition(180, true
)
255 splitter
.SetMinimumPaneSize(20)
256 splitter2
.SetSashPosition(450, true
)
257 splitter2
.SetMinimumPaneSize(20)
261 # select initial items
262 self
.nb
.SetSelection(0)
263 self
.tree
.SelectItem(root
)
265 if len(sys
.argv
) == 2:
267 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
271 self
.tree
.SelectItem(selectedDemo
)
272 self
.tree
.EnsureVisible(selectedDemo
)
275 wxLogMessage('window handle: %s' % self
.GetHandle())
278 #---------------------------------------------
279 def WriteText(self
, text
):
280 if text
[-1:] == '\n':
285 def write(self
, txt
):
288 #---------------------------------------------
289 def OnItemExpanded(self
, event
):
290 item
= event
.GetItem()
291 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
294 #---------------------------------------------
295 def OnItemCollapsed(self
, event
):
296 item
= event
.GetItem()
297 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
300 #---------------------------------------------
301 def OnTreeLeftDown(self
, event
):
302 pt
= event
.GetPosition();
303 item
, flags
= self
.tree
.HitTest(pt
)
304 if item
== self
.tree
.GetSelection():
305 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
308 #---------------------------------------------
309 def OnSelChanged(self
, event
):
313 item
= event
.GetItem()
314 itemText
= self
.tree
.GetItemText(item
)
315 self
.RunDemo(itemText
)
318 #---------------------------------------------
319 def RunDemo(self
, itemText
):
321 if self
.nb
.GetPageCount() == 3:
322 if self
.nb
.GetSelection() == 2:
323 self
.nb
.SetSelection(0)
324 self
.nb
.DeletePage(2)
326 if itemText
== 'Overview':
327 self
.GetDemoFile('Main.py')
328 self
.SetOverview('Overview', overview
)
333 if os
.path
.exists(itemText
+ '.py'):
335 wxLogMessage("Running demo %s.py..." % itemText
)
337 self
.GetDemoFile(itemText
+ '.py')
338 module
= __import__(itemText
, globals())
339 self
.SetOverview(itemText
, module
.overview
)
343 # in case runTest is modal, make sure things look right...
347 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
349 self
.nb
.AddPage(self
.window
, 'Demo')
351 self
.nb
.SetSelection(2)
360 #---------------------------------------------
362 def GetDemoFile(self
, filename
):
365 self
.txt
.SetValue(open(filename
).read())
367 self
.txt
.WriteText("Cannot open %s file." % filename
)
369 self
.txt
.SetInsertionPoint(0)
370 self
.txt
.ShowPosition(0)
372 #---------------------------------------------
373 def SetOverview(self
, name
, text
):
374 self
.curOverview
= text
376 if lead
!= '<html>' and lead
!= '<HTML>':
377 text
= string
.join(string
.split(text
, '\n'), '<br>')
378 self
.ovr
.SetPage(text
)
379 self
.nb
.SetPageText(0, name
)
381 #---------------------------------------------
383 def OnFileExit(self
, *event
):
387 def OnHelpAbout(self
, event
):
388 from About
import MyAboutBox
389 about
= MyAboutBox(self
)
394 #---------------------------------------------
395 def OnCloseWindow(self
, event
):
399 if hasattr(self
, "tbicon"):
404 #---------------------------------------------
405 def OnIdle(self
, event
):
407 self
.otherWin
.Raise()
408 self
.window
= self
.otherWin
411 #---------------------------------------------
412 def OnDemoMenu(self
, event
):
414 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
418 self
.tree
.SelectItem(selectedDemo
)
419 self
.tree
.EnsureVisible(selectedDemo
)
422 #---------------------------------------------
423 def OnTaskBarActivate(self
, evt
):
424 if self
.IsIconized():
426 if not self
.IsShown():
430 #---------------------------------------------
432 TBMENU_RESTORE
= 1000
435 def OnTaskBarMenu(self
, evt
):
437 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
438 menu
.Append(self
.TBMENU_CLOSE
, "Close")
439 self
.tbicon
.PopupMenu(menu
)
442 #---------------------------------------------
443 def OnTaskBarClose(self
, evt
):
446 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
447 # prod the main idle handler a bit to get the window to actually close
448 wxGetApp().ProcessIdle()
451 #---------------------------------------------
452 def OnIconfiy(self
, evt
):
453 wxLogMessage("OnIconfiy")
456 #---------------------------------------------
457 def OnMaximize(self
, evt
):
458 wxLogMessage("OnMaximize")
464 #---------------------------------------------------------------------------
465 #---------------------------------------------------------------------------
467 class MySplashScreen(wxSplashScreen
):
469 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
470 wxSplashScreen
.__init
__(self
, bmp
,
471 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
473 EVT_CLOSE(self
, self
.OnClose
)
475 def OnClose(self
, evt
):
476 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
481 def ShowTip(self
, frame
):
483 showTipText
= open(opj("data/showTips")).read()
484 showTip
, index
= eval(showTipText
)
486 showTip
, index
= (1, 0)
488 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
489 showTip
= wxShowTip(frame
, tp
)
490 index
= tp
.GetCurrentTip()
491 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
498 Create and show the splash screen. It will then create and show
499 the main frame when it is time to do so.
501 wxInitAllImageHandlers()
502 splash
= MySplashScreen()
509 #---------------------------------------------------------------------------
513 demoPath
= os
.path
.dirname(__file__
)
521 #---------------------------------------------------------------------------
525 overview
= """<html><body>
528 Python is an interpreted, interactive, object-oriented programming
529 language often compared to Tcl, Perl, Scheme, or Java.
531 <p> Python combines remarkable power with very clear syntax. It has
532 modules, classes, exceptions, very high level dynamic data types, and
533 dynamic typing. There are interfaces to many system calls and
534 libraries, and new built-in modules are easily written in C or
535 C++. Python is also usable as an extension language for applications
536 that need a programmable interface. <p>
540 wxWindows is a free C++ framework designed to make cross-platform
541 programming child's play. Well, almost. wxWindows 2 supports Windows
542 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
543 underway. Other ports are under consideration. <p>
545 wxWindows is a set of libraries that allows C++ applications to
546 compile and run on several different types of computers, with minimal
547 source code changes. There is one library per supported GUI (such as
548 Motif, or Windows). As well as providing a common API (Application
549 Programming Interface) for GUI functionality, it provides
550 functionality for accessing some commonly-used operating system
551 facilities, such as copying or deleting files. wxWindows is a
552 'framework' in the sense that it provides a lot of built-in
553 functionality, which the application can use or replace as required,
554 thus saving a great deal of coding effort. Basic data structures such
555 as strings, linked lists and hash tables are also supported.
560 wxPython is a Python extension module that encapsulates the wxWindows
561 GUI classes. Currently it is only available for the Win32 and GTK
562 ports of wxWindows, but as soon as the other ports are brought up to
563 the same level as Win32 and GTK, it should be fairly trivial to
564 enable wxPython to be used with the new GUI.
568 The wxPython extension module attempts to mirror the class heiarchy
569 of wxWindows as closely as possible. This means that there is a
570 wxFrame class in wxPython that looks, smells, tastes and acts almost
571 the same as the wxFrame class in the C++ version. Unfortunately,
572 because of differences in the languages, wxPython doesn't match
573 wxWindows exactly, but the differences should be easy to absorb
574 because they are natural to Python. For example, some methods that
575 return multiple values via argument pointers in C++ will return a
576 tuple of values in Python.
580 There is still much to be done for wxPython, many classes still need
581 to be mirrored. Also, wxWindows is still somewhat of a moving target
582 so it is a bit of an effort just keeping wxPython up to date. On the
583 other hand, there are enough of the core classes completed that
584 useful applications can be written.
588 wxPython is close enough to the C++ version that the majority of
589 the wxPython documentation is actually just notes attached to the C++
590 documents that describe the places where wxPython is different. There
591 is also a series of sample programs included, and a series of
592 documentation pages that assist the programmer in getting started
598 #----------------------------------------------------------------------------
599 #----------------------------------------------------------------------------
601 if __name__
== '__main__':
604 #----------------------------------------------------------------------------