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 #----------------------------------------------------------------------------
14 import sys
, os
, time
, string
15 from wxPython
.wx
import *
16 from wxPython
.html
import wxHtmlWindow
20 #---------------------------------------------------------------------------
24 ('New since last release', ['wxGenericDirCtrl',
29 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
30 'wxGrid', 'wxSashWindow',
31 'wxScrolledWindow', 'wxSplitterWindow',
32 'wxStatusBar', 'wxNotebook',
34 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
36 'wxDynamicSashWindow',
39 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
40 'wxSingleChoiceDialog', 'wxTextEntryDialog',
41 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
42 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
45 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
46 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'VirtualListCtrl',
48 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
49 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
50 'wxCalendarCtrl', 'wxToggleButton',
51 'wxEditableListBox', 'wxLEDNumberCtrl',
54 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource',
58 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
60 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
61 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
62 'PythonEvents', 'Threads',
63 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
64 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
65 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
66 'ContextHelp', 'SplitTree',
69 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
70 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
71 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
72 'FileBrowseButton', 'GenericButtons', 'wxEditor',
73 'ColourSelect', 'ImageBrowser',
74 'infoframe', 'ColourDB', 'PyCrust', 'PyCrustWithFilling',
79 ('Cool Contribs', ['pyTree', 'hangman',
86 #---------------------------------------------------------------------------
89 def __init__(self
, textCtrl
, logTime
=0):
90 wxPyLog
.__init
__(self
)
92 self
.logTime
= logTime
94 def DoLogString(self
, message
, timeStamp
):
96 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
98 self
.tc
.AppendText(message
+ '\n')
101 #---------------------------------------------------------------------------
104 """Convert paths to the platform-specific separator"""
105 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
108 #---------------------------------------------------------------------------
110 class wxPythonDemo(wxFrame
):
112 def __init__(self
, parent
, id, title
):
113 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
114 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
116 self
.cwd
= os
.getcwd()
117 self
.curOverview
= ""
119 icon
= images
.getMondrianIcon()
122 if wxPlatform
== '__WXMSW__':
123 # setup a taskbar icon, and catch some events from it
124 self
.tbicon
= wxTaskBarIcon()
125 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
126 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
127 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
128 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
129 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
133 EVT_IDLE(self
, self
.OnIdle
)
134 EVT_CLOSE(self
, self
.OnCloseWindow
)
135 EVT_ICONIZE(self
, self
.OnIconfiy
)
136 EVT_MAXIMIZE(self
, self
.OnMaximize
)
139 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
141 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
142 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
144 def EmptyHandler(evt
): pass
145 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
146 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
148 # Prevent TreeCtrl from displaying all items after destruction when true
152 self
.mainmenu
= wxMenuBar()
155 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
156 EVT_MENU(self
, exitID
, self
.OnFileExit
)
157 self
.mainmenu
.Append(menu
, '&File')
161 for item
in _treeList
:
163 for childItem
in item
[1]:
165 submenu
.Append(mID
, childItem
)
166 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
167 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
168 self
.mainmenu
.Append(menu
, '&Demo')
174 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
175 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
176 self
.mainmenu
.Append(menu
, '&Help')
177 self
.SetMenuBar(self
.mainmenu
)
179 # set the menu accellerator table...
180 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
181 (wxACCEL_CTRL
, ord('H'), helpID
)])
182 self
.SetAcceleratorTable(aTable
)
188 self
.tree
= wxTreeCtrl(splitter
, tID
,
189 style
=wxTR_HAS_BUTTONS |
191 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
193 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
194 root
= self
.tree
.AddRoot("Overview")
196 for item
in _treeList
:
197 child
= self
.tree
.AppendItem(root
, item
[0])
198 if not firstChild
: firstChild
= child
199 for childItem
in item
[1]:
200 theDemo
= self
.tree
.AppendItem(child
, childItem
)
201 self
.treeMap
[childItem
] = theDemo
203 self
.tree
.Expand(root
)
204 self
.tree
.Expand(firstChild
)
205 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
206 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
207 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
208 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
211 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
213 # Set up a wxHtmlWindow on the Overview Notebook page
214 # we put it in a panel first because there seems to be a
215 # refresh bug of some sort (wxGTK) when it is directly in
218 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
219 self
.nb
.AddPage(self
.ovr
, "Overview")
221 else: # hopefully I can remove this hacky code soon, see bug #216861
222 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
223 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
224 self
.nb
.AddPage(panel
, "Overview")
226 def OnOvrSize(evt
, ovr
=self
.ovr
):
227 ovr
.SetSize(evt
.GetSize())
229 EVT_SIZE(panel
, OnOvrSize
)
230 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
233 self
.SetOverview("Overview", overview
)
236 # Set up a TextCtrl on the Demo Code Notebook page
237 self
.txt
= wxTextCtrl(self
.nb
, -1,
238 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
239 self
.nb
.AddPage(self
.txt
, "Demo Code")
242 # Set up a log on the View Log Notebook page
243 self
.log
= wxTextCtrl(splitter2
, -1,
244 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
245 # Set the wxWindows log target to be this textctrl
246 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
247 wxLog_SetActiveTarget(MyLog(self
.log
))
253 # add the windows to the splitter and split it.
254 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
255 splitter
.SplitVertically(self
.tree
, splitter2
)
257 splitter
.SetSashPosition(180, true
)
258 splitter
.SetMinimumPaneSize(20)
259 splitter2
.SetSashPosition(450, true
)
260 splitter2
.SetMinimumPaneSize(20)
264 # select initial items
265 self
.nb
.SetSelection(0)
266 self
.tree
.SelectItem(root
)
268 if len(sys
.argv
) == 2:
270 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
274 self
.tree
.SelectItem(selectedDemo
)
275 self
.tree
.EnsureVisible(selectedDemo
)
278 wxLogMessage('window handle: %s' % self
.GetHandle())
281 #---------------------------------------------
282 def WriteText(self
, text
):
283 if text
[-1:] == '\n':
288 def write(self
, txt
):
291 #---------------------------------------------
292 def OnItemExpanded(self
, event
):
293 item
= event
.GetItem()
294 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
297 #---------------------------------------------
298 def OnItemCollapsed(self
, event
):
299 item
= event
.GetItem()
300 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
303 #---------------------------------------------
304 def OnTreeLeftDown(self
, event
):
305 pt
= event
.GetPosition();
306 item
, flags
= self
.tree
.HitTest(pt
)
307 if item
== self
.tree
.GetSelection():
308 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
311 #---------------------------------------------
312 def OnSelChanged(self
, event
):
316 item
= event
.GetItem()
317 itemText
= self
.tree
.GetItemText(item
)
318 self
.RunDemo(itemText
)
321 #---------------------------------------------
322 def RunDemo(self
, itemText
):
324 if self
.nb
.GetPageCount() == 3:
325 if self
.nb
.GetSelection() == 2:
326 self
.nb
.SetSelection(0)
327 self
.nb
.DeletePage(2)
329 if itemText
== 'Overview':
330 self
.GetDemoFile('Main.py')
331 self
.SetOverview('Overview', overview
)
336 if os
.path
.exists(itemText
+ '.py'):
338 wxLogMessage("Running demo %s.py..." % itemText
)
340 self
.GetDemoFile(itemText
+ '.py')
341 module
= __import__(itemText
, globals())
342 self
.SetOverview(itemText
, module
.overview
)
346 # in case runTest is modal, make sure things look right...
350 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
352 self
.nb
.AddPage(self
.window
, 'Demo')
354 self
.nb
.SetSelection(2)
363 #---------------------------------------------
365 def GetDemoFile(self
, filename
):
368 self
.txt
.SetValue(open(filename
).read())
370 self
.txt
.WriteText("Cannot open %s file." % filename
)
372 self
.txt
.SetInsertionPoint(0)
373 self
.txt
.ShowPosition(0)
375 #---------------------------------------------
376 def SetOverview(self
, name
, text
):
377 self
.curOverview
= text
379 if lead
!= '<html>' and lead
!= '<HTML>':
380 text
= string
.join(string
.split(text
, '\n'), '<br>')
381 self
.ovr
.SetPage(text
)
382 self
.nb
.SetPageText(0, name
)
384 #---------------------------------------------
386 def OnFileExit(self
, *event
):
390 def OnHelpAbout(self
, event
):
391 from About
import MyAboutBox
392 about
= MyAboutBox(self
)
397 #---------------------------------------------
398 def OnCloseWindow(self
, event
):
402 if hasattr(self
, "tbicon"):
407 #---------------------------------------------
408 def OnIdle(self
, event
):
410 self
.otherWin
.Raise()
411 self
.window
= self
.otherWin
414 #---------------------------------------------
415 def OnDemoMenu(self
, event
):
417 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
421 self
.tree
.SelectItem(selectedDemo
)
422 self
.tree
.EnsureVisible(selectedDemo
)
425 #---------------------------------------------
426 def OnTaskBarActivate(self
, evt
):
427 if self
.IsIconized():
429 if not self
.IsShown():
433 #---------------------------------------------
435 TBMENU_RESTORE
= 1000
438 def OnTaskBarMenu(self
, evt
):
440 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
441 menu
.Append(self
.TBMENU_CLOSE
, "Close")
442 self
.tbicon
.PopupMenu(menu
)
445 #---------------------------------------------
446 def OnTaskBarClose(self
, evt
):
449 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
450 # prod the main idle handler a bit to get the window to actually close
451 wxGetApp().ProcessIdle()
454 #---------------------------------------------
455 def OnIconfiy(self
, evt
):
456 wxLogMessage("OnIconfiy")
459 #---------------------------------------------
460 def OnMaximize(self
, evt
):
461 wxLogMessage("OnMaximize")
467 #---------------------------------------------------------------------------
468 #---------------------------------------------------------------------------
470 class MySplashScreen(wxSplashScreen
):
472 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
473 wxSplashScreen
.__init
__(self
, bmp
,
474 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
476 EVT_CLOSE(self
, self
.OnClose
)
478 def OnClose(self
, evt
):
479 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
484 def ShowTip(self
, frame
):
486 showTipText
= open(opj("data/showTips")).read()
487 showTip
, index
= eval(showTipText
)
489 showTip
, index
= (1, 0)
491 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
492 showTip
= wxShowTip(frame
, tp
)
493 index
= tp
.GetCurrentTip()
494 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
501 Create and show the splash screen. It will then create and show
502 the main frame when it is time to do so.
504 wxInitAllImageHandlers()
505 splash
= MySplashScreen()
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 #----------------------------------------------------------------------------