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', [
39 # managed windows == things with a caption you can close
40 ('Base Frames and Dialogs', [
52 'wxFindReplaceDialog',
58 'wxSingleChoiceDialog',
62 # dialogs form libraries
66 'wxMultipleChoiceDialog',
67 'wxScrolledMessageDialog',
71 ('Core Windows/Controls', [
103 # controls coming from other librairies
104 ('More Windows/Controls', [
111 'PyCrustWithFilling',
116 'wxDynamicSashWindow',
123 'wxMimeTypesManager',
126 'wxStyledTextCtrl_1',
127 'wxStyledTextCtrl_2',
130 # How to lay out the controls in a frame/dialog
137 'wxLayoutConstraints',
142 ('Process and Events', [
152 ('Clipboard and DnD', [
181 # need libs not coming with the demo
182 ('Objects using an external library', [
183 'ActiveXWrapper_Acrobat',
190 ('Check out the samples dir too', [
197 #---------------------------------------------------------------------------
199 class MyLog(wxPyLog
):
200 def __init__(self
, textCtrl
, logTime
=0):
201 wxPyLog
.__init
__(self
)
203 self
.logTime
= logTime
205 def DoLogString(self
, message
, timeStamp
):
207 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
209 self
.tc
.AppendText(message
+ '\n')
212 class MyTP(wxPyTipProvider
):
214 return "This is my tip"
216 #---------------------------------------------------------------------------
219 """Convert paths to the platform-specific separator"""
220 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
223 #---------------------------------------------------------------------------
225 class wxPythonDemo(wxFrame
):
226 overviewText
= "wxPython Overview"
228 def __init__(self
, parent
, id, title
):
229 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
230 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
232 self
.cwd
= os
.getcwd()
233 self
.curOverview
= ""
235 icon
= images
.getMondrianIcon()
238 if wxPlatform
== '__WXMSW__':
239 # setup a taskbar icon, and catch some events from it
240 self
.tbicon
= wxTaskBarIcon()
241 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
242 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
243 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
244 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
245 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
250 EVT_IDLE(self
, self
.OnIdle
)
251 EVT_CLOSE(self
, self
.OnCloseWindow
)
252 EVT_ICONIZE(self
, self
.OnIconfiy
)
253 EVT_MAXIMIZE(self
, self
.OnMaximize
)
256 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
258 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
259 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
261 def EmptyHandler(evt
): pass
262 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
263 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
265 # Prevent TreeCtrl from displaying all items after destruction when true
269 self
.mainmenu
= wxMenuBar()
272 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
273 EVT_MENU(self
, exitID
, self
.OnFileExit
)
274 self
.mainmenu
.Append(menu
, '&File')
278 for item
in _treeList
:
280 for childItem
in item
[1]:
282 submenu
.Append(mID
, childItem
)
283 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
284 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
285 self
.mainmenu
.Append(menu
, '&Demo')
291 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
292 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
293 self
.mainmenu
.Append(menu
, '&Help')
294 self
.SetMenuBar(self
.mainmenu
)
296 # set the menu accellerator table...
297 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
298 (wxACCEL_CTRL
, ord('H'), helpID
)])
299 self
.SetAcceleratorTable(aTable
)
305 self
.tree
= wxTreeCtrl(splitter
, tID
,
306 style
=wxTR_HAS_BUTTONS |
308 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
310 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
311 root
= self
.tree
.AddRoot("wxPython Overview")
313 for item
in _treeList
:
314 child
= self
.tree
.AppendItem(root
, item
[0])
315 if not firstChild
: firstChild
= child
316 for childItem
in item
[1]:
317 theDemo
= self
.tree
.AppendItem(child
, childItem
)
318 self
.treeMap
[childItem
] = theDemo
320 self
.tree
.Expand(root
)
321 self
.tree
.Expand(firstChild
)
322 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
323 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
324 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
325 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
328 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
330 # Set up a wxHtmlWindow on the Overview Notebook page
331 # we put it in a panel first because there seems to be a
332 # refresh bug of some sort (wxGTK) when it is directly in
335 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
336 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
338 else: # hopefully I can remove this hacky code soon, see bug #216861
339 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
340 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
341 self
.nb
.AddPage(panel
, self
.overviewText
)
343 def OnOvrSize(evt
, ovr
=self
.ovr
):
344 ovr
.SetSize(evt
.GetSize())
346 EVT_SIZE(panel
, OnOvrSize
)
347 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
350 self
.SetOverview(self
.overviewText
, overview
)
353 # Set up a TextCtrl on the Demo Code Notebook page
354 self
.txt
= wxTextCtrl(self
.nb
, -1,
355 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
356 self
.nb
.AddPage(self
.txt
, "Demo Code")
359 # Set up a log on the View Log Notebook page
360 self
.log
= wxTextCtrl(splitter2
, -1,
361 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
363 # Set the wxWindows log target to be this textctrl
364 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
366 # But instead of the above we want to show how to use our own wxLog class
367 wxLog_SetActiveTarget(MyLog(self
.log
))
369 # for serious debugging
370 #wxLog_SetActiveTarget(wxLogStderr())
371 #wxLog_SetTraceMask(wxTraceMessages)
376 # add the windows to the splitter and split it.
377 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
378 splitter
.SplitVertically(self
.tree
, splitter2
)
380 splitter
.SetSashPosition(180, true
)
381 splitter
.SetMinimumPaneSize(20)
382 splitter2
.SetSashPosition(450, true
)
383 splitter2
.SetMinimumPaneSize(20)
387 # select initial items
388 self
.nb
.SetSelection(0)
389 self
.tree
.SelectItem(root
)
391 if len(sys
.argv
) == 2:
393 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
397 self
.tree
.SelectItem(selectedDemo
)
398 self
.tree
.EnsureVisible(selectedDemo
)
401 wxLogMessage('window handle: %s' % self
.GetHandle())
404 #---------------------------------------------
405 def WriteText(self
, text
):
406 if text
[-1:] == '\n':
411 def write(self
, txt
):
414 #---------------------------------------------
415 def OnItemExpanded(self
, event
):
416 item
= event
.GetItem()
417 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
420 #---------------------------------------------
421 def OnItemCollapsed(self
, event
):
422 item
= event
.GetItem()
423 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
426 #---------------------------------------------
427 def OnTreeLeftDown(self
, event
):
428 pt
= event
.GetPosition();
429 item
, flags
= self
.tree
.HitTest(pt
)
430 if item
== self
.tree
.GetSelection():
431 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
434 #---------------------------------------------
435 def OnSelChanged(self
, event
):
439 item
= event
.GetItem()
440 itemText
= self
.tree
.GetItemText(item
)
441 self
.RunDemo(itemText
)
444 #---------------------------------------------
445 def RunDemo(self
, itemText
):
447 if self
.nb
.GetPageCount() == 3:
448 if self
.nb
.GetSelection() == 2:
449 self
.nb
.SetSelection(0)
450 self
.nb
.DeletePage(2)
452 if itemText
== self
.overviewText
:
453 self
.GetDemoFile('Main.py')
454 self
.SetOverview(self
.overviewText
, overview
)
459 if os
.path
.exists(itemText
+ '.py'):
461 wxLogMessage("Running demo %s.py..." % itemText
)
463 self
.GetDemoFile(itemText
+ '.py')
464 module
= __import__(itemText
, globals())
465 self
.SetOverview(itemText
+ " Overview", module
.overview
)
470 # in case runTest is modal, make sure things look right...
474 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
476 self
.nb
.AddPage(self
.window
, 'Demo')
477 self
.nb
.SetSelection(2)
478 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
487 #---------------------------------------------
489 def GetDemoFile(self
, filename
):
492 self
.txt
.SetValue(open(filename
).read())
494 self
.txt
.WriteText("Cannot open %s file." % filename
)
496 self
.txt
.SetInsertionPoint(0)
497 self
.txt
.ShowPosition(0)
499 #---------------------------------------------
500 def SetOverview(self
, name
, text
):
501 self
.curOverview
= text
503 if lead
!= '<html>' and lead
!= '<HTML>':
504 text
= string
.join(string
.split(text
, '\n'), '<br>')
505 self
.ovr
.SetPage(text
)
506 self
.nb
.SetPageText(0, name
)
508 #---------------------------------------------
510 def OnFileExit(self
, *event
):
514 def OnHelpAbout(self
, event
):
515 from About
import MyAboutBox
516 about
= MyAboutBox(self
)
521 #---------------------------------------------
522 def OnCloseWindow(self
, event
):
526 if hasattr(self
, "tbicon"):
531 #---------------------------------------------
532 def OnIdle(self
, event
):
534 self
.otherWin
.Raise()
535 self
.window
= self
.otherWin
543 #---------------------------------------------
546 showTipText
= open(opj("data/showTips")).read()
547 showTip
, index
= eval(showTipText
)
549 showTip
, index
= (1, 0)
551 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
553 showTip
= wxShowTip(self
, tp
)
554 index
= tp
.GetCurrentTip()
555 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
558 #---------------------------------------------
559 def OnDemoMenu(self
, event
):
561 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
565 self
.tree
.SelectItem(selectedDemo
)
566 self
.tree
.EnsureVisible(selectedDemo
)
569 #---------------------------------------------
570 def OnTaskBarActivate(self
, evt
):
571 if self
.IsIconized():
573 if not self
.IsShown():
577 #---------------------------------------------
579 TBMENU_RESTORE
= 1000
582 def OnTaskBarMenu(self
, evt
):
584 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
585 menu
.Append(self
.TBMENU_CLOSE
, "Close")
586 self
.tbicon
.PopupMenu(menu
)
589 #---------------------------------------------
590 def OnTaskBarClose(self
, evt
):
593 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
594 # prod the main idle handler a bit to get the window to actually close
595 wxGetApp().ProcessIdle()
598 #---------------------------------------------
599 def OnIconfiy(self
, evt
):
600 wxLogMessage("OnIconfiy")
603 #---------------------------------------------
604 def OnMaximize(self
, evt
):
605 wxLogMessage("OnMaximize")
611 #---------------------------------------------------------------------------
612 #---------------------------------------------------------------------------
614 class MySplashScreen(wxSplashScreen
):
616 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
617 wxSplashScreen
.__init
__(self
, bmp
,
618 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
620 style
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
)
621 EVT_CLOSE(self
, self
.OnClose
)
623 def OnClose(self
, evt
):
624 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
626 evt
.Skip() # Make sure the default handler runs too...
632 Create and show the splash screen. It will then create and show
633 the main frame when it is time to do so.
635 wxInitAllImageHandlers()
636 splash
= MySplashScreen()
642 #---------------------------------------------------------------------------
646 demoPath
= os
.path
.dirname(__file__
)
650 app
= MyApp(wxPlatform
== "__WXMAC__")
654 #---------------------------------------------------------------------------
658 overview
= """<html><body>
661 Python is an interpreted, interactive, object-oriented programming
662 language often compared to Tcl, Perl, Scheme, or Java.
664 <p> Python combines remarkable power with very clear syntax. It has
665 modules, classes, exceptions, very high level dynamic data types, and
666 dynamic typing. There are interfaces to many system calls and
667 libraries, and new built-in modules are easily written in C or
668 C++. Python is also usable as an extension language for applications
669 that need a programmable interface. <p>
673 wxWindows is a free C++ framework designed to make cross-platform
674 programming child's play. Well, almost. wxWindows 2 supports Windows
675 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
676 underway. Other ports are under consideration. <p>
678 wxWindows is a set of libraries that allows C++ applications to
679 compile and run on several different types of computers, with minimal
680 source code changes. There is one library per supported GUI (such as
681 Motif, or Windows). As well as providing a common API (Application
682 Programming Interface) for GUI functionality, it provides
683 functionality for accessing some commonly-used operating system
684 facilities, such as copying or deleting files. wxWindows is a
685 'framework' in the sense that it provides a lot of built-in
686 functionality, which the application can use or replace as required,
687 thus saving a great deal of coding effort. Basic data structures such
688 as strings, linked lists and hash tables are also supported.
693 wxPython is a Python extension module that encapsulates the wxWindows
694 GUI classes. Currently it is only available for the Win32 and GTK
695 ports of wxWindows, but as soon as the other ports are brought up to
696 the same level as Win32 and GTK, it should be fairly trivial to
697 enable wxPython to be used with the new GUI.
701 The wxPython extension module attempts to mirror the class heiarchy
702 of wxWindows as closely as possible. This means that there is a
703 wxFrame class in wxPython that looks, smells, tastes and acts almost
704 the same as the wxFrame class in the C++ version. Unfortunately,
705 because of differences in the languages, wxPython doesn't match
706 wxWindows exactly, but the differences should be easy to absorb
707 because they are natural to Python. For example, some methods that
708 return multiple values via argument pointers in C++ will return a
709 tuple of values in Python.
713 There is still much to be done for wxPython, many classes still need
714 to be mirrored. Also, wxWindows is still somewhat of a moving target
715 so it is a bit of an effort just keeping wxPython up to date. On the
716 other hand, there are enough of the core classes completed that
717 useful applications can be written.
721 wxPython is close enough to the C++ version that the majority of
722 the wxPython documentation is actually just notes attached to the C++
723 documents that describe the places where wxPython is different. There
724 is also a series of sample programs included, and a series of
725 documentation pages that assist the programmer in getting started
731 #----------------------------------------------------------------------------
732 #----------------------------------------------------------------------------
734 if __name__
== '__main__':
737 #----------------------------------------------------------------------------