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',
40 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
41 'wxGrid', 'wxSashWindow',
42 'wxScrolledWindow', 'wxSplitterWindow',
43 'wxStatusBar', 'wxNotebook',
45 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
49 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
50 'wxSingleChoiceDialog', 'wxTextEntryDialog',
51 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
52 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
55 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
56 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl',
57 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
58 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
59 'wxCalendarCtrl', 'wxToggleButton',
62 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
64 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'URLDragAndDrop',
66 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
67 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
68 'PythonEvents', 'Threads',
69 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
70 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
71 'wxJoystick', 'DrawXXXList', 'ErrorDialogs',
74 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
75 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
76 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
77 'FileBrowseButton', 'GenericButtons', 'wxEditor',
78 'ColourSelect', 'ImageBrowser',
79 'infoframe', 'ColourDB', 'PyCrust', 'TablePrint',
83 ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']),
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 #---------------------------------------------------------------------------
104 class wxPythonDemo(wxFrame
):
106 def __init__(self
, parent
, id, title
):
107 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
108 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
110 self
.cwd
= os
.getcwd()
111 self
.curOverview
= ""
114 icon
= wxIconFromXPMData(images
.getMondrianData())
116 # another way to do it
117 bmp
= images
.getMondrianBitmap()
119 icon
.CopyFromBitmap(bmp
)
123 if wxPlatform
== '__WXMSW__':
124 # setup a taskbar icon, and catch some events from it
125 self
.tbicon
= wxTaskBarIcon()
126 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
127 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
128 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
129 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
130 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
134 EVT_IDLE(self
, self
.OnIdle
)
135 EVT_CLOSE(self
, self
.OnCloseWindow
)
136 EVT_ICONIZE(self
, self
.OnIconfiy
)
137 EVT_MAXIMIZE(self
, self
.OnMaximize
)
140 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
142 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
143 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
145 def EmptyHandler(evt
): pass
146 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
147 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
149 # Prevent TreeCtrl from displaying all items after destruction when true
153 self
.mainmenu
= wxMenuBar()
156 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
157 EVT_MENU(self
, exitID
, self
.OnFileExit
)
158 self
.mainmenu
.Append(menu
, '&File')
162 for item
in _treeList
:
164 for childItem
in item
[1]:
166 submenu
.Append(mID
, childItem
)
167 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
168 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
169 self
.mainmenu
.Append(menu
, '&Demo')
175 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
176 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
177 self
.mainmenu
.Append(menu
, '&Help')
178 self
.SetMenuBar(self
.mainmenu
)
180 # set the menu accellerator table...
181 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
182 (wxACCEL_CTRL
, ord('H'), helpID
)])
183 self
.SetAcceleratorTable(aTable
)
189 self
.tree
= wxTreeCtrl(splitter
, tID
,
190 style
=wxTR_HAS_BUTTONS |
192 wxTR_HAS_VARIABLE_ROW_HEIGHT |
194 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
195 root
= self
.tree
.AddRoot("Overview")
197 for item
in _treeList
:
198 child
= self
.tree
.AppendItem(root
, item
[0])
199 if not firstChild
: firstChild
= child
200 for childItem
in item
[1]:
201 theDemo
= self
.tree
.AppendItem(child
, childItem
)
202 self
.treeMap
[childItem
] = theDemo
204 self
.tree
.Expand(root
)
205 self
.tree
.Expand(firstChild
)
206 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
207 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
208 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
209 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
212 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
214 # Set up a wxHtmlWindow on the Overview Notebook page
215 # we put it in a panel first because there seems to be a
216 # refresh bug of some sort (wxGTK) when it is directly in
219 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
220 self
.nb
.AddPage(self
.ovr
, "Overview")
222 else: # hopefully I can remove this hacky code soon, see bug #216861
223 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
224 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
225 self
.nb
.AddPage(panel
, "Overview")
227 def OnOvrSize(evt
, ovr
=self
.ovr
):
228 ovr
.SetSize(evt
.GetSize())
230 EVT_SIZE(panel
, OnOvrSize
)
231 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
234 self
.SetOverview("Overview", overview
)
237 # Set up a TextCtrl on the Demo Code Notebook page
238 self
.txt
= wxTextCtrl(self
.nb
, -1,
239 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
240 self
.nb
.AddPage(self
.txt
, "Demo Code")
243 # Set up a log on the View Log Notebook page
244 self
.log
= wxTextCtrl(splitter2
, -1,
245 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
246 # Set the wxWindows log target to be this textctrl
247 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
248 wxLog_SetActiveTarget(MyLog(self
.log
))
254 # add the windows to the splitter and split it.
255 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
256 splitter2
.SetSashPosition(450, true
)
257 splitter2
.SetMinimumPaneSize(20)
259 splitter
.SplitVertically(self
.tree
, splitter2
)
260 splitter
.SetSashPosition(180, true
)
261 splitter
.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 #text = '<font size="-1"><pre>' + text + '</pre></font>'
382 self
.ovr
.SetPage(text
)
383 self
.nb
.SetPageText(0, name
)
385 #---------------------------------------------
387 def OnFileExit(self
, *event
):
391 def OnHelpAbout(self
, event
):
392 from About
import MyAboutBox
393 about
= MyAboutBox(self
)
398 #---------------------------------------------
399 def OnCloseWindow(self
, event
):
403 if hasattr(self
, "tbicon"):
408 #---------------------------------------------
409 def OnIdle(self
, event
):
411 self
.otherWin
.Raise()
412 self
.window
= self
.otherWin
415 #---------------------------------------------
416 def OnDemoMenu(self
, event
):
418 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
422 self
.tree
.SelectItem(selectedDemo
)
423 self
.tree
.EnsureVisible(selectedDemo
)
426 #---------------------------------------------
427 def OnTaskBarActivate(self
, evt
):
428 if self
.IsIconized():
430 if not self
.IsShown():
434 #---------------------------------------------
436 TBMENU_RESTORE
= 1000
439 def OnTaskBarMenu(self
, evt
):
441 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
442 menu
.Append(self
.TBMENU_CLOSE
, "Close")
443 self
.tbicon
.PopupMenu(menu
)
446 #---------------------------------------------
447 def OnTaskBarClose(self
, evt
):
450 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
451 # prod the main idle handler a bit to get the window to actually close
452 wxGetApp().ProcessIdle()
455 #---------------------------------------------
456 def OnIconfiy(self
, evt
):
457 wxLogMessage("OnIconfiy")
460 #---------------------------------------------
461 def OnMaximize(self
, evt
):
462 wxLogMessage("OnMaximize")
468 #---------------------------------------------------------------------------
469 #---------------------------------------------------------------------------
473 wxInitAllImageHandlers()
475 self
.splash
= SplashScreen(None, bitmapfile
='bitmaps/splash.gif',
476 duration
=4000, callback
=self
.AfterSplash
)
477 self
.splash
.Show(true
)
482 def AfterSplash(self
):
483 self
.splash
.Close(true
)
484 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
486 self
.SetTopWindow(frame
)
490 def ShowTip(self
, frame
):
492 showTipText
= open("data/showTips").read()
493 showTip
, index
= eval(showTipText
)
495 showTip
, index
= (1, 0)
496 #print showTip, index
498 tp
= wxCreateFileTipProvider("data/tips.txt", index
)
499 showTip
= wxShowTip(frame
, tp
)
500 index
= tp
.GetCurrentTip()
501 open("data/showTips", "w").write(str( (showTip
, index
) ))
504 #---------------------------------------------------------------------------
508 demoPath
= os
.path
.dirname(__file__
)
516 #---------------------------------------------------------------------------
520 overview
= """<html><body>
523 Python is an interpreted, interactive, object-oriented programming
524 language often compared to Tcl, Perl, Scheme, or Java.
526 <p> Python combines remarkable power with very clear syntax. It has
527 modules, classes, exceptions, very high level dynamic data types, and
528 dynamic typing. There are interfaces to many system calls and
529 libraries, and new built-in modules are easily written in C or
530 C++. Python is also usable as an extension language for applications
531 that need a programmable interface. <p>
535 wxWindows is a free C++ framework designed to make cross-platform
536 programming child's play. Well, almost. wxWindows 2 supports Windows
537 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
538 underway. Other ports are under consideration. <p>
540 wxWindows is a set of libraries that allows C++ applications to
541 compile and run on several different types of computers, with minimal
542 source code changes. There is one library per supported GUI (such as
543 Motif, or Windows). As well as providing a common API (Application
544 Programming Interface) for GUI functionality, it provides
545 functionality for accessing some commonly-used operating system
546 facilities, such as copying or deleting files. wxWindows is a
547 'framework' in the sense that it provides a lot of built-in
548 functionality, which the application can use or replace as required,
549 thus saving a great deal of coding effort. Basic data structures such
550 as strings, linked lists and hash tables are also supported.
555 wxPython is a Python extension module that encapsulates the wxWindows
556 GUI classes. Currently it is only available for the Win32 and GTK
557 ports of wxWindows, but as soon as the other ports are brought up to
558 the same level as Win32 and GTK, it should be fairly trivial to
559 enable wxPython to be used with the new GUI.
563 The wxPython extension module attempts to mirror the class heiarchy
564 of wxWindows as closely as possible. This means that there is a
565 wxFrame class in wxPython that looks, smells, tastes and acts almost
566 the same as the wxFrame class in the C++ version. Unfortunately,
567 because of differences in the languages, wxPython doesn't match
568 wxWindows exactly, but the differences should be easy to absorb
569 because they are natural to Python. For example, some methods that
570 return multiple values via argument pointers in C++ will return a
571 tuple of values in Python.
575 There is still much to be done for wxPython, many classes still need
576 to be mirrored. Also, wxWindows is still somewhat of a moving target
577 so it is a bit of an effort just keeping wxPython up to date. On the
578 other hand, there are enough of the core classes completed that
579 useful applications can be written.
583 wxPython is close enough to the C++ version that the majority of
584 the wxPython documentation is actually just notes attached to the C++
585 documents that describe the places where wxPython is different. There
586 is also a series of sample programs included, and a series of
587 documentation pages that assist the programmer in getting started
593 #----------------------------------------------------------------------------
594 #----------------------------------------------------------------------------
596 if __name__
== '__main__':
599 #----------------------------------------------------------------------------