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',
27 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
28 'wxGrid', 'wxSashWindow',
29 'wxScrolledWindow', 'wxSplitterWindow',
30 'wxStatusBar', 'wxNotebook',
32 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
34 'wxDynamicSashWindow',
37 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
38 'wxSingleChoiceDialog', 'wxTextEntryDialog',
39 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
40 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
43 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
44 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'VirtualListCtrl',
46 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
47 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
48 'wxCalendarCtrl', 'wxToggleButton',
49 'wxEditableListBox', 'wxLEDNumberCtrl',
52 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
54 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
56 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
57 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
58 'PythonEvents', 'Threads',
59 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
60 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
61 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
62 'ContextHelp', 'SplitTree',
65 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
66 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
67 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
68 'FileBrowseButton', 'GenericButtons', 'wxEditor',
69 'ColourSelect', 'ImageBrowser',
70 'infoframe', 'ColourDB', 'PyCrust', 'PyCrustWithFilling',
75 ('Cool Contribs', ['pyTree', 'hangman',
82 #---------------------------------------------------------------------------
85 def __init__(self
, textCtrl
, logTime
=0):
86 wxPyLog
.__init
__(self
)
88 self
.logTime
= logTime
90 def DoLogString(self
, message
, timeStamp
):
92 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
94 self
.tc
.AppendText(message
+ '\n')
97 #---------------------------------------------------------------------------
100 """Convert paths to the platform-specific separator"""
101 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
104 #---------------------------------------------------------------------------
106 class wxPythonDemo(wxFrame
):
108 def __init__(self
, parent
, id, title
):
109 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
110 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
112 self
.cwd
= os
.getcwd()
113 self
.curOverview
= ""
116 icon
= wxIconFromXPMData(images
.getMondrianData())
118 # another way to do it
119 bmp
= images
.getMondrianBitmap()
121 icon
.CopyFromBitmap(bmp
)
125 if wxPlatform
== '__WXMSW__':
126 # setup a taskbar icon, and catch some events from it
127 self
.tbicon
= wxTaskBarIcon()
128 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
129 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
130 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
131 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
132 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("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
, "Overview")
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
, "Overview")
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("Overview", 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 splitter2
.SetSashPosition(450, true
)
259 splitter2
.SetMinimumPaneSize(20)
261 splitter
.SplitVertically(self
.tree
, splitter2
)
262 splitter
.SetSashPosition(180, true
)
263 splitter
.SetMinimumPaneSize(20)
266 # select initial items
267 self
.nb
.SetSelection(0)
268 self
.tree
.SelectItem(root
)
270 if len(sys
.argv
) == 2:
272 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
276 self
.tree
.SelectItem(selectedDemo
)
277 self
.tree
.EnsureVisible(selectedDemo
)
280 wxLogMessage('window handle: %s' % self
.GetHandle())
283 #---------------------------------------------
284 def WriteText(self
, text
):
285 if text
[-1:] == '\n':
290 def write(self
, txt
):
293 #---------------------------------------------
294 def OnItemExpanded(self
, event
):
295 item
= event
.GetItem()
296 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
299 #---------------------------------------------
300 def OnItemCollapsed(self
, event
):
301 item
= event
.GetItem()
302 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
305 #---------------------------------------------
306 def OnTreeLeftDown(self
, event
):
307 pt
= event
.GetPosition();
308 item
, flags
= self
.tree
.HitTest(pt
)
309 if item
== self
.tree
.GetSelection():
310 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
313 #---------------------------------------------
314 def OnSelChanged(self
, event
):
318 item
= event
.GetItem()
319 itemText
= self
.tree
.GetItemText(item
)
320 self
.RunDemo(itemText
)
323 #---------------------------------------------
324 def RunDemo(self
, itemText
):
326 if self
.nb
.GetPageCount() == 3:
327 if self
.nb
.GetSelection() == 2:
328 self
.nb
.SetSelection(0)
329 self
.nb
.DeletePage(2)
331 if itemText
== 'Overview':
332 self
.GetDemoFile('Main.py')
333 self
.SetOverview('Overview', overview
)
338 if os
.path
.exists(itemText
+ '.py'):
340 wxLogMessage("Running demo %s.py..." % itemText
)
342 self
.GetDemoFile(itemText
+ '.py')
343 module
= __import__(itemText
, globals())
344 self
.SetOverview(itemText
, module
.overview
)
348 # in case runTest is modal, make sure things look right...
352 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
354 self
.nb
.AddPage(self
.window
, 'Demo')
356 self
.nb
.SetSelection(2)
365 #---------------------------------------------
367 def GetDemoFile(self
, filename
):
370 self
.txt
.SetValue(open(filename
).read())
372 self
.txt
.WriteText("Cannot open %s file." % filename
)
374 self
.txt
.SetInsertionPoint(0)
375 self
.txt
.ShowPosition(0)
377 #---------------------------------------------
378 def SetOverview(self
, name
, text
):
379 self
.curOverview
= text
381 if lead
!= '<html>' and lead
!= '<HTML>':
382 text
= string
.join(string
.split(text
, '\n'), '<br>')
383 self
.ovr
.SetPage(text
)
384 self
.nb
.SetPageText(0, name
)
386 #---------------------------------------------
388 def OnFileExit(self
, *event
):
392 def OnHelpAbout(self
, event
):
393 from About
import MyAboutBox
394 about
= MyAboutBox(self
)
399 #---------------------------------------------
400 def OnCloseWindow(self
, event
):
404 if hasattr(self
, "tbicon"):
409 #---------------------------------------------
410 def OnIdle(self
, event
):
412 self
.otherWin
.Raise()
413 self
.window
= self
.otherWin
416 #---------------------------------------------
417 def OnDemoMenu(self
, event
):
419 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
423 self
.tree
.SelectItem(selectedDemo
)
424 self
.tree
.EnsureVisible(selectedDemo
)
427 #---------------------------------------------
428 def OnTaskBarActivate(self
, evt
):
429 if self
.IsIconized():
431 if not self
.IsShown():
435 #---------------------------------------------
437 TBMENU_RESTORE
= 1000
440 def OnTaskBarMenu(self
, evt
):
442 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
443 menu
.Append(self
.TBMENU_CLOSE
, "Close")
444 self
.tbicon
.PopupMenu(menu
)
447 #---------------------------------------------
448 def OnTaskBarClose(self
, evt
):
451 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
452 # prod the main idle handler a bit to get the window to actually close
453 wxGetApp().ProcessIdle()
456 #---------------------------------------------
457 def OnIconfiy(self
, evt
):
458 wxLogMessage("OnIconfiy")
461 #---------------------------------------------
462 def OnMaximize(self
, evt
):
463 wxLogMessage("OnMaximize")
469 #---------------------------------------------------------------------------
470 #---------------------------------------------------------------------------
472 class MySplashScreen(wxSplashScreen
):
474 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
475 wxSplashScreen
.__init
__(self
, bmp
,
476 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
478 EVT_CLOSE(self
, self
.OnClose
)
480 def OnClose(self
, evt
):
481 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
486 def ShowTip(self
, frame
):
488 showTipText
= open(opj("data/showTips")).read()
489 showTip
, index
= eval(showTipText
)
491 showTip
, index
= (1, 0)
493 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
494 showTip
= wxShowTip(frame
, tp
)
495 index
= tp
.GetCurrentTip()
496 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
503 Create and show the splash screen. It will then create and show
504 the main frame when it is time to do so.
506 wxInitAllImageHandlers()
507 splash
= MySplashScreen()
514 #---------------------------------------------------------------------------
518 demoPath
= os
.path
.dirname(__file__
)
526 #---------------------------------------------------------------------------
530 overview
= """<html><body>
533 Python is an interpreted, interactive, object-oriented programming
534 language often compared to Tcl, Perl, Scheme, or Java.
536 <p> Python combines remarkable power with very clear syntax. It has
537 modules, classes, exceptions, very high level dynamic data types, and
538 dynamic typing. There are interfaces to many system calls and
539 libraries, and new built-in modules are easily written in C or
540 C++. Python is also usable as an extension language for applications
541 that need a programmable interface. <p>
545 wxWindows is a free C++ framework designed to make cross-platform
546 programming child's play. Well, almost. wxWindows 2 supports Windows
547 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
548 underway. Other ports are under consideration. <p>
550 wxWindows is a set of libraries that allows C++ applications to
551 compile and run on several different types of computers, with minimal
552 source code changes. There is one library per supported GUI (such as
553 Motif, or Windows). As well as providing a common API (Application
554 Programming Interface) for GUI functionality, it provides
555 functionality for accessing some commonly-used operating system
556 facilities, such as copying or deleting files. wxWindows is a
557 'framework' in the sense that it provides a lot of built-in
558 functionality, which the application can use or replace as required,
559 thus saving a great deal of coding effort. Basic data structures such
560 as strings, linked lists and hash tables are also supported.
565 wxPython is a Python extension module that encapsulates the wxWindows
566 GUI classes. Currently it is only available for the Win32 and GTK
567 ports of wxWindows, but as soon as the other ports are brought up to
568 the same level as Win32 and GTK, it should be fairly trivial to
569 enable wxPython to be used with the new GUI.
573 The wxPython extension module attempts to mirror the class heiarchy
574 of wxWindows as closely as possible. This means that there is a
575 wxFrame class in wxPython that looks, smells, tastes and acts almost
576 the same as the wxFrame class in the C++ version. Unfortunately,
577 because of differences in the languages, wxPython doesn't match
578 wxWindows exactly, but the differences should be easy to absorb
579 because they are natural to Python. For example, some methods that
580 return multiple values via argument pointers in C++ will return a
581 tuple of values in Python.
585 There is still much to be done for wxPython, many classes still need
586 to be mirrored. Also, wxWindows is still somewhat of a moving target
587 so it is a bit of an effort just keeping wxPython up to date. On the
588 other hand, there are enough of the core classes completed that
589 useful applications can be written.
593 wxPython is close enough to the C++ version that the majority of
594 the wxPython documentation is actually just notes attached to the C++
595 documents that describe the places where wxPython is different. There
596 is also a series of sample programs included, and a series of
597 documentation pages that assist the programmer in getting started
603 #----------------------------------------------------------------------------
604 #----------------------------------------------------------------------------
606 if __name__
== '__main__':
609 #----------------------------------------------------------------------------