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',
30 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
31 'wxGrid', 'wxSashWindow',
32 'wxScrolledWindow', 'wxSplitterWindow',
33 'wxStatusBar', 'wxNotebook',
35 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
37 'wxDynamicSashWindow',
40 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
41 'wxSingleChoiceDialog', 'wxTextEntryDialog',
42 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
43 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
46 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
47 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'VirtualListCtrl',
49 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
50 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
51 'wxCalendarCtrl', 'wxToggleButton',
52 'wxEditableListBox', 'wxLEDNumberCtrl',
55 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource',
59 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
61 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
62 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
63 'PythonEvents', 'Threads',
64 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
65 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
66 'wxJoystick', 'DrawXXXList', 'ErrorDialogs', 'wxMimeTypesManager',
67 'ContextHelp', 'SplitTree', 'Unicode',
70 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
71 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
72 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
73 'FileBrowseButton', 'GenericButtons', 'wxEditor',
74 'ColourSelect', 'ImageBrowser',
75 'infoframe', 'ColourDB', 'PyCrust', 'PyCrustWithFilling',
80 ('Cool Contribs', ['pyTree', 'hangman',
87 #---------------------------------------------------------------------------
90 def __init__(self
, textCtrl
, logTime
=0):
91 wxPyLog
.__init
__(self
)
93 self
.logTime
= logTime
95 def DoLogString(self
, message
, timeStamp
):
97 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
99 self
.tc
.AppendText(message
+ '\n')
102 #---------------------------------------------------------------------------
105 """Convert paths to the platform-specific separator"""
106 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
109 #---------------------------------------------------------------------------
111 class wxPythonDemo(wxFrame
):
112 overviewText
= "wxPython Overview"
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
= ""
121 icon
= images
.getMondrianIcon()
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
)
136 EVT_IDLE(self
, self
.OnIdle
)
137 EVT_CLOSE(self
, self
.OnCloseWindow
)
138 EVT_ICONIZE(self
, self
.OnIconfiy
)
139 EVT_MAXIMIZE(self
, self
.OnMaximize
)
142 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
144 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
145 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
147 def EmptyHandler(evt
): pass
148 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
149 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
151 # Prevent TreeCtrl from displaying all items after destruction when true
155 self
.mainmenu
= wxMenuBar()
158 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
159 EVT_MENU(self
, exitID
, self
.OnFileExit
)
160 self
.mainmenu
.Append(menu
, '&File')
164 for item
in _treeList
:
166 for childItem
in item
[1]:
168 submenu
.Append(mID
, childItem
)
169 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
170 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
171 self
.mainmenu
.Append(menu
, '&Demo')
177 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
178 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
179 self
.mainmenu
.Append(menu
, '&Help')
180 self
.SetMenuBar(self
.mainmenu
)
182 # set the menu accellerator table...
183 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
184 (wxACCEL_CTRL
, ord('H'), helpID
)])
185 self
.SetAcceleratorTable(aTable
)
191 self
.tree
= wxTreeCtrl(splitter
, tID
,
192 style
=wxTR_HAS_BUTTONS |
194 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
196 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
197 root
= self
.tree
.AddRoot("wxPython Overview")
199 for item
in _treeList
:
200 child
= self
.tree
.AppendItem(root
, item
[0])
201 if not firstChild
: firstChild
= child
202 for childItem
in item
[1]:
203 theDemo
= self
.tree
.AppendItem(child
, childItem
)
204 self
.treeMap
[childItem
] = theDemo
206 self
.tree
.Expand(root
)
207 self
.tree
.Expand(firstChild
)
208 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
209 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
210 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
211 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
214 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
216 # Set up a wxHtmlWindow on the Overview Notebook page
217 # we put it in a panel first because there seems to be a
218 # refresh bug of some sort (wxGTK) when it is directly in
221 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
222 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
224 else: # hopefully I can remove this hacky code soon, see bug #216861
225 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
226 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
227 self
.nb
.AddPage(panel
, self
.overviewText
)
229 def OnOvrSize(evt
, ovr
=self
.ovr
):
230 ovr
.SetSize(evt
.GetSize())
232 EVT_SIZE(panel
, OnOvrSize
)
233 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
236 self
.SetOverview(self
.overviewText
, overview
)
239 # Set up a TextCtrl on the Demo Code Notebook page
240 self
.txt
= wxTextCtrl(self
.nb
, -1,
241 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
242 self
.nb
.AddPage(self
.txt
, "Demo Code")
245 # Set up a log on the View Log Notebook page
246 self
.log
= wxTextCtrl(splitter2
, -1,
247 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
249 # Set the wxWindows log target to be this textctrl
250 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
252 # But instead of the above we want to show how to use our own wxLog class
253 wxLog_SetActiveTarget(MyLog(self
.log
))
259 # add the windows to the splitter and split it.
260 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
261 splitter
.SplitVertically(self
.tree
, splitter2
)
263 splitter
.SetSashPosition(180, true
)
264 splitter
.SetMinimumPaneSize(20)
265 splitter2
.SetSashPosition(450, true
)
266 splitter2
.SetMinimumPaneSize(20)
270 # select initial items
271 self
.nb
.SetSelection(0)
272 self
.tree
.SelectItem(root
)
274 if len(sys
.argv
) == 2:
276 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
280 self
.tree
.SelectItem(selectedDemo
)
281 self
.tree
.EnsureVisible(selectedDemo
)
284 wxLogMessage('window handle: %s' % self
.GetHandle())
287 #---------------------------------------------
288 def WriteText(self
, text
):
289 if text
[-1:] == '\n':
294 def write(self
, txt
):
297 #---------------------------------------------
298 def OnItemExpanded(self
, event
):
299 item
= event
.GetItem()
300 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
303 #---------------------------------------------
304 def OnItemCollapsed(self
, event
):
305 item
= event
.GetItem()
306 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
309 #---------------------------------------------
310 def OnTreeLeftDown(self
, event
):
311 pt
= event
.GetPosition();
312 item
, flags
= self
.tree
.HitTest(pt
)
313 if item
== self
.tree
.GetSelection():
314 self
.SetOverview(self
.tree
.GetItemText(item
), self
.curOverview
)
317 #---------------------------------------------
318 def OnSelChanged(self
, event
):
322 item
= event
.GetItem()
323 itemText
= self
.tree
.GetItemText(item
)
324 self
.RunDemo(itemText
)
327 #---------------------------------------------
328 def RunDemo(self
, itemText
):
330 if self
.nb
.GetPageCount() == 3:
331 if self
.nb
.GetSelection() == 2:
332 self
.nb
.SetSelection(0)
333 self
.nb
.DeletePage(2)
335 if itemText
== self
.overviewText
:
336 self
.GetDemoFile('Main.py')
337 self
.SetOverview(self
.overviewText
, overview
)
342 if os
.path
.exists(itemText
+ '.py'):
344 wxLogMessage("Running demo %s.py..." % itemText
)
346 self
.GetDemoFile(itemText
+ '.py')
347 module
= __import__(itemText
, globals())
348 self
.SetOverview(itemText
+ " Overview", module
.overview
)
352 # in case runTest is modal, make sure things look right...
356 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
358 self
.nb
.AddPage(self
.window
, 'Demo')
360 self
.nb
.SetSelection(2)
369 #---------------------------------------------
371 def GetDemoFile(self
, filename
):
374 self
.txt
.SetValue(open(filename
).read())
376 self
.txt
.WriteText("Cannot open %s file." % filename
)
378 self
.txt
.SetInsertionPoint(0)
379 self
.txt
.ShowPosition(0)
381 #---------------------------------------------
382 def SetOverview(self
, name
, text
):
383 self
.curOverview
= text
385 if lead
!= '<html>' and lead
!= '<HTML>':
386 text
= string
.join(string
.split(text
, '\n'), '<br>')
387 self
.ovr
.SetPage(text
)
388 self
.nb
.SetPageText(0, name
)
390 #---------------------------------------------
392 def OnFileExit(self
, *event
):
396 def OnHelpAbout(self
, event
):
397 from About
import MyAboutBox
398 about
= MyAboutBox(self
)
403 #---------------------------------------------
404 def OnCloseWindow(self
, event
):
408 if hasattr(self
, "tbicon"):
413 #---------------------------------------------
414 def OnIdle(self
, event
):
416 self
.otherWin
.Raise()
417 self
.window
= self
.otherWin
425 #---------------------------------------------
428 showTipText
= open(opj("data/showTips")).read()
429 showTip
, index
= eval(showTipText
)
431 showTip
, index
= (1, 0)
433 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
434 showTip
= wxShowTip(self
, tp
)
435 index
= tp
.GetCurrentTip()
436 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
439 #---------------------------------------------
440 def OnDemoMenu(self
, event
):
442 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
446 self
.tree
.SelectItem(selectedDemo
)
447 self
.tree
.EnsureVisible(selectedDemo
)
450 #---------------------------------------------
451 def OnTaskBarActivate(self
, evt
):
452 if self
.IsIconized():
454 if not self
.IsShown():
458 #---------------------------------------------
460 TBMENU_RESTORE
= 1000
463 def OnTaskBarMenu(self
, evt
):
465 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
466 menu
.Append(self
.TBMENU_CLOSE
, "Close")
467 self
.tbicon
.PopupMenu(menu
)
470 #---------------------------------------------
471 def OnTaskBarClose(self
, evt
):
474 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
475 # prod the main idle handler a bit to get the window to actually close
476 wxGetApp().ProcessIdle()
479 #---------------------------------------------
480 def OnIconfiy(self
, evt
):
481 wxLogMessage("OnIconfiy")
484 #---------------------------------------------
485 def OnMaximize(self
, evt
):
486 wxLogMessage("OnMaximize")
492 #---------------------------------------------------------------------------
493 #---------------------------------------------------------------------------
495 class MySplashScreen(wxSplashScreen
):
497 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
498 wxSplashScreen
.__init
__(self
, bmp
,
499 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
501 EVT_CLOSE(self
, self
.OnClose
)
503 def OnClose(self
, evt
):
504 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
506 evt
.Skip() # Make sure the default handler runs too...
512 Create and show the splash screen. It will then create and show
513 the main frame when it is time to do so.
515 wxInitAllImageHandlers()
516 splash
= MySplashScreen()
522 #---------------------------------------------------------------------------
526 demoPath
= os
.path
.dirname(__file__
)
534 #---------------------------------------------------------------------------
538 overview
= """<html><body>
541 Python is an interpreted, interactive, object-oriented programming
542 language often compared to Tcl, Perl, Scheme, or Java.
544 <p> Python combines remarkable power with very clear syntax. It has
545 modules, classes, exceptions, very high level dynamic data types, and
546 dynamic typing. There are interfaces to many system calls and
547 libraries, and new built-in modules are easily written in C or
548 C++. Python is also usable as an extension language for applications
549 that need a programmable interface. <p>
553 wxWindows is a free C++ framework designed to make cross-platform
554 programming child's play. Well, almost. wxWindows 2 supports Windows
555 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
556 underway. Other ports are under consideration. <p>
558 wxWindows is a set of libraries that allows C++ applications to
559 compile and run on several different types of computers, with minimal
560 source code changes. There is one library per supported GUI (such as
561 Motif, or Windows). As well as providing a common API (Application
562 Programming Interface) for GUI functionality, it provides
563 functionality for accessing some commonly-used operating system
564 facilities, such as copying or deleting files. wxWindows is a
565 'framework' in the sense that it provides a lot of built-in
566 functionality, which the application can use or replace as required,
567 thus saving a great deal of coding effort. Basic data structures such
568 as strings, linked lists and hash tables are also supported.
573 wxPython is a Python extension module that encapsulates the wxWindows
574 GUI classes. Currently it is only available for the Win32 and GTK
575 ports of wxWindows, but as soon as the other ports are brought up to
576 the same level as Win32 and GTK, it should be fairly trivial to
577 enable wxPython to be used with the new GUI.
581 The wxPython extension module attempts to mirror the class heiarchy
582 of wxWindows as closely as possible. This means that there is a
583 wxFrame class in wxPython that looks, smells, tastes and acts almost
584 the same as the wxFrame class in the C++ version. Unfortunately,
585 because of differences in the languages, wxPython doesn't match
586 wxWindows exactly, but the differences should be easy to absorb
587 because they are natural to Python. For example, some methods that
588 return multiple values via argument pointers in C++ will return a
589 tuple of values in Python.
593 There is still much to be done for wxPython, many classes still need
594 to be mirrored. Also, wxWindows is still somewhat of a moving target
595 so it is a bit of an effort just keeping wxPython up to date. On the
596 other hand, there are enough of the core classes completed that
597 useful applications can be written.
601 wxPython is close enough to the C++ version that the majority of
602 the wxPython documentation is actually just notes attached to the C++
603 documents that describe the places where wxPython is different. There
604 is also a series of sample programs included, and a series of
605 documentation pages that assist the programmer in getting started
611 #----------------------------------------------------------------------------
612 #----------------------------------------------------------------------------
614 if __name__
== '__main__':
617 #----------------------------------------------------------------------------