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',
44 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
45 'wxGrid', 'wxSashWindow',
46 'wxScrolledWindow', 'wxSplitterWindow',
47 'wxStatusBar', 'wxNotebook',
49 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
51 'wxDynamicSashWindow',
54 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
55 'wxSingleChoiceDialog', 'wxTextEntryDialog',
56 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
57 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
60 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
61 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl',
62 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
63 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
64 'wxCalendarCtrl', 'wxToggleButton',
68 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
70 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
72 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
73 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
74 'PythonEvents', 'Threads',
75 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
76 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
77 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
81 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
82 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
83 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
84 'FileBrowseButton', 'GenericButtons', 'wxEditor',
85 'ColourSelect', 'ImageBrowser',
86 'infoframe', 'ColourDB', 'PyCrust', 'TablePrint',
90 ('Cool Contribs', ['pyTree', 'hangman',
97 #---------------------------------------------------------------------------
100 def __init__(self
, textCtrl
, logTime
=0):
101 wxPyLog
.__init
__(self
)
103 self
.logTime
= logTime
105 def DoLogString(self
, message
, timeStamp
):
107 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
109 self
.tc
.AppendText(message
+ '\n')
112 #---------------------------------------------------------------------------
114 class wxPythonDemo(wxFrame
):
116 def __init__(self
, parent
, id, title
):
117 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
118 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
120 self
.cwd
= os
.getcwd()
121 self
.curOverview
= ""
124 icon
= wxIconFromXPMData(images
.getMondrianData())
126 # another way to do it
127 bmp
= images
.getMondrianBitmap()
129 icon
.CopyFromBitmap(bmp
)
133 if wxPlatform
== '__WXMSW__':
134 # setup a taskbar icon, and catch some events from it
135 self
.tbicon
= wxTaskBarIcon()
136 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
137 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
138 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
139 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
140 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
144 EVT_IDLE(self
, self
.OnIdle
)
145 EVT_CLOSE(self
, self
.OnCloseWindow
)
146 EVT_ICONIZE(self
, self
.OnIconfiy
)
147 EVT_MAXIMIZE(self
, self
.OnMaximize
)
150 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
152 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
153 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
155 def EmptyHandler(evt
): pass
156 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
157 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
159 # Prevent TreeCtrl from displaying all items after destruction when true
163 self
.mainmenu
= wxMenuBar()
166 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
167 EVT_MENU(self
, exitID
, self
.OnFileExit
)
168 self
.mainmenu
.Append(menu
, '&File')
172 for item
in _treeList
:
174 for childItem
in item
[1]:
176 submenu
.Append(mID
, childItem
)
177 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
178 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
179 self
.mainmenu
.Append(menu
, '&Demo')
185 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
186 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
187 self
.mainmenu
.Append(menu
, '&Help')
188 self
.SetMenuBar(self
.mainmenu
)
190 # set the menu accellerator table...
191 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
192 (wxACCEL_CTRL
, ord('H'), helpID
)])
193 self
.SetAcceleratorTable(aTable
)
199 self
.tree
= wxTreeCtrl(splitter
, tID
,
200 style
=wxTR_HAS_BUTTONS |
202 wxTR_HAS_VARIABLE_ROW_HEIGHT |
204 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
205 root
= self
.tree
.AddRoot("Overview")
207 for item
in _treeList
:
208 child
= self
.tree
.AppendItem(root
, item
[0])
209 if not firstChild
: firstChild
= child
210 for childItem
in item
[1]:
211 theDemo
= self
.tree
.AppendItem(child
, childItem
)
212 self
.treeMap
[childItem
] = theDemo
214 self
.tree
.Expand(root
)
215 self
.tree
.Expand(firstChild
)
216 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
217 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
218 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
219 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
222 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
224 # Set up a wxHtmlWindow on the Overview Notebook page
225 # we put it in a panel first because there seems to be a
226 # refresh bug of some sort (wxGTK) when it is directly in
229 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
230 self
.nb
.AddPage(self
.ovr
, "Overview")
232 else: # hopefully I can remove this hacky code soon, see bug #216861
233 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
234 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
235 self
.nb
.AddPage(panel
, "Overview")
237 def OnOvrSize(evt
, ovr
=self
.ovr
):
238 ovr
.SetSize(evt
.GetSize())
240 EVT_SIZE(panel
, OnOvrSize
)
241 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
244 self
.SetOverview("Overview", overview
)
247 # Set up a TextCtrl on the Demo Code Notebook page
248 self
.txt
= wxTextCtrl(self
.nb
, -1,
249 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
250 self
.nb
.AddPage(self
.txt
, "Demo Code")
253 # Set up a log on the View Log Notebook page
254 self
.log
= wxTextCtrl(splitter2
, -1,
255 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
256 # Set the wxWindows log target to be this textctrl
257 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
258 wxLog_SetActiveTarget(MyLog(self
.log
))
264 # add the windows to the splitter and split it.
265 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
266 splitter2
.SetSashPosition(450, true
)
267 splitter2
.SetMinimumPaneSize(20)
269 splitter
.SplitVertically(self
.tree
, splitter2
)
270 splitter
.SetSashPosition(180, true
)
271 splitter
.SetMinimumPaneSize(20)
274 # select initial items
275 self
.nb
.SetSelection(0)
276 self
.tree
.SelectItem(root
)
278 if len(sys
.argv
) == 2:
280 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
284 self
.tree
.SelectItem(selectedDemo
)
285 self
.tree
.EnsureVisible(selectedDemo
)
288 wxLogMessage('window handle: %s' % self
.GetHandle())
291 #---------------------------------------------
292 def WriteText(self
, text
):
293 if text
[-1:] == '\n':
298 def write(self
, txt
):
301 #---------------------------------------------
302 def OnItemExpanded(self
, event
):
303 item
= event
.GetItem()
304 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
307 #---------------------------------------------
308 def OnItemCollapsed(self
, event
):
309 item
= event
.GetItem()
310 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
313 #---------------------------------------------
314 def OnTreeLeftDown(self
, event
):
315 pt
= event
.GetPosition();
316 item
, flags
= self
.tree
.HitTest(pt
)
317 if item
== self
.tree
.GetSelection():
318 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
321 #---------------------------------------------
322 def OnSelChanged(self
, event
):
326 item
= event
.GetItem()
327 itemText
= self
.tree
.GetItemText(item
)
328 self
.RunDemo(itemText
)
331 #---------------------------------------------
332 def RunDemo(self
, itemText
):
334 if self
.nb
.GetPageCount() == 3:
335 if self
.nb
.GetSelection() == 2:
336 self
.nb
.SetSelection(0)
337 self
.nb
.DeletePage(2)
339 if itemText
== 'Overview':
340 self
.GetDemoFile('Main.py')
341 self
.SetOverview('Overview', overview
)
346 if os
.path
.exists(itemText
+ '.py'):
348 wxLogMessage("Running demo %s.py..." % itemText
)
350 self
.GetDemoFile(itemText
+ '.py')
351 module
= __import__(itemText
, globals())
352 self
.SetOverview(itemText
, module
.overview
)
356 # in case runTest is modal, make sure things look right...
360 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
362 self
.nb
.AddPage(self
.window
, 'Demo')
364 self
.nb
.SetSelection(2)
373 #---------------------------------------------
375 def GetDemoFile(self
, filename
):
378 self
.txt
.SetValue(open(filename
).read())
380 self
.txt
.WriteText("Cannot open %s file." % filename
)
382 self
.txt
.SetInsertionPoint(0)
383 self
.txt
.ShowPosition(0)
385 #---------------------------------------------
386 def SetOverview(self
, name
, text
):
387 self
.curOverview
= text
389 if lead
!= '<html>' and lead
!= '<HTML>':
390 text
= string
.join(string
.split(text
, '\n'), '<br>')
391 #text = '<font size="-1"><pre>' + text + '</pre></font>'
392 self
.ovr
.SetPage(text
)
393 self
.nb
.SetPageText(0, name
)
395 #---------------------------------------------
397 def OnFileExit(self
, *event
):
401 def OnHelpAbout(self
, event
):
402 from About
import MyAboutBox
403 about
= MyAboutBox(self
)
408 #---------------------------------------------
409 def OnCloseWindow(self
, event
):
413 if hasattr(self
, "tbicon"):
418 #---------------------------------------------
419 def OnIdle(self
, event
):
421 self
.otherWin
.Raise()
422 self
.window
= self
.otherWin
425 #---------------------------------------------
426 def OnDemoMenu(self
, event
):
428 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
432 self
.tree
.SelectItem(selectedDemo
)
433 self
.tree
.EnsureVisible(selectedDemo
)
436 #---------------------------------------------
437 def OnTaskBarActivate(self
, evt
):
438 if self
.IsIconized():
440 if not self
.IsShown():
444 #---------------------------------------------
446 TBMENU_RESTORE
= 1000
449 def OnTaskBarMenu(self
, evt
):
451 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
452 menu
.Append(self
.TBMENU_CLOSE
, "Close")
453 self
.tbicon
.PopupMenu(menu
)
456 #---------------------------------------------
457 def OnTaskBarClose(self
, evt
):
460 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
461 # prod the main idle handler a bit to get the window to actually close
462 wxGetApp().ProcessIdle()
465 #---------------------------------------------
466 def OnIconfiy(self
, evt
):
467 wxLogMessage("OnIconfiy")
470 #---------------------------------------------
471 def OnMaximize(self
, evt
):
472 wxLogMessage("OnMaximize")
478 #---------------------------------------------------------------------------
479 #---------------------------------------------------------------------------
483 wxInitAllImageHandlers()
485 self
.splash
= SplashScreen(None, bitmapfile
='bitmaps/splash.gif',
486 duration
=4000, callback
=self
.AfterSplash
)
487 self
.splash
.Show(true
)
492 def AfterSplash(self
):
493 self
.splash
.Close(true
)
494 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
496 self
.SetTopWindow(frame
)
500 def ShowTip(self
, frame
):
502 showTipText
= open("data/showTips").read()
503 showTip
, index
= eval(showTipText
)
505 showTip
, index
= (1, 0)
506 #print showTip, index
508 tp
= wxCreateFileTipProvider("data/tips.txt", index
)
509 showTip
= wxShowTip(frame
, tp
)
510 index
= tp
.GetCurrentTip()
511 open("data/showTips", "w").write(str( (showTip
, index
) ))
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 #----------------------------------------------------------------------------