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 #----------------------------------------------------------------------------
15 from wxPython
.wx
import *
16 from wxPython
.lib
.splashscreen
import SplashScreen
17 from wxPython
.html
import wxHtmlWindow
21 #---------------------------------------------------------------------------
25 ('New since last release', ['ColourSelect', 'ImageBrowser', 'infoframe',
26 'ColourDB', 'wxToggleButton', 'OOR', 'wxWave',
30 ('Managed Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame']),
32 ('Non-Managed Windows', ['wxGrid', 'wxSashWindow',
33 'wxScrolledWindow', 'wxSplitterWindow',
34 'wxStatusBar', 'wxNotebook',
36 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',]),
38 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
39 'wxSingleChoiceDialog', 'wxTextEntryDialog',
40 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
41 'wxMessageDialog', 'wxProgressDialog']),
43 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
44 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl',
45 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
46 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
47 'wxCalendarCtrl', 'wxToggleButton',
50 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', ]),
52 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'FontEnumerator',
53 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
54 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
55 'PythonEvents', 'Threads',
56 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
57 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
61 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
62 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
63 'PyShell', 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
64 'FileBrowseButton', 'GenericButtons', 'wxEditor',
65 'PyShellWindow', 'ColourSelect', 'ImageBrowser',
68 ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']),
72 #---------------------------------------------------------------------------
74 class wxPythonDemo(wxFrame
):
76 def __init__(self
, parent
, id, title
):
77 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
78 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
80 self
.cwd
= os
.getcwd()
84 icon
= wxIconFromXPMData(images
.getMondrianData())
86 # another way to do it
87 bmp
= images
.getMondrianBitmap()
89 icon
.CopyFromBitmap(bmp
)
93 if wxPlatform
== '__WXMSW__':
94 # setup a taskbar icon, and catch some events from it
95 self
.tbicon
= wxTaskBarIcon()
96 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
97 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
98 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
99 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
100 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
104 EVT_IDLE(self
, self
.OnIdle
)
105 EVT_CLOSE(self
, self
.OnCloseWindow
)
106 EVT_ICONIZE(self
, self
.OnIconfiy
)
107 EVT_MAXIMIZE(self
, self
.OnMaximize
)
110 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
112 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
113 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
116 # Prevent TreeCtrl from displaying all items after destruction
120 self
.mainmenu
= wxMenuBar()
123 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
124 EVT_MENU(self
, exitID
, self
.OnFileExit
)
125 self
.mainmenu
.Append(menu
, '&File')
129 for item
in _treeList
:
131 for childItem
in item
[1]:
133 submenu
.Append(mID
, childItem
)
134 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
135 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
136 self
.mainmenu
.Append(menu
, '&Demo')
142 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
143 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
144 self
.mainmenu
.Append(menu
, '&Help')
145 self
.SetMenuBar(self
.mainmenu
)
147 # set the menu accellerator table...
148 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
149 (wxACCEL_CTRL
, ord('H'), helpID
)])
150 self
.SetAcceleratorTable(aTable
)
156 self
.tree
= wxTreeCtrl(splitter
, tID
,
157 style
=wxTR_HAS_BUTTONS |
159 wxTR_HAS_VARIABLE_ROW_HEIGHT |
161 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
162 root
= self
.tree
.AddRoot("Overview")
164 for item
in _treeList
:
165 child
= self
.tree
.AppendItem(root
, item
[0])
166 if not firstChild
: firstChild
= child
167 for childItem
in item
[1]:
168 theDemo
= self
.tree
.AppendItem(child
, childItem
)
169 self
.treeMap
[childItem
] = theDemo
171 self
.tree
.Expand(root
)
172 self
.tree
.Expand(firstChild
)
173 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
174 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
175 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
176 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
179 self
.nb
= wxNotebook(splitter2
, -1)
181 # Set up a wxHtmlWindow on the Overview Notebook page
182 # we put it in a panel first because there seems to be a
183 # refresh bug of some sort (wxGTK) when it is directly in
186 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
187 self
.nb
.AddPage(self
.ovr
, "Overview")
189 else: # hopefully I can remove this hacky code soon, see bug #216861
190 panel
= wxPanel(self
.nb
, -1)
191 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
192 self
.nb
.AddPage(panel
, "Overview")
194 def OnOvrSize(evt
, ovr
=self
.ovr
):
195 ovr
.SetSize(evt
.GetSize())
197 EVT_SIZE(panel
, OnOvrSize
)
199 self
.SetOverview("Overview", overview
)
202 # Set up a TextCtrl on the Demo Code Notebook page
203 self
.txt
= wxTextCtrl(self
.nb
, -1,
204 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
205 self
.txt
.SetFont(wxFont(9, wxMODERN
, wxNORMAL
, wxNORMAL
, false
))
206 self
.nb
.AddPage(self
.txt
, "Demo Code")
209 # Set up a log on the View Log Notebook page
210 self
.log
= wxTextCtrl(splitter2
, -1,
211 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
212 # Set the wxWindows log target to be this textctrl
213 wxLog_SetActiveTarget(wxLogTextCtrl(self
.log
))
219 # add the windows to the splitter and split it.
220 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
221 splitter2
.SetSashPosition(450, true
)
222 splitter2
.SetMinimumPaneSize(20)
224 splitter
.SplitVertically(self
.tree
, splitter2
)
225 splitter
.SetSashPosition(180, true
)
226 splitter
.SetMinimumPaneSize(20)
229 # select initial items
230 self
.nb
.SetSelection(0)
231 self
.tree
.SelectItem(root
)
233 if len(sys
.argv
) == 2:
235 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
239 self
.tree
.SelectItem(selectedDemo
)
240 self
.tree
.EnsureVisible(selectedDemo
)
243 wxLogMessage('window handle: %s' % self
.GetHandle())
246 #---------------------------------------------
247 def WriteText(self
, text
):
248 if text
[-1:] == '\n':
253 def write(self
, txt
):
256 #---------------------------------------------
257 def OnItemExpanded(self
, event
):
258 item
= event
.GetItem()
259 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
262 #---------------------------------------------
263 def OnItemCollapsed(self
, event
):
264 item
= event
.GetItem()
265 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
268 #---------------------------------------------
269 def OnTreeLeftDown(self
, event
):
270 pt
= event
.GetPosition();
271 item
, flags
= self
.tree
.HitTest(pt
)
272 if item
== self
.tree
.GetSelection():
273 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
276 #---------------------------------------------
277 def OnSelChanged(self
, event
):
281 item
= event
.GetItem()
282 itemText
= self
.tree
.GetItemText(item
)
283 self
.RunDemo(itemText
)
286 #---------------------------------------------
287 def RunDemo(self
, itemText
):
289 if self
.nb
.GetPageCount() == 3:
290 if self
.nb
.GetSelection() == 2:
291 self
.nb
.SetSelection(0)
292 self
.nb
.DeletePage(2)
294 if itemText
== 'Overview':
295 self
.GetDemoFile('Main.py')
296 self
.SetOverview('Overview', overview
)
301 if os
.path
.exists(itemText
+ '.py'):
303 wxLogMessage("Running demo %s.py..." % itemText
)
305 self
.GetDemoFile(itemText
+ '.py')
306 module
= __import__(itemText
, globals())
307 self
.SetOverview(itemText
, module
.overview
)
311 # in case runTest is modal, make sure things look right...
315 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
317 self
.nb
.AddPage(self
.window
, 'Demo')
319 self
.nb
.SetSelection(2)
328 #---------------------------------------------
330 def GetDemoFile(self
, filename
):
333 self
.txt
.SetValue(open(filename
).read())
335 self
.txt
.WriteText("Cannot open %s file." % filename
)
337 self
.txt
.SetInsertionPoint(0)
338 self
.txt
.ShowPosition(0)
340 #---------------------------------------------
341 def SetOverview(self
, name
, text
):
342 self
.curOverview
= text
344 if lead
!= '<html>' and lead
!= '<HTML>':
345 text
= string
.join(string
.split(text
, '\n'), '<br>')
346 #text = '<font size="-1"><pre>' + text + '</pre></font>'
347 self
.ovr
.SetPage(text
)
348 self
.nb
.SetPageText(0, name
)
350 #---------------------------------------------
352 def OnFileExit(self
, *event
):
356 def OnHelpAbout(self
, event
):
357 from About
import MyAboutBox
358 about
= MyAboutBox(self
)
363 #---------------------------------------------
364 def OnCloseWindow(self
, event
):
368 if hasattr(self
, "tbicon"):
373 #---------------------------------------------
374 def OnIdle(self
, event
):
376 self
.otherWin
.Raise()
377 self
.window
= self
.otherWin
380 #---------------------------------------------
381 def OnDemoMenu(self
, event
):
383 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
387 self
.tree
.SelectItem(selectedDemo
)
388 self
.tree
.EnsureVisible(selectedDemo
)
391 #---------------------------------------------
392 def OnTaskBarActivate(self
, evt
):
393 if self
.IsIconized():
395 if not self
.IsShown():
399 #---------------------------------------------
401 TBMENU_RESTORE
= 1000
404 def OnTaskBarMenu(self
, evt
):
406 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
407 menu
.Append(self
.TBMENU_CLOSE
, "Close")
408 self
.tbicon
.PopupMenu(menu
)
411 #---------------------------------------------
412 def OnTaskBarClose(self
, evt
):
415 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
416 # prod the main idle handler a bit to get the window to actually close
417 wxGetApp().ProcessIdle()
420 #---------------------------------------------
421 def OnIconfiy(self
, evt
):
422 wxLogMessage("OnIconfiy")
425 #---------------------------------------------
426 def OnMaximize(self
, evt
):
427 wxLogMessage("OnMaximize")
433 #---------------------------------------------------------------------------
434 #---------------------------------------------------------------------------
438 wxInitAllImageHandlers()
440 self
.splash
= SplashScreen(None, bitmapfile
='bitmaps/splash.gif',
441 duration
=4000, callback
=self
.AfterSplash
)
442 self
.splash
.Show(true
)
447 def AfterSplash(self
):
448 self
.splash
.Close(true
)
449 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
451 self
.SetTopWindow(frame
)
455 def ShowTip(self
, frame
):
457 showTipText
= open("data/showTips").read()
458 showTip
, index
= eval(showTipText
)
460 showTip
, index
= (1, 0)
461 #print showTip, index
463 tp
= wxCreateFileTipProvider("data/tips.txt", index
)
464 showTip
= wxShowTip(frame
, tp
)
465 index
= tp
.GetCurrentTip()
466 open("data/showTips", "w").write(str( (showTip
, index
) ))
469 #---------------------------------------------------------------------------
473 demoPath
= os
.path
.split(__file__
)[0]
481 #---------------------------------------------------------------------------
485 overview
= """<html><body>
488 Python is an interpreted, interactive, object-oriented programming
489 language often compared to Tcl, Perl, Scheme, or Java.
491 <p> Python combines remarkable power with very clear syntax. It has
492 modules, classes, exceptions, very high level dynamic data types, and
493 dynamic typing. There are interfaces to many system calls and
494 libraries, and new built-in modules are easily written in C or
495 C++. Python is also usable as an extension language for applications
496 that need a programmable interface. <p>
500 wxWindows is a free C++ framework designed to make cross-platform
501 programming child's play. Well, almost. wxWindows 2 supports Windows
502 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
503 underway. Other ports are under consideration. <p>
505 wxWindows is a set of libraries that allows C++ applications to
506 compile and run on several different types of computers, with minimal
507 source code changes. There is one library per supported GUI (such as
508 Motif, or Windows). As well as providing a common API (Application
509 Programming Interface) for GUI functionality, it provides
510 functionality for accessing some commonly-used operating system
511 facilities, such as copying or deleting files. wxWindows is a
512 'framework' in the sense that it provides a lot of built-in
513 functionality, which the application can use or replace as required,
514 thus saving a great deal of coding effort. Basic data structures such
515 as strings, linked lists and hash tables are also supported.
520 wxPython is a Python extension module that encapsulates the wxWindows
521 GUI classes. Currently it is only available for the Win32 and GTK
522 ports of wxWindows, but as soon as the other ports are brought up to
523 the same level as Win32 and GTK, it should be fairly trivial to
524 enable wxPython to be used with the new GUI.
528 The wxPython extension module attempts to mirror the class heiarchy
529 of wxWindows as closely as possible. This means that there is a
530 wxFrame class in wxPython that looks, smells, tastes and acts almost
531 the same as the wxFrame class in the C++ version. Unfortunately,
532 because of differences in the languages, wxPython doesn't match
533 wxWindows exactly, but the differences should be easy to absorb
534 because they are natural to Python. For example, some methods that
535 return multiple values via argument pointers in C++ will return a
536 tuple of values in Python.
540 There is still much to be done for wxPython, many classes still need
541 to be mirrored. Also, wxWindows is still somewhat of a moving target
542 so it is a bit of an effort just keeping wxPython up to date. On the
543 other hand, there are enough of the core classes completed that
544 useful applications can be written.
548 wxPython is close enough to the C++ version that the majority of
549 the wxPython documentation is actually just notes attached to the C++
550 documents that describe the places where wxPython is different. There
551 is also a series of sample programs included, and a series of
552 documentation pages that assist the programmer in getting started
558 #----------------------------------------------------------------------------
559 #----------------------------------------------------------------------------
561 if __name__
== '__main__':
564 #----------------------------------------------------------------------------