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',
30 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
31 'wxGrid', 'wxSashWindow',
32 'wxScrolledWindow', 'wxSplitterWindow',
33 'wxStatusBar', 'wxNotebook',
35 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
37 'wxDynamicSashWindow',
40 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
41 'wxSingleChoiceDialog', 'wxTextEntryDialog',
42 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
43 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
46 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
47 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'VirtualListCtrl',
49 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
50 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
51 'wxCalendarCtrl', 'wxToggleButton',
52 'wxEditableListBox', 'wxLEDNumberCtrl',
55 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource',
59 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
61 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
62 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
63 'PythonEvents', 'Threads',
64 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
65 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
66 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
67 'ContextHelp', 'SplitTree', 'Unicode',
70 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
71 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
72 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
73 'FileBrowseButton', 'GenericButtons', 'wxEditor',
74 'ColourSelect', 'ImageBrowser',
75 'infoframe', 'ColourDB', 'PyCrust', 'PyCrustWithFilling',
80 ('Cool Contribs', ['pyTree', 'hangman',
87 #---------------------------------------------------------------------------
90 def __init__(self
, textCtrl
, logTime
=0):
91 wxPyLog
.__init
__(self
)
93 self
.logTime
= logTime
95 def DoLogString(self
, message
, timeStamp
):
97 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
99 self
.tc
.AppendText(message
+ '\n')
102 #---------------------------------------------------------------------------
105 """Convert paths to the platform-specific separator"""
106 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
109 #---------------------------------------------------------------------------
111 class wxPythonDemo(wxFrame
):
112 overviewText
= "wxPython Overview"
114 def __init__(self
, parent
, id, title
):
115 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
116 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
118 self
.cwd
= os
.getcwd()
119 self
.curOverview
= ""
121 icon
= images
.getMondrianIcon()
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
)
136 EVT_IDLE(self
, self
.OnIdle
)
137 EVT_CLOSE(self
, self
.OnCloseWindow
)
138 EVT_ICONIZE(self
, self
.OnIconfiy
)
139 EVT_MAXIMIZE(self
, self
.OnMaximize
)
142 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
144 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
145 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
147 def EmptyHandler(evt
): pass
148 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
149 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
151 # Prevent TreeCtrl from displaying all items after destruction when true
155 self
.mainmenu
= wxMenuBar()
158 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
159 EVT_MENU(self
, exitID
, self
.OnFileExit
)
160 self
.mainmenu
.Append(menu
, '&File')
164 for item
in _treeList
:
166 for childItem
in item
[1]:
168 submenu
.Append(mID
, childItem
)
169 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
170 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
171 self
.mainmenu
.Append(menu
, '&Demo')
177 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
178 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
179 self
.mainmenu
.Append(menu
, '&Help')
180 self
.SetMenuBar(self
.mainmenu
)
182 # set the menu accellerator table...
183 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
184 (wxACCEL_CTRL
, ord('H'), helpID
)])
185 self
.SetAcceleratorTable(aTable
)
191 self
.tree
= wxTreeCtrl(splitter
, tID
,
192 style
=wxTR_HAS_BUTTONS |
194 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
196 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
197 root
= self
.tree
.AddRoot("wxPython Overview")
199 for item
in _treeList
:
200 child
= self
.tree
.AppendItem(root
, item
[0])
201 if not firstChild
: firstChild
= child
202 for childItem
in item
[1]:
203 theDemo
= self
.tree
.AppendItem(child
, childItem
)
204 self
.treeMap
[childItem
] = theDemo
206 self
.tree
.Expand(root
)
207 self
.tree
.Expand(firstChild
)
208 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
209 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
210 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
211 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
214 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
216 # Set up a wxHtmlWindow on the Overview Notebook page
217 # we put it in a panel first because there seems to be a
218 # refresh bug of some sort (wxGTK) when it is directly in
221 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
222 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
224 else: # hopefully I can remove this hacky code soon, see bug #216861
225 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
226 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
227 self
.nb
.AddPage(panel
, self
.overviewText
)
229 def OnOvrSize(evt
, ovr
=self
.ovr
):
230 ovr
.SetSize(evt
.GetSize())
232 EVT_SIZE(panel
, OnOvrSize
)
233 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
236 self
.SetOverview(self
.overviewText
, overview
)
239 # Set up a TextCtrl on the Demo Code Notebook page
240 self
.txt
= wxTextCtrl(self
.nb
, -1,
241 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
242 self
.nb
.AddPage(self
.txt
, "Demo Code")
245 # Set up a log on the View Log Notebook page
246 self
.log
= wxTextCtrl(splitter2
, -1,
247 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
248 # Set the wxWindows log target to be this textctrl
249 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
250 wxLog_SetActiveTarget(MyLog(self
.log
))
256 # add the windows to the splitter and split it.
257 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
258 splitter
.SplitVertically(self
.tree
, splitter2
)
260 splitter
.SetSashPosition(180, true
)
261 splitter
.SetMinimumPaneSize(20)
262 splitter2
.SetSashPosition(450, true
)
263 splitter2
.SetMinimumPaneSize(20)
267 # select initial items
268 self
.nb
.SetSelection(0)
269 self
.tree
.SelectItem(root
)
271 if len(sys
.argv
) == 2:
273 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
277 self
.tree
.SelectItem(selectedDemo
)
278 self
.tree
.EnsureVisible(selectedDemo
)
281 wxLogMessage('window handle: %s' % self
.GetHandle())
284 #---------------------------------------------
285 def WriteText(self
, text
):
286 if text
[-1:] == '\n':
291 def write(self
, txt
):
294 #---------------------------------------------
295 def OnItemExpanded(self
, event
):
296 item
= event
.GetItem()
297 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
300 #---------------------------------------------
301 def OnItemCollapsed(self
, event
):
302 item
= event
.GetItem()
303 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
306 #---------------------------------------------
307 def OnTreeLeftDown(self
, event
):
308 pt
= event
.GetPosition();
309 item
, flags
= self
.tree
.HitTest(pt
)
310 if item
== self
.tree
.GetSelection():
311 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
314 #---------------------------------------------
315 def OnSelChanged(self
, event
):
319 item
= event
.GetItem()
320 itemText
= self
.tree
.GetItemText(item
)
321 self
.RunDemo(itemText
)
324 #---------------------------------------------
325 def RunDemo(self
, itemText
):
327 if self
.nb
.GetPageCount() == 3:
328 if self
.nb
.GetSelection() == 2:
329 self
.nb
.SetSelection(0)
330 self
.nb
.DeletePage(2)
332 if itemText
== self
.overviewText
:
333 self
.GetDemoFile('Main.py')
334 self
.SetOverview(self
.overviewText
, overview
)
339 if os
.path
.exists(itemText
+ '.py'):
341 wxLogMessage("Running demo %s.py..." % itemText
)
343 self
.GetDemoFile(itemText
+ '.py')
344 module
= __import__(itemText
, globals())
345 self
.SetOverview(itemText
+ " Overview", module
.overview
)
349 # in case runTest is modal, make sure things look right...
353 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
355 self
.nb
.AddPage(self
.window
, 'Demo')
357 self
.nb
.SetSelection(2)
366 #---------------------------------------------
368 def GetDemoFile(self
, filename
):
371 self
.txt
.SetValue(open(filename
).read())
373 self
.txt
.WriteText("Cannot open %s file." % filename
)
375 self
.txt
.SetInsertionPoint(0)
376 self
.txt
.ShowPosition(0)
378 #---------------------------------------------
379 def SetOverview(self
, name
, text
):
380 self
.curOverview
= text
382 if lead
!= '<html>' and lead
!= '<HTML>':
383 text
= string
.join(string
.split(text
, '\n'), '<br>')
384 self
.ovr
.SetPage(text
)
385 self
.nb
.SetPageText(0, name
)
387 #---------------------------------------------
389 def OnFileExit(self
, *event
):
393 def OnHelpAbout(self
, event
):
394 from About
import MyAboutBox
395 about
= MyAboutBox(self
)
400 #---------------------------------------------
401 def OnCloseWindow(self
, event
):
405 if hasattr(self
, "tbicon"):
410 #---------------------------------------------
411 def OnIdle(self
, event
):
413 self
.otherWin
.Raise()
414 self
.window
= self
.otherWin
422 #---------------------------------------------
425 showTipText
= open(opj("data/showTips")).read()
426 showTip
, index
= eval(showTipText
)
428 showTip
, index
= (1, 0)
430 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
431 showTip
= wxShowTip(self
, tp
)
432 index
= tp
.GetCurrentTip()
433 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
436 #---------------------------------------------
437 def OnDemoMenu(self
, event
):
439 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
443 self
.tree
.SelectItem(selectedDemo
)
444 self
.tree
.EnsureVisible(selectedDemo
)
447 #---------------------------------------------
448 def OnTaskBarActivate(self
, evt
):
449 if self
.IsIconized():
451 if not self
.IsShown():
455 #---------------------------------------------
457 TBMENU_RESTORE
= 1000
460 def OnTaskBarMenu(self
, evt
):
462 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
463 menu
.Append(self
.TBMENU_CLOSE
, "Close")
464 self
.tbicon
.PopupMenu(menu
)
467 #---------------------------------------------
468 def OnTaskBarClose(self
, evt
):
471 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
472 # prod the main idle handler a bit to get the window to actually close
473 wxGetApp().ProcessIdle()
476 #---------------------------------------------
477 def OnIconfiy(self
, evt
):
478 wxLogMessage("OnIconfiy")
481 #---------------------------------------------
482 def OnMaximize(self
, evt
):
483 wxLogMessage("OnMaximize")
489 #---------------------------------------------------------------------------
490 #---------------------------------------------------------------------------
492 class MySplashScreen(wxSplashScreen
):
494 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
495 wxSplashScreen
.__init
__(self
, bmp
,
496 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
498 EVT_CLOSE(self
, self
.OnClose
)
500 def OnClose(self
, evt
):
501 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
503 evt
.Skip() # Make sure the default handler runs too...
509 Create and show the splash screen. It will then create and show
510 the main frame when it is time to do so.
512 wxInitAllImageHandlers()
513 splash
= MySplashScreen()
519 #---------------------------------------------------------------------------
523 demoPath
= os
.path
.dirname(__file__
)
531 #---------------------------------------------------------------------------
535 overview
= """<html><body>
538 Python is an interpreted, interactive, object-oriented programming
539 language often compared to Tcl, Perl, Scheme, or Java.
541 <p> Python combines remarkable power with very clear syntax. It has
542 modules, classes, exceptions, very high level dynamic data types, and
543 dynamic typing. There are interfaces to many system calls and
544 libraries, and new built-in modules are easily written in C or
545 C++. Python is also usable as an extension language for applications
546 that need a programmable interface. <p>
550 wxWindows is a free C++ framework designed to make cross-platform
551 programming child's play. Well, almost. wxWindows 2 supports Windows
552 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
553 underway. Other ports are under consideration. <p>
555 wxWindows is a set of libraries that allows C++ applications to
556 compile and run on several different types of computers, with minimal
557 source code changes. There is one library per supported GUI (such as
558 Motif, or Windows). As well as providing a common API (Application
559 Programming Interface) for GUI functionality, it provides
560 functionality for accessing some commonly-used operating system
561 facilities, such as copying or deleting files. wxWindows is a
562 'framework' in the sense that it provides a lot of built-in
563 functionality, which the application can use or replace as required,
564 thus saving a great deal of coding effort. Basic data structures such
565 as strings, linked lists and hash tables are also supported.
570 wxPython is a Python extension module that encapsulates the wxWindows
571 GUI classes. Currently it is only available for the Win32 and GTK
572 ports of wxWindows, but as soon as the other ports are brought up to
573 the same level as Win32 and GTK, it should be fairly trivial to
574 enable wxPython to be used with the new GUI.
578 The wxPython extension module attempts to mirror the class heiarchy
579 of wxWindows as closely as possible. This means that there is a
580 wxFrame class in wxPython that looks, smells, tastes and acts almost
581 the same as the wxFrame class in the C++ version. Unfortunately,
582 because of differences in the languages, wxPython doesn't match
583 wxWindows exactly, but the differences should be easy to absorb
584 because they are natural to Python. For example, some methods that
585 return multiple values via argument pointers in C++ will return a
586 tuple of values in Python.
590 There is still much to be done for wxPython, many classes still need
591 to be mirrored. Also, wxWindows is still somewhat of a moving target
592 so it is a bit of an effort just keeping wxPython up to date. On the
593 other hand, there are enough of the core classes completed that
594 useful applications can be written.
598 wxPython is close enough to the C++ version that the majority of
599 the wxPython documentation is actually just notes attached to the C++
600 documents that describe the places where wxPython is different. There
601 is also a series of sample programs included, and a series of
602 documentation pages that assist the programmer in getting started
608 #----------------------------------------------------------------------------
609 #----------------------------------------------------------------------------
611 if __name__
== '__main__':
614 #----------------------------------------------------------------------------