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',
39 'wxDynamicSashWindow',
43 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
44 'wxGrid', 'wxSashWindow',
45 'wxScrolledWindow', 'wxSplitterWindow',
46 'wxStatusBar', 'wxNotebook',
48 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
50 'wxDynamicSashWindow',
53 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
54 'wxSingleChoiceDialog', 'wxTextEntryDialog',
55 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
56 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
59 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
60 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl',
61 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
62 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
63 'wxCalendarCtrl', 'wxToggleButton',
67 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
69 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
71 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
72 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
73 'PythonEvents', 'Threads',
74 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
75 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
76 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
79 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
80 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
81 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
82 'FileBrowseButton', 'GenericButtons', 'wxEditor',
83 'ColourSelect', 'ImageBrowser',
84 'infoframe', 'ColourDB', 'PyCrust', 'TablePrint',
88 ('Cool Contribs', ['pyTree', 'hangman',
95 #---------------------------------------------------------------------------
98 def __init__(self
, textCtrl
, logTime
=0):
99 wxPyLog
.__init
__(self
)
101 self
.logTime
= logTime
103 def DoLogString(self
, message
, timeStamp
):
105 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
107 self
.tc
.AppendText(message
+ '\n')
110 #---------------------------------------------------------------------------
112 class wxPythonDemo(wxFrame
):
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
= ""
122 icon
= wxIconFromXPMData(images
.getMondrianData())
124 # another way to do it
125 bmp
= images
.getMondrianBitmap()
127 icon
.CopyFromBitmap(bmp
)
131 if wxPlatform
== '__WXMSW__':
132 # setup a taskbar icon, and catch some events from it
133 self
.tbicon
= wxTaskBarIcon()
134 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
135 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
136 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
137 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
138 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
142 EVT_IDLE(self
, self
.OnIdle
)
143 EVT_CLOSE(self
, self
.OnCloseWindow
)
144 EVT_ICONIZE(self
, self
.OnIconfiy
)
145 EVT_MAXIMIZE(self
, self
.OnMaximize
)
148 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
150 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
151 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
153 def EmptyHandler(evt
): pass
154 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
155 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
157 # Prevent TreeCtrl from displaying all items after destruction when true
161 self
.mainmenu
= wxMenuBar()
164 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
165 EVT_MENU(self
, exitID
, self
.OnFileExit
)
166 self
.mainmenu
.Append(menu
, '&File')
170 for item
in _treeList
:
172 for childItem
in item
[1]:
174 submenu
.Append(mID
, childItem
)
175 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
176 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
177 self
.mainmenu
.Append(menu
, '&Demo')
183 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
184 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
185 self
.mainmenu
.Append(menu
, '&Help')
186 self
.SetMenuBar(self
.mainmenu
)
188 # set the menu accellerator table...
189 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
190 (wxACCEL_CTRL
, ord('H'), helpID
)])
191 self
.SetAcceleratorTable(aTable
)
197 self
.tree
= wxTreeCtrl(splitter
, tID
,
198 style
=wxTR_HAS_BUTTONS |
200 wxTR_HAS_VARIABLE_ROW_HEIGHT |
202 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
203 root
= self
.tree
.AddRoot("Overview")
205 for item
in _treeList
:
206 child
= self
.tree
.AppendItem(root
, item
[0])
207 if not firstChild
: firstChild
= child
208 for childItem
in item
[1]:
209 theDemo
= self
.tree
.AppendItem(child
, childItem
)
210 self
.treeMap
[childItem
] = theDemo
212 self
.tree
.Expand(root
)
213 self
.tree
.Expand(firstChild
)
214 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
215 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
216 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
217 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
220 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
222 # Set up a wxHtmlWindow on the Overview Notebook page
223 # we put it in a panel first because there seems to be a
224 # refresh bug of some sort (wxGTK) when it is directly in
227 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
228 self
.nb
.AddPage(self
.ovr
, "Overview")
230 else: # hopefully I can remove this hacky code soon, see bug #216861
231 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
232 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
233 self
.nb
.AddPage(panel
, "Overview")
235 def OnOvrSize(evt
, ovr
=self
.ovr
):
236 ovr
.SetSize(evt
.GetSize())
238 EVT_SIZE(panel
, OnOvrSize
)
239 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
242 self
.SetOverview("Overview", overview
)
245 # Set up a TextCtrl on the Demo Code Notebook page
246 self
.txt
= wxTextCtrl(self
.nb
, -1,
247 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
248 self
.nb
.AddPage(self
.txt
, "Demo Code")
251 # Set up a log on the View Log Notebook page
252 self
.log
= wxTextCtrl(splitter2
, -1,
253 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
254 # Set the wxWindows log target to be this textctrl
255 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
256 wxLog_SetActiveTarget(MyLog(self
.log
))
262 # add the windows to the splitter and split it.
263 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
264 splitter2
.SetSashPosition(450, true
)
265 splitter2
.SetMinimumPaneSize(20)
267 splitter
.SplitVertically(self
.tree
, splitter2
)
268 splitter
.SetSashPosition(180, true
)
269 splitter
.SetMinimumPaneSize(20)
272 # select initial items
273 self
.nb
.SetSelection(0)
274 self
.tree
.SelectItem(root
)
276 if len(sys
.argv
) == 2:
278 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
282 self
.tree
.SelectItem(selectedDemo
)
283 self
.tree
.EnsureVisible(selectedDemo
)
286 wxLogMessage('window handle: %s' % self
.GetHandle())
289 #---------------------------------------------
290 def WriteText(self
, text
):
291 if text
[-1:] == '\n':
296 def write(self
, txt
):
299 #---------------------------------------------
300 def OnItemExpanded(self
, event
):
301 item
= event
.GetItem()
302 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
305 #---------------------------------------------
306 def OnItemCollapsed(self
, event
):
307 item
= event
.GetItem()
308 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
311 #---------------------------------------------
312 def OnTreeLeftDown(self
, event
):
313 pt
= event
.GetPosition();
314 item
, flags
= self
.tree
.HitTest(pt
)
315 if item
== self
.tree
.GetSelection():
316 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
319 #---------------------------------------------
320 def OnSelChanged(self
, event
):
324 item
= event
.GetItem()
325 itemText
= self
.tree
.GetItemText(item
)
326 self
.RunDemo(itemText
)
329 #---------------------------------------------
330 def RunDemo(self
, itemText
):
332 if self
.nb
.GetPageCount() == 3:
333 if self
.nb
.GetSelection() == 2:
334 self
.nb
.SetSelection(0)
335 self
.nb
.DeletePage(2)
337 if itemText
== 'Overview':
338 self
.GetDemoFile('Main.py')
339 self
.SetOverview('Overview', overview
)
344 if os
.path
.exists(itemText
+ '.py'):
346 wxLogMessage("Running demo %s.py..." % itemText
)
348 self
.GetDemoFile(itemText
+ '.py')
349 module
= __import__(itemText
, globals())
350 self
.SetOverview(itemText
, module
.overview
)
354 # in case runTest is modal, make sure things look right...
358 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
360 self
.nb
.AddPage(self
.window
, 'Demo')
362 self
.nb
.SetSelection(2)
371 #---------------------------------------------
373 def GetDemoFile(self
, filename
):
376 self
.txt
.SetValue(open(filename
).read())
378 self
.txt
.WriteText("Cannot open %s file." % filename
)
380 self
.txt
.SetInsertionPoint(0)
381 self
.txt
.ShowPosition(0)
383 #---------------------------------------------
384 def SetOverview(self
, name
, text
):
385 self
.curOverview
= text
387 if lead
!= '<html>' and lead
!= '<HTML>':
388 text
= string
.join(string
.split(text
, '\n'), '<br>')
389 #text = '<font size="-1"><pre>' + text + '</pre></font>'
390 self
.ovr
.SetPage(text
)
391 self
.nb
.SetPageText(0, name
)
393 #---------------------------------------------
395 def OnFileExit(self
, *event
):
399 def OnHelpAbout(self
, event
):
400 from About
import MyAboutBox
401 about
= MyAboutBox(self
)
406 #---------------------------------------------
407 def OnCloseWindow(self
, event
):
411 if hasattr(self
, "tbicon"):
416 #---------------------------------------------
417 def OnIdle(self
, event
):
419 self
.otherWin
.Raise()
420 self
.window
= self
.otherWin
423 #---------------------------------------------
424 def OnDemoMenu(self
, event
):
426 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
430 self
.tree
.SelectItem(selectedDemo
)
431 self
.tree
.EnsureVisible(selectedDemo
)
434 #---------------------------------------------
435 def OnTaskBarActivate(self
, evt
):
436 if self
.IsIconized():
438 if not self
.IsShown():
442 #---------------------------------------------
444 TBMENU_RESTORE
= 1000
447 def OnTaskBarMenu(self
, evt
):
449 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
450 menu
.Append(self
.TBMENU_CLOSE
, "Close")
451 self
.tbicon
.PopupMenu(menu
)
454 #---------------------------------------------
455 def OnTaskBarClose(self
, evt
):
458 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
459 # prod the main idle handler a bit to get the window to actually close
460 wxGetApp().ProcessIdle()
463 #---------------------------------------------
464 def OnIconfiy(self
, evt
):
465 wxLogMessage("OnIconfiy")
468 #---------------------------------------------
469 def OnMaximize(self
, evt
):
470 wxLogMessage("OnMaximize")
476 #---------------------------------------------------------------------------
477 #---------------------------------------------------------------------------
481 wxInitAllImageHandlers()
483 self
.splash
= SplashScreen(None, bitmapfile
='bitmaps/splash.gif',
484 duration
=4000, callback
=self
.AfterSplash
)
485 self
.splash
.Show(true
)
490 def AfterSplash(self
):
491 self
.splash
.Close(true
)
492 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
494 self
.SetTopWindow(frame
)
498 def ShowTip(self
, frame
):
500 showTipText
= open("data/showTips").read()
501 showTip
, index
= eval(showTipText
)
503 showTip
, index
= (1, 0)
504 #print showTip, index
506 tp
= wxCreateFileTipProvider("data/tips.txt", index
)
507 showTip
= wxShowTip(frame
, tp
)
508 index
= tp
.GetCurrentTip()
509 open("data/showTips", "w").write(str( (showTip
, index
) ))
512 #---------------------------------------------------------------------------
516 demoPath
= os
.path
.dirname(__file__
)
524 #---------------------------------------------------------------------------
528 overview
= """<html><body>
531 Python is an interpreted, interactive, object-oriented programming
532 language often compared to Tcl, Perl, Scheme, or Java.
534 <p> Python combines remarkable power with very clear syntax. It has
535 modules, classes, exceptions, very high level dynamic data types, and
536 dynamic typing. There are interfaces to many system calls and
537 libraries, and new built-in modules are easily written in C or
538 C++. Python is also usable as an extension language for applications
539 that need a programmable interface. <p>
543 wxWindows is a free C++ framework designed to make cross-platform
544 programming child's play. Well, almost. wxWindows 2 supports Windows
545 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
546 underway. Other ports are under consideration. <p>
548 wxWindows is a set of libraries that allows C++ applications to
549 compile and run on several different types of computers, with minimal
550 source code changes. There is one library per supported GUI (such as
551 Motif, or Windows). As well as providing a common API (Application
552 Programming Interface) for GUI functionality, it provides
553 functionality for accessing some commonly-used operating system
554 facilities, such as copying or deleting files. wxWindows is a
555 'framework' in the sense that it provides a lot of built-in
556 functionality, which the application can use or replace as required,
557 thus saving a great deal of coding effort. Basic data structures such
558 as strings, linked lists and hash tables are also supported.
563 wxPython is a Python extension module that encapsulates the wxWindows
564 GUI classes. Currently it is only available for the Win32 and GTK
565 ports of wxWindows, but as soon as the other ports are brought up to
566 the same level as Win32 and GTK, it should be fairly trivial to
567 enable wxPython to be used with the new GUI.
571 The wxPython extension module attempts to mirror the class heiarchy
572 of wxWindows as closely as possible. This means that there is a
573 wxFrame class in wxPython that looks, smells, tastes and acts almost
574 the same as the wxFrame class in the C++ version. Unfortunately,
575 because of differences in the languages, wxPython doesn't match
576 wxWindows exactly, but the differences should be easy to absorb
577 because they are natural to Python. For example, some methods that
578 return multiple values via argument pointers in C++ will return a
579 tuple of values in Python.
583 There is still much to be done for wxPython, many classes still need
584 to be mirrored. Also, wxWindows is still somewhat of a moving target
585 so it is a bit of an effort just keeping wxPython up to date. On the
586 other hand, there are enough of the core classes completed that
587 useful applications can be written.
591 wxPython is close enough to the C++ version that the majority of
592 the wxPython documentation is actually just notes attached to the C++
593 documents that describe the places where wxPython is different. There
594 is also a series of sample programs included, and a series of
595 documentation pages that assist the programmer in getting started
601 #----------------------------------------------------------------------------
602 #----------------------------------------------------------------------------
604 if __name__
== '__main__':
607 #----------------------------------------------------------------------------