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', [
41 # managed windows == things with a caption you can close
42 ('Base Frames and Dialogs', [
55 'wxFindReplaceDialog',
61 'wxSingleChoiceDialog',
65 # dialogs from libraries
69 'wxMultipleChoiceDialog',
70 'wxScrolledMessageDialog',
74 ('Core Windows/Controls', [
106 # controls coming from other librairies
107 ('More Windows/Controls', [
114 'PyCrustWithFilling',
119 'wxDynamicSashWindow',
122 #'wxFloatBar', deprecated
126 'wxMimeTypesManager',
127 #'wxMVCTree', deprecated
129 'wxStyledTextCtrl_1',
130 'wxStyledTextCtrl_2',
133 # How to lay out the controls in a frame/dialog
140 'wxLayoutConstraints',
145 ('Process and Events', [
156 ('Clipboard and DnD', [
185 # need libs not coming with the demo
186 ('Objects using an external library', [
187 'ActiveXWrapper_Acrobat',
194 ('Check out the samples dir too', [
201 #---------------------------------------------------------------------------
203 class MyLog(wxPyLog
):
204 def __init__(self
, textCtrl
, logTime
=0):
205 wxPyLog
.__init
__(self
)
207 self
.logTime
= logTime
209 def DoLogString(self
, message
, timeStamp
):
211 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
213 self
.tc
.AppendText(message
+ '\n')
216 class MyTP(wxPyTipProvider
):
218 return "This is my tip"
220 #---------------------------------------------------------------------------
223 """Convert paths to the platform-specific separator"""
224 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
227 #---------------------------------------------------------------------------
229 class wxPythonDemo(wxFrame
):
230 overviewText
= "wxPython Overview"
232 def __init__(self
, parent
, id, title
):
233 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
234 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
236 self
.cwd
= os
.getcwd()
237 self
.curOverview
= ""
239 icon
= images
.getMondrianIcon()
242 if wxPlatform
== '__WXMSW__':
243 # setup a taskbar icon, and catch some events from it
244 self
.tbicon
= wxTaskBarIcon()
245 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
246 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
247 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
248 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
249 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
254 EVT_IDLE(self
, self
.OnIdle
)
255 EVT_CLOSE(self
, self
.OnCloseWindow
)
256 EVT_ICONIZE(self
, self
.OnIconfiy
)
257 EVT_MAXIMIZE(self
, self
.OnMaximize
)
260 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
262 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
263 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
265 def EmptyHandler(evt
): pass
266 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
267 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
269 # Prevent TreeCtrl from displaying all items after destruction when true
273 self
.mainmenu
= wxMenuBar()
276 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
277 EVT_MENU(self
, exitID
, self
.OnFileExit
)
278 self
.mainmenu
.Append(menu
, '&File')
282 for item
in _treeList
:
284 for childItem
in item
[1]:
286 submenu
.Append(mID
, childItem
)
287 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
288 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
289 self
.mainmenu
.Append(menu
, '&Demo')
295 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
296 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
297 self
.mainmenu
.Append(menu
, '&Help')
298 self
.SetMenuBar(self
.mainmenu
)
300 # set the menu accellerator table...
301 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
302 (wxACCEL_CTRL
, ord('H'), helpID
)])
303 self
.SetAcceleratorTable(aTable
)
309 self
.tree
= wxTreeCtrl(splitter
, tID
,
310 style
=wxTR_HAS_BUTTONS |
311 wxTR_HAS_VARIABLE_ROW_HEIGHT
314 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
315 root
= self
.tree
.AddRoot("wxPython Overview")
317 for item
in _treeList
:
318 child
= self
.tree
.AppendItem(root
, item
[0])
319 if not firstChild
: firstChild
= child
320 for childItem
in item
[1]:
321 theDemo
= self
.tree
.AppendItem(child
, childItem
)
322 self
.treeMap
[childItem
] = theDemo
324 self
.tree
.Expand(root
)
325 self
.tree
.Expand(firstChild
)
326 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
327 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
328 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
329 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
332 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
334 # Set up a wxHtmlWindow on the Overview Notebook page
335 # we put it in a panel first because there seems to be a
336 # refresh bug of some sort (wxGTK) when it is directly in
339 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
340 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
342 else: # hopefully I can remove this hacky code soon, see bug #216861
343 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
344 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
345 self
.nb
.AddPage(panel
, self
.overviewText
)
347 def OnOvrSize(evt
, ovr
=self
.ovr
):
348 ovr
.SetSize(evt
.GetSize())
350 EVT_SIZE(panel
, OnOvrSize
)
351 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
354 self
.SetOverview(self
.overviewText
, overview
)
357 # Set up a TextCtrl on the Demo Code Notebook page
358 self
.txt
= wxTextCtrl(self
.nb
, -1,
359 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
360 self
.nb
.AddPage(self
.txt
, "Demo Code")
363 # Set up a log on the View Log Notebook page
364 self
.log
= wxTextCtrl(splitter2
, -1,
365 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
367 # Set the wxWindows log target to be this textctrl
368 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
370 # But instead of the above we want to show how to use our own wxLog class
371 wxLog_SetActiveTarget(MyLog(self
.log
))
373 # for serious debugging
374 #wxLog_SetActiveTarget(wxLogStderr())
375 #wxLog_SetTraceMask(wxTraceMessages)
380 # add the windows to the splitter and split it.
381 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
382 splitter
.SplitVertically(self
.tree
, splitter2
)
384 splitter
.SetSashPosition(180, true
)
385 splitter
.SetMinimumPaneSize(20)
386 splitter2
.SetSashPosition(450, true
)
387 splitter2
.SetMinimumPaneSize(20)
391 # select initial items
392 self
.nb
.SetSelection(0)
393 self
.tree
.SelectItem(root
)
395 if len(sys
.argv
) == 2:
397 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
401 self
.tree
.SelectItem(selectedDemo
)
402 self
.tree
.EnsureVisible(selectedDemo
)
405 wxLogMessage('window handle: %s' % self
.GetHandle())
408 #---------------------------------------------
409 def WriteText(self
, text
):
410 if text
[-1:] == '\n':
415 def write(self
, txt
):
418 #---------------------------------------------
419 def OnItemExpanded(self
, event
):
420 item
= event
.GetItem()
421 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
424 #---------------------------------------------
425 def OnItemCollapsed(self
, event
):
426 item
= event
.GetItem()
427 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
430 #---------------------------------------------
431 def OnTreeLeftDown(self
, event
):
432 pt
= event
.GetPosition();
433 item
, flags
= self
.tree
.HitTest(pt
)
434 if item
== self
.tree
.GetSelection():
435 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
438 #---------------------------------------------
439 def OnSelChanged(self
, event
):
443 item
= event
.GetItem()
444 itemText
= self
.tree
.GetItemText(item
)
445 self
.RunDemo(itemText
)
448 #---------------------------------------------
449 def RunDemo(self
, itemText
):
451 if self
.nb
.GetPageCount() == 3:
452 if self
.nb
.GetSelection() == 2:
453 self
.nb
.SetSelection(0)
454 self
.nb
.DeletePage(2)
456 if itemText
== self
.overviewText
:
457 self
.GetDemoFile('Main.py')
458 self
.SetOverview(self
.overviewText
, overview
)
463 if os
.path
.exists(itemText
+ '.py'):
465 wxLogMessage("Running demo %s.py..." % itemText
)
467 self
.GetDemoFile(itemText
+ '.py')
468 module
= __import__(itemText
, globals())
469 self
.SetOverview(itemText
+ " Overview", module
.overview
)
474 # in case runTest is modal, make sure things look right...
478 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
480 self
.nb
.AddPage(self
.window
, 'Demo')
481 self
.nb
.SetSelection(2)
482 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
491 #---------------------------------------------
493 def GetDemoFile(self
, filename
):
496 self
.txt
.SetValue(open(filename
).read())
498 self
.txt
.WriteText("Cannot open %s file." % filename
)
500 self
.txt
.SetInsertionPoint(0)
501 self
.txt
.ShowPosition(0)
503 #---------------------------------------------
504 def SetOverview(self
, name
, text
):
505 self
.curOverview
= text
507 if lead
!= '<html>' and lead
!= '<HTML>':
508 text
= string
.join(string
.split(text
, '\n'), '<br>')
509 self
.ovr
.SetPage(text
)
510 self
.nb
.SetPageText(0, name
)
512 #---------------------------------------------
514 def OnFileExit(self
, *event
):
518 def OnHelpAbout(self
, event
):
519 from About
import MyAboutBox
520 about
= MyAboutBox(self
)
525 #---------------------------------------------
526 def OnCloseWindow(self
, event
):
530 if hasattr(self
, "tbicon"):
535 #---------------------------------------------
536 def OnIdle(self
, event
):
538 self
.otherWin
.Raise()
539 self
.window
= self
.otherWin
547 #---------------------------------------------
550 showTipText
= open(opj("data/showTips")).read()
551 showTip
, index
= eval(showTipText
)
553 showTip
, index
= (1, 0)
555 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
557 showTip
= wxShowTip(self
, tp
)
558 index
= tp
.GetCurrentTip()
559 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
562 #---------------------------------------------
563 def OnDemoMenu(self
, event
):
565 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
569 self
.tree
.SelectItem(selectedDemo
)
570 self
.tree
.EnsureVisible(selectedDemo
)
573 #---------------------------------------------
574 def OnTaskBarActivate(self
, evt
):
575 if self
.IsIconized():
577 if not self
.IsShown():
581 #---------------------------------------------
583 TBMENU_RESTORE
= 1000
586 def OnTaskBarMenu(self
, evt
):
588 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
589 menu
.Append(self
.TBMENU_CLOSE
, "Close")
590 self
.tbicon
.PopupMenu(menu
)
593 #---------------------------------------------
594 def OnTaskBarClose(self
, evt
):
597 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
598 # prod the main idle handler a bit to get the window to actually close
599 wxGetApp().ProcessIdle()
602 #---------------------------------------------
603 def OnIconfiy(self
, evt
):
604 wxLogMessage("OnIconfiy")
607 #---------------------------------------------
608 def OnMaximize(self
, evt
):
609 wxLogMessage("OnMaximize")
615 #---------------------------------------------------------------------------
616 #---------------------------------------------------------------------------
618 class MySplashScreen(wxSplashScreen
):
620 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
621 wxSplashScreen
.__init
__(self
, bmp
,
622 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
624 style
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
)
625 EVT_CLOSE(self
, self
.OnClose
)
627 def OnClose(self
, evt
):
628 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
630 evt
.Skip() # Make sure the default handler runs too...
636 Create and show the splash screen. It will then create and show
637 the main frame when it is time to do so.
639 wxInitAllImageHandlers()
640 splash
= MySplashScreen()
646 #---------------------------------------------------------------------------
650 demoPath
= os
.path
.dirname(__file__
)
654 app
= MyApp(wxPlatform
== "__WXMAC__")
658 #---------------------------------------------------------------------------
662 overview
= """<html><body>
665 Python is an interpreted, interactive, object-oriented programming
666 language often compared to Tcl, Perl, Scheme, or Java.
668 <p> Python combines remarkable power with very clear syntax. It has
669 modules, classes, exceptions, very high level dynamic data types, and
670 dynamic typing. There are interfaces to many system calls and
671 libraries, and new built-in modules are easily written in C or
672 C++. Python is also usable as an extension language for applications
673 that need a programmable interface. <p>
677 wxWindows is a free C++ framework designed to make cross-platform
678 programming child's play. Well, almost. wxWindows 2 supports Windows
679 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
680 underway. Other ports are under consideration. <p>
682 wxWindows is a set of libraries that allows C++ applications to
683 compile and run on several different types of computers, with minimal
684 source code changes. There is one library per supported GUI (such as
685 Motif, or Windows). As well as providing a common API (Application
686 Programming Interface) for GUI functionality, it provides
687 functionality for accessing some commonly-used operating system
688 facilities, such as copying or deleting files. wxWindows is a
689 'framework' in the sense that it provides a lot of built-in
690 functionality, which the application can use or replace as required,
691 thus saving a great deal of coding effort. Basic data structures such
692 as strings, linked lists and hash tables are also supported.
697 wxPython is a Python extension module that encapsulates the wxWindows
698 GUI classes. Currently it is only available for the Win32 and GTK
699 ports of wxWindows, but as soon as the other ports are brought up to
700 the same level as Win32 and GTK, it should be fairly trivial to
701 enable wxPython to be used with the new GUI.
705 The wxPython extension module attempts to mirror the class heiarchy
706 of wxWindows as closely as possible. This means that there is a
707 wxFrame class in wxPython that looks, smells, tastes and acts almost
708 the same as the wxFrame class in the C++ version. Unfortunately,
709 because of differences in the languages, wxPython doesn't match
710 wxWindows exactly, but the differences should be easy to absorb
711 because they are natural to Python. For example, some methods that
712 return multiple values via argument pointers in C++ will return a
713 tuple of values in Python.
717 There is still much to be done for wxPython, many classes still need
718 to be mirrored. Also, wxWindows is still somewhat of a moving target
719 so it is a bit of an effort just keeping wxPython up to date. On the
720 other hand, there are enough of the core classes completed that
721 useful applications can be written.
725 wxPython is close enough to the C++ version that the majority of
726 the wxPython documentation is actually just notes attached to the C++
727 documents that describe the places where wxPython is different. There
728 is also a series of sample programs included, and a series of
729 documentation pages that assist the programmer in getting started
735 #----------------------------------------------------------------------------
736 #----------------------------------------------------------------------------
738 if __name__
== '__main__':
741 #----------------------------------------------------------------------------