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',
32 'wxFindReplaceDialog',
41 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
42 'wxGrid', 'wxSashWindow',
43 'wxScrolledWindow', 'wxSplitterWindow',
44 'wxStatusBar', 'wxNotebook',
46 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
50 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
51 'wxSingleChoiceDialog', 'wxTextEntryDialog',
52 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
53 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
56 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
57 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl',
58 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
59 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
60 'wxCalendarCtrl', 'wxToggleButton',
63 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
65 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
67 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
68 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
69 'PythonEvents', 'Threads',
70 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
71 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
72 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
75 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
76 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
77 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
78 'FileBrowseButton', 'GenericButtons', 'wxEditor',
79 'ColourSelect', 'ImageBrowser',
80 'infoframe', 'ColourDB', 'PyCrust', 'TablePrint',
84 ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']),
88 #---------------------------------------------------------------------------
91 def __init__(self
, textCtrl
, logTime
=0):
92 wxPyLog
.__init
__(self
)
94 self
.logTime
= logTime
96 def DoLogString(self
, message
, timeStamp
):
98 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
100 self
.tc
.AppendText(message
+ '\n')
103 #---------------------------------------------------------------------------
105 class wxPythonDemo(wxFrame
):
107 def __init__(self
, parent
, id, title
):
108 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
109 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
111 self
.cwd
= os
.getcwd()
112 self
.curOverview
= ""
115 icon
= wxIconFromXPMData(images
.getMondrianData())
117 # another way to do it
118 bmp
= images
.getMondrianBitmap()
120 icon
.CopyFromBitmap(bmp
)
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
)
135 EVT_IDLE(self
, self
.OnIdle
)
136 EVT_CLOSE(self
, self
.OnCloseWindow
)
137 EVT_ICONIZE(self
, self
.OnIconfiy
)
138 EVT_MAXIMIZE(self
, self
.OnMaximize
)
141 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
143 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
144 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
146 def EmptyHandler(evt
): pass
147 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
148 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
150 # Prevent TreeCtrl from displaying all items after destruction when true
154 self
.mainmenu
= wxMenuBar()
157 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
158 EVT_MENU(self
, exitID
, self
.OnFileExit
)
159 self
.mainmenu
.Append(menu
, '&File')
163 for item
in _treeList
:
165 for childItem
in item
[1]:
167 submenu
.Append(mID
, childItem
)
168 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
169 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
170 self
.mainmenu
.Append(menu
, '&Demo')
176 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
177 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
178 self
.mainmenu
.Append(menu
, '&Help')
179 self
.SetMenuBar(self
.mainmenu
)
181 # set the menu accellerator table...
182 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
183 (wxACCEL_CTRL
, ord('H'), helpID
)])
184 self
.SetAcceleratorTable(aTable
)
190 self
.tree
= wxTreeCtrl(splitter
, tID
,
191 style
=wxTR_HAS_BUTTONS |
193 wxTR_HAS_VARIABLE_ROW_HEIGHT |
195 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
196 root
= self
.tree
.AddRoot("Overview")
198 for item
in _treeList
:
199 child
= self
.tree
.AppendItem(root
, item
[0])
200 if not firstChild
: firstChild
= child
201 for childItem
in item
[1]:
202 theDemo
= self
.tree
.AppendItem(child
, childItem
)
203 self
.treeMap
[childItem
] = theDemo
205 self
.tree
.Expand(root
)
206 self
.tree
.Expand(firstChild
)
207 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
208 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
209 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
210 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
213 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
215 # Set up a wxHtmlWindow on the Overview Notebook page
216 # we put it in a panel first because there seems to be a
217 # refresh bug of some sort (wxGTK) when it is directly in
220 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
221 self
.nb
.AddPage(self
.ovr
, "Overview")
223 else: # hopefully I can remove this hacky code soon, see bug #216861
224 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
225 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
226 self
.nb
.AddPage(panel
, "Overview")
228 def OnOvrSize(evt
, ovr
=self
.ovr
):
229 ovr
.SetSize(evt
.GetSize())
231 EVT_SIZE(panel
, OnOvrSize
)
232 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
235 self
.SetOverview("Overview", overview
)
238 # Set up a TextCtrl on the Demo Code Notebook page
239 self
.txt
= wxTextCtrl(self
.nb
, -1,
240 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
241 self
.nb
.AddPage(self
.txt
, "Demo Code")
244 # Set up a log on the View Log Notebook page
245 self
.log
= wxTextCtrl(splitter2
, -1,
246 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
247 # Set the wxWindows log target to be this textctrl
248 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
249 wxLog_SetActiveTarget(MyLog(self
.log
))
255 # add the windows to the splitter and split it.
256 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
257 splitter2
.SetSashPosition(450, true
)
258 splitter2
.SetMinimumPaneSize(20)
260 splitter
.SplitVertically(self
.tree
, splitter2
)
261 splitter
.SetSashPosition(180, true
)
262 splitter
.SetMinimumPaneSize(20)
265 # select initial items
266 self
.nb
.SetSelection(0)
267 self
.tree
.SelectItem(root
)
269 if len(sys
.argv
) == 2:
271 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
275 self
.tree
.SelectItem(selectedDemo
)
276 self
.tree
.EnsureVisible(selectedDemo
)
279 wxLogMessage('window handle: %s' % self
.GetHandle())
282 #---------------------------------------------
283 def WriteText(self
, text
):
284 if text
[-1:] == '\n':
289 def write(self
, txt
):
292 #---------------------------------------------
293 def OnItemExpanded(self
, event
):
294 item
= event
.GetItem()
295 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
298 #---------------------------------------------
299 def OnItemCollapsed(self
, event
):
300 item
= event
.GetItem()
301 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
304 #---------------------------------------------
305 def OnTreeLeftDown(self
, event
):
306 pt
= event
.GetPosition();
307 item
, flags
= self
.tree
.HitTest(pt
)
308 if item
== self
.tree
.GetSelection():
309 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
312 #---------------------------------------------
313 def OnSelChanged(self
, event
):
317 item
= event
.GetItem()
318 itemText
= self
.tree
.GetItemText(item
)
319 self
.RunDemo(itemText
)
322 #---------------------------------------------
323 def RunDemo(self
, itemText
):
325 if self
.nb
.GetPageCount() == 3:
326 if self
.nb
.GetSelection() == 2:
327 self
.nb
.SetSelection(0)
328 self
.nb
.DeletePage(2)
330 if itemText
== 'Overview':
331 self
.GetDemoFile('Main.py')
332 self
.SetOverview('Overview', overview
)
337 if os
.path
.exists(itemText
+ '.py'):
339 wxLogMessage("Running demo %s.py..." % itemText
)
341 self
.GetDemoFile(itemText
+ '.py')
342 module
= __import__(itemText
, globals())
343 self
.SetOverview(itemText
, module
.overview
)
347 # in case runTest is modal, make sure things look right...
351 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
353 self
.nb
.AddPage(self
.window
, 'Demo')
355 self
.nb
.SetSelection(2)
364 #---------------------------------------------
366 def GetDemoFile(self
, filename
):
369 self
.txt
.SetValue(open(filename
).read())
371 self
.txt
.WriteText("Cannot open %s file." % filename
)
373 self
.txt
.SetInsertionPoint(0)
374 self
.txt
.ShowPosition(0)
376 #---------------------------------------------
377 def SetOverview(self
, name
, text
):
378 self
.curOverview
= text
380 if lead
!= '<html>' and lead
!= '<HTML>':
381 text
= string
.join(string
.split(text
, '\n'), '<br>')
382 #text = '<font size="-1"><pre>' + text + '</pre></font>'
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 #---------------------------------------------------------------------------
474 wxInitAllImageHandlers()
476 self
.splash
= SplashScreen(None, bitmapfile
='bitmaps/splash.gif',
477 duration
=4000, callback
=self
.AfterSplash
)
478 self
.splash
.Show(true
)
483 def AfterSplash(self
):
484 self
.splash
.Close(true
)
485 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
487 self
.SetTopWindow(frame
)
491 def ShowTip(self
, frame
):
493 showTipText
= open("data/showTips").read()
494 showTip
, index
= eval(showTipText
)
496 showTip
, index
= (1, 0)
497 #print showTip, index
499 tp
= wxCreateFileTipProvider("data/tips.txt", index
)
500 showTip
= wxShowTip(frame
, tp
)
501 index
= tp
.GetCurrentTip()
502 open("data/showTips", "w").write(str( (showTip
, index
) ))
505 #---------------------------------------------------------------------------
509 demoPath
= os
.path
.dirname(__file__
)
517 #---------------------------------------------------------------------------
521 overview
= """<html><body>
524 Python is an interpreted, interactive, object-oriented programming
525 language often compared to Tcl, Perl, Scheme, or Java.
527 <p> Python combines remarkable power with very clear syntax. It has
528 modules, classes, exceptions, very high level dynamic data types, and
529 dynamic typing. There are interfaces to many system calls and
530 libraries, and new built-in modules are easily written in C or
531 C++. Python is also usable as an extension language for applications
532 that need a programmable interface. <p>
536 wxWindows is a free C++ framework designed to make cross-platform
537 programming child's play. Well, almost. wxWindows 2 supports Windows
538 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
539 underway. Other ports are under consideration. <p>
541 wxWindows is a set of libraries that allows C++ applications to
542 compile and run on several different types of computers, with minimal
543 source code changes. There is one library per supported GUI (such as
544 Motif, or Windows). As well as providing a common API (Application
545 Programming Interface) for GUI functionality, it provides
546 functionality for accessing some commonly-used operating system
547 facilities, such as copying or deleting files. wxWindows is a
548 'framework' in the sense that it provides a lot of built-in
549 functionality, which the application can use or replace as required,
550 thus saving a great deal of coding effort. Basic data structures such
551 as strings, linked lists and hash tables are also supported.
556 wxPython is a Python extension module that encapsulates the wxWindows
557 GUI classes. Currently it is only available for the Win32 and GTK
558 ports of wxWindows, but as soon as the other ports are brought up to
559 the same level as Win32 and GTK, it should be fairly trivial to
560 enable wxPython to be used with the new GUI.
564 The wxPython extension module attempts to mirror the class heiarchy
565 of wxWindows as closely as possible. This means that there is a
566 wxFrame class in wxPython that looks, smells, tastes and acts almost
567 the same as the wxFrame class in the C++ version. Unfortunately,
568 because of differences in the languages, wxPython doesn't match
569 wxWindows exactly, but the differences should be easy to absorb
570 because they are natural to Python. For example, some methods that
571 return multiple values via argument pointers in C++ will return a
572 tuple of values in Python.
576 There is still much to be done for wxPython, many classes still need
577 to be mirrored. Also, wxWindows is still somewhat of a moving target
578 so it is a bit of an effort just keeping wxPython up to date. On the
579 other hand, there are enough of the core classes completed that
580 useful applications can be written.
584 wxPython is close enough to the C++ version that the majority of
585 the wxPython documentation is actually just notes attached to the C++
586 documents that describe the places where wxPython is different. There
587 is also a series of sample programs included, and a series of
588 documentation pages that assist the programmer in getting started
594 #----------------------------------------------------------------------------
595 #----------------------------------------------------------------------------
597 if __name__
== '__main__':
600 #----------------------------------------------------------------------------