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
18 ##from wxPython.stc import *
22 #---------------------------------------------------------------------------
27 ('New since last release', [
37 # managed windows == things with a caption you can close
38 ('Base Frames and Dialogs', [
50 'wxFindReplaceDialog',
56 'wxSingleChoiceDialog',
60 # dialogs form libraries
64 'wxMultipleChoiceDialog',
65 'wxScrolledMessageDialog',
69 ('Core Windows/Controls', [
100 # controls coming from other librairies
101 ('More Windows/Controls', [
108 'PyCrustWithFilling',
113 'wxDynamicSashWindow',
119 'wxMimeTypesManager',
121 'wxStyledTextCtrl_1',
122 'wxStyledTextCtrl_2',
126 # How to lay out the controls in a frame/dialog
133 'wxLayoutConstraints',
138 ('Process and Events', [
148 ('Clipboard and DnD', [
177 # need libs not coming with the demo
178 ('Objects using an external library', [
179 'ActiveXWrapper_Acrobat',
185 # pyTree, hangman, ... in the samples dir
186 ('Check out the samples dir too', [
193 #---------------------------------------------------------------------------
195 class MyLog(wxPyLog
):
196 def __init__(self
, textCtrl
, logTime
=0):
197 wxPyLog
.__init
__(self
)
199 self
.logTime
= logTime
201 def DoLogString(self
, message
, timeStamp
):
203 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
205 self
.tc
.AppendText(message
+ '\n')
208 #---------------------------------------------------------------------------
211 """Convert paths to the platform-specific separator"""
212 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
215 #---------------------------------------------------------------------------
217 class wxPythonDemo(wxFrame
):
218 overviewText
= "wxPython Overview"
220 def __init__(self
, parent
, id, title
):
221 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
222 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
224 self
.cwd
= os
.getcwd()
225 self
.curOverview
= ""
227 icon
= images
.getMondrianIcon()
230 if wxPlatform
== '__WXMSW__':
231 # setup a taskbar icon, and catch some events from it
232 self
.tbicon
= wxTaskBarIcon()
233 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
234 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
235 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
236 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
237 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
242 EVT_IDLE(self
, self
.OnIdle
)
243 EVT_CLOSE(self
, self
.OnCloseWindow
)
244 EVT_ICONIZE(self
, self
.OnIconfiy
)
245 EVT_MAXIMIZE(self
, self
.OnMaximize
)
248 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
250 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
251 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
253 def EmptyHandler(evt
): pass
254 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
255 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
257 # Prevent TreeCtrl from displaying all items after destruction when true
261 self
.mainmenu
= wxMenuBar()
264 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
265 EVT_MENU(self
, exitID
, self
.OnFileExit
)
266 self
.mainmenu
.Append(menu
, '&File')
270 for item
in _treeList
:
272 for childItem
in item
[1]:
274 submenu
.Append(mID
, childItem
)
275 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
276 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
277 self
.mainmenu
.Append(menu
, '&Demo')
283 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
284 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
285 self
.mainmenu
.Append(menu
, '&Help')
286 self
.SetMenuBar(self
.mainmenu
)
288 # set the menu accellerator table...
289 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
290 (wxACCEL_CTRL
, ord('H'), helpID
)])
291 self
.SetAcceleratorTable(aTable
)
297 self
.tree
= wxTreeCtrl(splitter
, tID
,
298 style
=wxTR_HAS_BUTTONS |
300 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
302 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
303 root
= self
.tree
.AddRoot("wxPython Overview")
305 for item
in _treeList
:
306 child
= self
.tree
.AppendItem(root
, item
[0])
307 if not firstChild
: firstChild
= child
308 for childItem
in item
[1]:
309 theDemo
= self
.tree
.AppendItem(child
, childItem
)
310 self
.treeMap
[childItem
] = theDemo
312 self
.tree
.Expand(root
)
313 self
.tree
.Expand(firstChild
)
314 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
315 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
316 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
317 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
320 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
322 # Set up a wxHtmlWindow on the Overview Notebook page
323 # we put it in a panel first because there seems to be a
324 # refresh bug of some sort (wxGTK) when it is directly in
327 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
328 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
330 else: # hopefully I can remove this hacky code soon, see bug #216861
331 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
332 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
333 self
.nb
.AddPage(panel
, self
.overviewText
)
335 def OnOvrSize(evt
, ovr
=self
.ovr
):
336 ovr
.SetSize(evt
.GetSize())
338 EVT_SIZE(panel
, OnOvrSize
)
339 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
342 self
.SetOverview(self
.overviewText
, overview
)
345 # Set up a TextCtrl on the Demo Code Notebook page
346 self
.txt
= wxTextCtrl(self
.nb
, -1,
347 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
348 self
.nb
.AddPage(self
.txt
, "Demo Code")
351 # Set up a log on the View Log Notebook page
352 self
.log
= wxTextCtrl(splitter2
, -1,
353 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
355 # Set the wxWindows log target to be this textctrl
356 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
358 # But instead of the above we want to show how to use our own wxLog class
359 wxLog_SetActiveTarget(MyLog(self
.log
))
361 # for serious debugging
362 #wxLog_SetActiveTarget(wxLogStderr())
363 #wxLog_SetTraceMask(wxTraceMessages)
368 # add the windows to the splitter and split it.
369 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
370 splitter
.SplitVertically(self
.tree
, splitter2
)
372 splitter
.SetSashPosition(180, true
)
373 splitter
.SetMinimumPaneSize(20)
374 splitter2
.SetSashPosition(450, true
)
375 splitter2
.SetMinimumPaneSize(20)
379 # select initial items
380 self
.nb
.SetSelection(0)
381 self
.tree
.SelectItem(root
)
383 if len(sys
.argv
) == 2:
385 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
389 self
.tree
.SelectItem(selectedDemo
)
390 self
.tree
.EnsureVisible(selectedDemo
)
393 wxLogMessage('window handle: %s' % self
.GetHandle())
396 #---------------------------------------------
397 def WriteText(self
, text
):
398 if text
[-1:] == '\n':
403 def write(self
, txt
):
406 #---------------------------------------------
407 def OnItemExpanded(self
, event
):
408 item
= event
.GetItem()
409 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
412 #---------------------------------------------
413 def OnItemCollapsed(self
, event
):
414 item
= event
.GetItem()
415 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
418 #---------------------------------------------
419 def OnTreeLeftDown(self
, event
):
420 pt
= event
.GetPosition();
421 item
, flags
= self
.tree
.HitTest(pt
)
422 if item
== self
.tree
.GetSelection():
423 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
426 #---------------------------------------------
427 def OnSelChanged(self
, event
):
431 item
= event
.GetItem()
432 itemText
= self
.tree
.GetItemText(item
)
433 self
.RunDemo(itemText
)
436 #---------------------------------------------
437 def RunDemo(self
, itemText
):
439 if self
.nb
.GetPageCount() == 3:
440 if self
.nb
.GetSelection() == 2:
441 self
.nb
.SetSelection(0)
442 self
.nb
.DeletePage(2)
444 if itemText
== self
.overviewText
:
445 self
.GetDemoFile('Main.py')
446 self
.SetOverview(self
.overviewText
, overview
)
451 if os
.path
.exists(itemText
+ '.py'):
453 wxLogMessage("Running demo %s.py..." % itemText
)
455 self
.GetDemoFile(itemText
+ '.py')
456 module
= __import__(itemText
, globals())
457 self
.SetOverview(itemText
+ " Overview", module
.overview
)
462 # in case runTest is modal, make sure things look right...
466 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
468 self
.nb
.AddPage(self
.window
, 'Demo')
469 self
.nb
.SetSelection(2)
470 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
479 #---------------------------------------------
481 def GetDemoFile(self
, filename
):
484 self
.txt
.SetValue(open(filename
).read())
486 self
.txt
.WriteText("Cannot open %s file." % filename
)
488 self
.txt
.SetInsertionPoint(0)
489 self
.txt
.ShowPosition(0)
491 #---------------------------------------------
492 def SetOverview(self
, name
, text
):
493 self
.curOverview
= text
495 if lead
!= '<html>' and lead
!= '<HTML>':
496 text
= string
.join(string
.split(text
, '\n'), '<br>')
497 self
.ovr
.SetPage(text
)
498 self
.nb
.SetPageText(0, name
)
500 #---------------------------------------------
502 def OnFileExit(self
, *event
):
506 def OnHelpAbout(self
, event
):
507 from About
import MyAboutBox
508 about
= MyAboutBox(self
)
513 #---------------------------------------------
514 def OnCloseWindow(self
, event
):
518 if hasattr(self
, "tbicon"):
523 #---------------------------------------------
524 def OnIdle(self
, event
):
526 self
.otherWin
.Raise()
527 self
.window
= self
.otherWin
535 #---------------------------------------------
538 showTipText
= open(opj("data/showTips")).read()
539 showTip
, index
= eval(showTipText
)
541 showTip
, index
= (1, 0)
543 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
544 showTip
= wxShowTip(self
, tp
)
545 index
= tp
.GetCurrentTip()
546 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
549 #---------------------------------------------
550 def OnDemoMenu(self
, event
):
552 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
556 self
.tree
.SelectItem(selectedDemo
)
557 self
.tree
.EnsureVisible(selectedDemo
)
560 #---------------------------------------------
561 def OnTaskBarActivate(self
, evt
):
562 if self
.IsIconized():
564 if not self
.IsShown():
568 #---------------------------------------------
570 TBMENU_RESTORE
= 1000
573 def OnTaskBarMenu(self
, evt
):
575 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
576 menu
.Append(self
.TBMENU_CLOSE
, "Close")
577 self
.tbicon
.PopupMenu(menu
)
580 #---------------------------------------------
581 def OnTaskBarClose(self
, evt
):
584 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
585 # prod the main idle handler a bit to get the window to actually close
586 wxGetApp().ProcessIdle()
589 #---------------------------------------------
590 def OnIconfiy(self
, evt
):
591 wxLogMessage("OnIconfiy")
594 #---------------------------------------------
595 def OnMaximize(self
, evt
):
596 wxLogMessage("OnMaximize")
602 #---------------------------------------------------------------------------
603 #---------------------------------------------------------------------------
605 class MySplashScreen(wxSplashScreen
):
607 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
608 wxSplashScreen
.__init
__(self
, bmp
,
609 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
611 style
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
)
612 EVT_CLOSE(self
, self
.OnClose
)
614 def OnClose(self
, evt
):
615 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
617 evt
.Skip() # Make sure the default handler runs too...
623 Create and show the splash screen. It will then create and show
624 the main frame when it is time to do so.
626 wxInitAllImageHandlers()
627 splash
= MySplashScreen()
633 #---------------------------------------------------------------------------
637 demoPath
= os
.path
.dirname(__file__
)
641 app
= MyApp(wxPlatform
== "__WXMAC__")
645 #---------------------------------------------------------------------------
649 overview
= """<html><body>
652 Python is an interpreted, interactive, object-oriented programming
653 language often compared to Tcl, Perl, Scheme, or Java.
655 <p> Python combines remarkable power with very clear syntax. It has
656 modules, classes, exceptions, very high level dynamic data types, and
657 dynamic typing. There are interfaces to many system calls and
658 libraries, and new built-in modules are easily written in C or
659 C++. Python is also usable as an extension language for applications
660 that need a programmable interface. <p>
664 wxWindows is a free C++ framework designed to make cross-platform
665 programming child's play. Well, almost. wxWindows 2 supports Windows
666 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
667 underway. Other ports are under consideration. <p>
669 wxWindows is a set of libraries that allows C++ applications to
670 compile and run on several different types of computers, with minimal
671 source code changes. There is one library per supported GUI (such as
672 Motif, or Windows). As well as providing a common API (Application
673 Programming Interface) for GUI functionality, it provides
674 functionality for accessing some commonly-used operating system
675 facilities, such as copying or deleting files. wxWindows is a
676 'framework' in the sense that it provides a lot of built-in
677 functionality, which the application can use or replace as required,
678 thus saving a great deal of coding effort. Basic data structures such
679 as strings, linked lists and hash tables are also supported.
684 wxPython is a Python extension module that encapsulates the wxWindows
685 GUI classes. Currently it is only available for the Win32 and GTK
686 ports of wxWindows, but as soon as the other ports are brought up to
687 the same level as Win32 and GTK, it should be fairly trivial to
688 enable wxPython to be used with the new GUI.
692 The wxPython extension module attempts to mirror the class heiarchy
693 of wxWindows as closely as possible. This means that there is a
694 wxFrame class in wxPython that looks, smells, tastes and acts almost
695 the same as the wxFrame class in the C++ version. Unfortunately,
696 because of differences in the languages, wxPython doesn't match
697 wxWindows exactly, but the differences should be easy to absorb
698 because they are natural to Python. For example, some methods that
699 return multiple values via argument pointers in C++ will return a
700 tuple of values in Python.
704 There is still much to be done for wxPython, many classes still need
705 to be mirrored. Also, wxWindows is still somewhat of a moving target
706 so it is a bit of an effort just keeping wxPython up to date. On the
707 other hand, there are enough of the core classes completed that
708 useful applications can be written.
712 wxPython is close enough to the C++ version that the majority of
713 the wxPython documentation is actually just notes attached to the C++
714 documents that describe the places where wxPython is different. There
715 is also a series of sample programs included, and a series of
716 documentation pages that assist the programmer in getting started
722 #----------------------------------------------------------------------------
723 #----------------------------------------------------------------------------
725 if __name__
== '__main__':
728 #----------------------------------------------------------------------------