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', ['ContextHelp',
28 ('Managed Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame']),
30 ('Non-Managed Windows', ['wxGrid', 'wxSashWindow',
31 'wxScrolledWindow', 'wxSplitterWindow',
32 'wxStatusBar', 'wxNotebook',
34 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',]),
36 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
37 'wxSingleChoiceDialog', 'wxTextEntryDialog',
38 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
39 'wxMessageDialog', 'wxProgressDialog']),
41 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
42 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl',
43 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
44 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
45 'wxCalendarCtrl', 'wxToggleButton',
48 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
50 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'FontEnumerator',
51 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
52 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
53 'PythonEvents', 'Threads',
54 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
55 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
59 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
60 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
61 'PyShell', 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
62 'FileBrowseButton', 'GenericButtons', 'wxEditor',
63 'PyShellWindow', 'ColourSelect', 'ImageBrowser',
64 'infoframe', 'ColourDB',
67 ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']),
71 #---------------------------------------------------------------------------
73 class wxPythonDemo(wxFrame
):
75 def __init__(self
, parent
, id, title
):
76 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
77 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
79 self
.cwd
= os
.getcwd()
83 icon
= wxIconFromXPMData(images
.getMondrianData())
85 # another way to do it
86 bmp
= images
.getMondrianBitmap()
88 icon
.CopyFromBitmap(bmp
)
92 if wxPlatform
== '__WXMSW__':
93 # setup a taskbar icon, and catch some events from it
94 self
.tbicon
= wxTaskBarIcon()
95 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
96 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
97 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
98 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
99 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
103 EVT_IDLE(self
, self
.OnIdle
)
104 EVT_CLOSE(self
, self
.OnCloseWindow
)
105 EVT_ICONIZE(self
, self
.OnIconfiy
)
106 EVT_MAXIMIZE(self
, self
.OnMaximize
)
109 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
111 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
112 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
114 def EmptyHandler(evt
): pass
115 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
116 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
118 # Prevent TreeCtrl from displaying all items after destruction
122 self
.mainmenu
= wxMenuBar()
125 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
126 EVT_MENU(self
, exitID
, self
.OnFileExit
)
127 self
.mainmenu
.Append(menu
, '&File')
131 for item
in _treeList
:
133 for childItem
in item
[1]:
135 submenu
.Append(mID
, childItem
)
136 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
137 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
138 self
.mainmenu
.Append(menu
, '&Demo')
144 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
145 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
146 self
.mainmenu
.Append(menu
, '&Help')
147 self
.SetMenuBar(self
.mainmenu
)
149 # set the menu accellerator table...
150 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
151 (wxACCEL_CTRL
, ord('H'), helpID
)])
152 self
.SetAcceleratorTable(aTable
)
158 self
.tree
= wxTreeCtrl(splitter
, tID
,
159 style
=wxTR_HAS_BUTTONS |
161 wxTR_HAS_VARIABLE_ROW_HEIGHT |
163 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
164 root
= self
.tree
.AddRoot("Overview")
166 for item
in _treeList
:
167 child
= self
.tree
.AppendItem(root
, item
[0])
168 if not firstChild
: firstChild
= child
169 for childItem
in item
[1]:
170 theDemo
= self
.tree
.AppendItem(child
, childItem
)
171 self
.treeMap
[childItem
] = theDemo
173 self
.tree
.Expand(root
)
174 self
.tree
.Expand(firstChild
)
175 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
176 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
177 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
178 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
181 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
183 # Set up a wxHtmlWindow on the Overview Notebook page
184 # we put it in a panel first because there seems to be a
185 # refresh bug of some sort (wxGTK) when it is directly in
188 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
189 self
.nb
.AddPage(self
.ovr
, "Overview")
191 else: # hopefully I can remove this hacky code soon, see bug #216861
192 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
193 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
194 self
.nb
.AddPage(panel
, "Overview")
196 def OnOvrSize(evt
, ovr
=self
.ovr
):
197 ovr
.SetSize(evt
.GetSize())
199 EVT_SIZE(panel
, OnOvrSize
)
200 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
203 self
.SetOverview("Overview", overview
)
206 # Set up a TextCtrl on the Demo Code Notebook page
207 self
.txt
= wxTextCtrl(self
.nb
, -1,
208 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
209 self
.txt
.SetFont(wxFont(9, wxMODERN
, wxNORMAL
, wxNORMAL
, false
))
210 self
.nb
.AddPage(self
.txt
, "Demo Code")
213 # Set up a log on the View Log Notebook page
214 self
.log
= wxTextCtrl(splitter2
, -1,
215 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
216 # Set the wxWindows log target to be this textctrl
217 wxLog_SetActiveTarget(wxLogTextCtrl(self
.log
))
223 # add the windows to the splitter and split it.
224 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
225 splitter2
.SetSashPosition(450, true
)
226 splitter2
.SetMinimumPaneSize(20)
228 splitter
.SplitVertically(self
.tree
, splitter2
)
229 splitter
.SetSashPosition(180, true
)
230 splitter
.SetMinimumPaneSize(20)
233 # select initial items
234 self
.nb
.SetSelection(0)
235 self
.tree
.SelectItem(root
)
237 if len(sys
.argv
) == 2:
239 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
243 self
.tree
.SelectItem(selectedDemo
)
244 self
.tree
.EnsureVisible(selectedDemo
)
247 wxLogMessage('window handle: %s' % self
.GetHandle())
250 #---------------------------------------------
251 def WriteText(self
, text
):
252 if text
[-1:] == '\n':
257 def write(self
, txt
):
260 #---------------------------------------------
261 def OnItemExpanded(self
, event
):
262 item
= event
.GetItem()
263 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
266 #---------------------------------------------
267 def OnItemCollapsed(self
, event
):
268 item
= event
.GetItem()
269 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
272 #---------------------------------------------
273 def OnTreeLeftDown(self
, event
):
274 pt
= event
.GetPosition();
275 item
, flags
= self
.tree
.HitTest(pt
)
276 if item
== self
.tree
.GetSelection():
277 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
280 #---------------------------------------------
281 def OnSelChanged(self
, event
):
285 item
= event
.GetItem()
286 itemText
= self
.tree
.GetItemText(item
)
287 self
.RunDemo(itemText
)
290 #---------------------------------------------
291 def RunDemo(self
, itemText
):
293 if self
.nb
.GetPageCount() == 3:
294 if self
.nb
.GetSelection() == 2:
295 self
.nb
.SetSelection(0)
296 self
.nb
.DeletePage(2)
298 if itemText
== 'Overview':
299 self
.GetDemoFile('Main.py')
300 self
.SetOverview('Overview', overview
)
305 if os
.path
.exists(itemText
+ '.py'):
307 wxLogMessage("Running demo %s.py..." % itemText
)
309 self
.GetDemoFile(itemText
+ '.py')
310 module
= __import__(itemText
, globals())
311 self
.SetOverview(itemText
, module
.overview
)
315 # in case runTest is modal, make sure things look right...
319 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
321 self
.nb
.AddPage(self
.window
, 'Demo')
323 self
.nb
.SetSelection(2)
332 #---------------------------------------------
334 def GetDemoFile(self
, filename
):
337 self
.txt
.SetValue(open(filename
).read())
339 self
.txt
.WriteText("Cannot open %s file." % filename
)
341 self
.txt
.SetInsertionPoint(0)
342 self
.txt
.ShowPosition(0)
344 #---------------------------------------------
345 def SetOverview(self
, name
, text
):
346 self
.curOverview
= text
348 if lead
!= '<html>' and lead
!= '<HTML>':
349 text
= string
.join(string
.split(text
, '\n'), '<br>')
350 #text = '<font size="-1"><pre>' + text + '</pre></font>'
351 self
.ovr
.SetPage(text
)
352 self
.nb
.SetPageText(0, name
)
354 #---------------------------------------------
356 def OnFileExit(self
, *event
):
360 def OnHelpAbout(self
, event
):
361 from About
import MyAboutBox
362 about
= MyAboutBox(self
)
367 #---------------------------------------------
368 def OnCloseWindow(self
, event
):
372 if hasattr(self
, "tbicon"):
377 #---------------------------------------------
378 def OnIdle(self
, event
):
380 self
.otherWin
.Raise()
381 self
.window
= self
.otherWin
384 #---------------------------------------------
385 def OnDemoMenu(self
, event
):
387 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
391 self
.tree
.SelectItem(selectedDemo
)
392 self
.tree
.EnsureVisible(selectedDemo
)
395 #---------------------------------------------
396 def OnTaskBarActivate(self
, evt
):
397 if self
.IsIconized():
399 if not self
.IsShown():
403 #---------------------------------------------
405 TBMENU_RESTORE
= 1000
408 def OnTaskBarMenu(self
, evt
):
410 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
411 menu
.Append(self
.TBMENU_CLOSE
, "Close")
412 self
.tbicon
.PopupMenu(menu
)
415 #---------------------------------------------
416 def OnTaskBarClose(self
, evt
):
419 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
420 # prod the main idle handler a bit to get the window to actually close
421 wxGetApp().ProcessIdle()
424 #---------------------------------------------
425 def OnIconfiy(self
, evt
):
426 wxLogMessage("OnIconfiy")
429 #---------------------------------------------
430 def OnMaximize(self
, evt
):
431 wxLogMessage("OnMaximize")
437 #---------------------------------------------------------------------------
438 #---------------------------------------------------------------------------
442 wxInitAllImageHandlers()
444 self
.splash
= SplashScreen(None, bitmapfile
='bitmaps/splash.gif',
445 duration
=4000, callback
=self
.AfterSplash
)
446 self
.splash
.Show(true
)
451 def AfterSplash(self
):
452 self
.splash
.Close(true
)
453 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
455 self
.SetTopWindow(frame
)
459 def ShowTip(self
, frame
):
461 showTipText
= open("data/showTips").read()
462 showTip
, index
= eval(showTipText
)
464 showTip
, index
= (1, 0)
465 #print showTip, index
467 tp
= wxCreateFileTipProvider("data/tips.txt", index
)
468 showTip
= wxShowTip(frame
, tp
)
469 index
= tp
.GetCurrentTip()
470 open("data/showTips", "w").write(str( (showTip
, index
) ))
473 #---------------------------------------------------------------------------
477 demoPath
= os
.path
.dirname(__file__
)
485 #---------------------------------------------------------------------------
489 overview
= """<html><body>
492 Python is an interpreted, interactive, object-oriented programming
493 language often compared to Tcl, Perl, Scheme, or Java.
495 <p> Python combines remarkable power with very clear syntax. It has
496 modules, classes, exceptions, very high level dynamic data types, and
497 dynamic typing. There are interfaces to many system calls and
498 libraries, and new built-in modules are easily written in C or
499 C++. Python is also usable as an extension language for applications
500 that need a programmable interface. <p>
504 wxWindows is a free C++ framework designed to make cross-platform
505 programming child's play. Well, almost. wxWindows 2 supports Windows
506 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
507 underway. Other ports are under consideration. <p>
509 wxWindows is a set of libraries that allows C++ applications to
510 compile and run on several different types of computers, with minimal
511 source code changes. There is one library per supported GUI (such as
512 Motif, or Windows). As well as providing a common API (Application
513 Programming Interface) for GUI functionality, it provides
514 functionality for accessing some commonly-used operating system
515 facilities, such as copying or deleting files. wxWindows is a
516 'framework' in the sense that it provides a lot of built-in
517 functionality, which the application can use or replace as required,
518 thus saving a great deal of coding effort. Basic data structures such
519 as strings, linked lists and hash tables are also supported.
524 wxPython is a Python extension module that encapsulates the wxWindows
525 GUI classes. Currently it is only available for the Win32 and GTK
526 ports of wxWindows, but as soon as the other ports are brought up to
527 the same level as Win32 and GTK, it should be fairly trivial to
528 enable wxPython to be used with the new GUI.
532 The wxPython extension module attempts to mirror the class heiarchy
533 of wxWindows as closely as possible. This means that there is a
534 wxFrame class in wxPython that looks, smells, tastes and acts almost
535 the same as the wxFrame class in the C++ version. Unfortunately,
536 because of differences in the languages, wxPython doesn't match
537 wxWindows exactly, but the differences should be easy to absorb
538 because they are natural to Python. For example, some methods that
539 return multiple values via argument pointers in C++ will return a
540 tuple of values in Python.
544 There is still much to be done for wxPython, many classes still need
545 to be mirrored. Also, wxWindows is still somewhat of a moving target
546 so it is a bit of an effort just keeping wxPython up to date. On the
547 other hand, there are enough of the core classes completed that
548 useful applications can be written.
552 wxPython is close enough to the C++ version that the majority of
553 the wxPython documentation is actually just notes attached to the C++
554 documents that describe the places where wxPython is different. There
555 is also a series of sample programs included, and a series of
556 documentation pages that assist the programmer in getting started
562 #----------------------------------------------------------------------------
563 #----------------------------------------------------------------------------
565 if __name__
== '__main__':
568 #----------------------------------------------------------------------------