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', [
40 # managed windows == things with a caption you can close
41 ('Base Frames and Dialogs', [
53 'wxFindReplaceDialog',
59 'wxSingleChoiceDialog',
63 # dialogs form libraries
67 'wxMultipleChoiceDialog',
68 'wxScrolledMessageDialog',
72 ('Core Windows/Controls', [
104 # controls coming from other librairies
105 ('More Windows/Controls', [
112 'PyCrustWithFilling',
117 'wxDynamicSashWindow',
120 #'wxFloatBar', deprecated
124 'wxMimeTypesManager',
125 #'wxMVCTree', deprecated
127 'wxStyledTextCtrl_1',
128 'wxStyledTextCtrl_2',
131 # How to lay out the controls in a frame/dialog
138 'wxLayoutConstraints',
143 ('Process and Events', [
154 ('Clipboard and DnD', [
183 # need libs not coming with the demo
184 ('Objects using an external library', [
185 'ActiveXWrapper_Acrobat',
192 ('Check out the samples dir too', [
199 #---------------------------------------------------------------------------
201 class MyLog(wxPyLog
):
202 def __init__(self
, textCtrl
, logTime
=0):
203 wxPyLog
.__init
__(self
)
205 self
.logTime
= logTime
207 def DoLogString(self
, message
, timeStamp
):
209 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
211 self
.tc
.AppendText(message
+ '\n')
214 class MyTP(wxPyTipProvider
):
216 return "This is my tip"
218 #---------------------------------------------------------------------------
221 """Convert paths to the platform-specific separator"""
222 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
225 #---------------------------------------------------------------------------
227 class wxPythonDemo(wxFrame
):
228 overviewText
= "wxPython Overview"
230 def __init__(self
, parent
, id, title
):
231 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
232 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
234 self
.cwd
= os
.getcwd()
235 self
.curOverview
= ""
237 icon
= images
.getMondrianIcon()
240 if wxPlatform
== '__WXMSW__':
241 # setup a taskbar icon, and catch some events from it
242 self
.tbicon
= wxTaskBarIcon()
243 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
244 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
245 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
246 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
247 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
252 EVT_IDLE(self
, self
.OnIdle
)
253 EVT_CLOSE(self
, self
.OnCloseWindow
)
254 EVT_ICONIZE(self
, self
.OnIconfiy
)
255 EVT_MAXIMIZE(self
, self
.OnMaximize
)
258 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
260 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
261 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
263 def EmptyHandler(evt
): pass
264 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
265 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
267 # Prevent TreeCtrl from displaying all items after destruction when true
271 self
.mainmenu
= wxMenuBar()
274 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
275 EVT_MENU(self
, exitID
, self
.OnFileExit
)
276 self
.mainmenu
.Append(menu
, '&File')
280 for item
in _treeList
:
282 for childItem
in item
[1]:
284 submenu
.Append(mID
, childItem
)
285 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
286 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
287 self
.mainmenu
.Append(menu
, '&Demo')
293 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
294 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
295 self
.mainmenu
.Append(menu
, '&Help')
296 self
.SetMenuBar(self
.mainmenu
)
298 # set the menu accellerator table...
299 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
300 (wxACCEL_CTRL
, ord('H'), helpID
)])
301 self
.SetAcceleratorTable(aTable
)
307 self
.tree
= wxTreeCtrl(splitter
, tID
,
308 style
=wxTR_HAS_BUTTONS |
309 wxTR_HAS_VARIABLE_ROW_HEIGHT
312 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
313 root
= self
.tree
.AddRoot("wxPython Overview")
315 for item
in _treeList
:
316 child
= self
.tree
.AppendItem(root
, item
[0])
317 if not firstChild
: firstChild
= child
318 for childItem
in item
[1]:
319 theDemo
= self
.tree
.AppendItem(child
, childItem
)
320 self
.treeMap
[childItem
] = theDemo
322 self
.tree
.Expand(root
)
323 self
.tree
.Expand(firstChild
)
324 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
325 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
326 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
327 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
330 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
332 # Set up a wxHtmlWindow on the Overview Notebook page
333 # we put it in a panel first because there seems to be a
334 # refresh bug of some sort (wxGTK) when it is directly in
337 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
338 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
340 else: # hopefully I can remove this hacky code soon, see bug #216861
341 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
342 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
343 self
.nb
.AddPage(panel
, self
.overviewText
)
345 def OnOvrSize(evt
, ovr
=self
.ovr
):
346 ovr
.SetSize(evt
.GetSize())
348 EVT_SIZE(panel
, OnOvrSize
)
349 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
352 self
.SetOverview(self
.overviewText
, overview
)
355 # Set up a TextCtrl on the Demo Code Notebook page
356 self
.txt
= wxTextCtrl(self
.nb
, -1,
357 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
358 self
.nb
.AddPage(self
.txt
, "Demo Code")
361 # Set up a log on the View Log Notebook page
362 self
.log
= wxTextCtrl(splitter2
, -1,
363 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
365 # Set the wxWindows log target to be this textctrl
366 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
368 # But instead of the above we want to show how to use our own wxLog class
369 wxLog_SetActiveTarget(MyLog(self
.log
))
371 # for serious debugging
372 #wxLog_SetActiveTarget(wxLogStderr())
373 #wxLog_SetTraceMask(wxTraceMessages)
378 # add the windows to the splitter and split it.
379 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
380 splitter
.SplitVertically(self
.tree
, splitter2
)
382 splitter
.SetSashPosition(180, true
)
383 splitter
.SetMinimumPaneSize(20)
384 splitter2
.SetSashPosition(450, true
)
385 splitter2
.SetMinimumPaneSize(20)
389 # select initial items
390 self
.nb
.SetSelection(0)
391 self
.tree
.SelectItem(root
)
393 if len(sys
.argv
) == 2:
395 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
399 self
.tree
.SelectItem(selectedDemo
)
400 self
.tree
.EnsureVisible(selectedDemo
)
403 wxLogMessage('window handle: %s' % self
.GetHandle())
406 #---------------------------------------------
407 def WriteText(self
, text
):
408 if text
[-1:] == '\n':
413 def write(self
, txt
):
416 #---------------------------------------------
417 def OnItemExpanded(self
, event
):
418 item
= event
.GetItem()
419 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
422 #---------------------------------------------
423 def OnItemCollapsed(self
, event
):
424 item
= event
.GetItem()
425 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
428 #---------------------------------------------
429 def OnTreeLeftDown(self
, event
):
430 pt
= event
.GetPosition();
431 item
, flags
= self
.tree
.HitTest(pt
)
432 if item
== self
.tree
.GetSelection():
433 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
436 #---------------------------------------------
437 def OnSelChanged(self
, event
):
441 item
= event
.GetItem()
442 itemText
= self
.tree
.GetItemText(item
)
443 self
.RunDemo(itemText
)
446 #---------------------------------------------
447 def RunDemo(self
, itemText
):
449 if self
.nb
.GetPageCount() == 3:
450 if self
.nb
.GetSelection() == 2:
451 self
.nb
.SetSelection(0)
452 self
.nb
.DeletePage(2)
454 if itemText
== self
.overviewText
:
455 self
.GetDemoFile('Main.py')
456 self
.SetOverview(self
.overviewText
, overview
)
461 if os
.path
.exists(itemText
+ '.py'):
463 wxLogMessage("Running demo %s.py..." % itemText
)
465 self
.GetDemoFile(itemText
+ '.py')
466 module
= __import__(itemText
, globals())
467 self
.SetOverview(itemText
+ " Overview", module
.overview
)
472 # in case runTest is modal, make sure things look right...
476 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
478 self
.nb
.AddPage(self
.window
, 'Demo')
479 self
.nb
.SetSelection(2)
480 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
489 #---------------------------------------------
491 def GetDemoFile(self
, filename
):
494 self
.txt
.SetValue(open(filename
).read())
496 self
.txt
.WriteText("Cannot open %s file." % filename
)
498 self
.txt
.SetInsertionPoint(0)
499 self
.txt
.ShowPosition(0)
501 #---------------------------------------------
502 def SetOverview(self
, name
, text
):
503 self
.curOverview
= text
505 if lead
!= '<html>' and lead
!= '<HTML>':
506 text
= string
.join(string
.split(text
, '\n'), '<br>')
507 self
.ovr
.SetPage(text
)
508 self
.nb
.SetPageText(0, name
)
510 #---------------------------------------------
512 def OnFileExit(self
, *event
):
516 def OnHelpAbout(self
, event
):
517 from About
import MyAboutBox
518 about
= MyAboutBox(self
)
523 #---------------------------------------------
524 def OnCloseWindow(self
, event
):
528 if hasattr(self
, "tbicon"):
533 #---------------------------------------------
534 def OnIdle(self
, event
):
536 self
.otherWin
.Raise()
537 self
.window
= self
.otherWin
545 #---------------------------------------------
548 showTipText
= open(opj("data/showTips")).read()
549 showTip
, index
= eval(showTipText
)
551 showTip
, index
= (1, 0)
553 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
555 showTip
= wxShowTip(self
, tp
)
556 index
= tp
.GetCurrentTip()
557 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
560 #---------------------------------------------
561 def OnDemoMenu(self
, event
):
563 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
567 self
.tree
.SelectItem(selectedDemo
)
568 self
.tree
.EnsureVisible(selectedDemo
)
571 #---------------------------------------------
572 def OnTaskBarActivate(self
, evt
):
573 if self
.IsIconized():
575 if not self
.IsShown():
579 #---------------------------------------------
581 TBMENU_RESTORE
= 1000
584 def OnTaskBarMenu(self
, evt
):
586 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
587 menu
.Append(self
.TBMENU_CLOSE
, "Close")
588 self
.tbicon
.PopupMenu(menu
)
591 #---------------------------------------------
592 def OnTaskBarClose(self
, evt
):
595 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
596 # prod the main idle handler a bit to get the window to actually close
597 wxGetApp().ProcessIdle()
600 #---------------------------------------------
601 def OnIconfiy(self
, evt
):
602 wxLogMessage("OnIconfiy")
605 #---------------------------------------------
606 def OnMaximize(self
, evt
):
607 wxLogMessage("OnMaximize")
613 #---------------------------------------------------------------------------
614 #---------------------------------------------------------------------------
616 class MySplashScreen(wxSplashScreen
):
618 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
619 wxSplashScreen
.__init
__(self
, bmp
,
620 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
622 style
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
)
623 EVT_CLOSE(self
, self
.OnClose
)
625 def OnClose(self
, evt
):
626 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
628 evt
.Skip() # Make sure the default handler runs too...
634 Create and show the splash screen. It will then create and show
635 the main frame when it is time to do so.
637 wxInitAllImageHandlers()
638 splash
= MySplashScreen()
644 #---------------------------------------------------------------------------
648 demoPath
= os
.path
.dirname(__file__
)
652 app
= MyApp(wxPlatform
== "__WXMAC__")
656 #---------------------------------------------------------------------------
660 overview
= """<html><body>
663 Python is an interpreted, interactive, object-oriented programming
664 language often compared to Tcl, Perl, Scheme, or Java.
666 <p> Python combines remarkable power with very clear syntax. It has
667 modules, classes, exceptions, very high level dynamic data types, and
668 dynamic typing. There are interfaces to many system calls and
669 libraries, and new built-in modules are easily written in C or
670 C++. Python is also usable as an extension language for applications
671 that need a programmable interface. <p>
675 wxWindows is a free C++ framework designed to make cross-platform
676 programming child's play. Well, almost. wxWindows 2 supports Windows
677 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
678 underway. Other ports are under consideration. <p>
680 wxWindows is a set of libraries that allows C++ applications to
681 compile and run on several different types of computers, with minimal
682 source code changes. There is one library per supported GUI (such as
683 Motif, or Windows). As well as providing a common API (Application
684 Programming Interface) for GUI functionality, it provides
685 functionality for accessing some commonly-used operating system
686 facilities, such as copying or deleting files. wxWindows is a
687 'framework' in the sense that it provides a lot of built-in
688 functionality, which the application can use or replace as required,
689 thus saving a great deal of coding effort. Basic data structures such
690 as strings, linked lists and hash tables are also supported.
695 wxPython is a Python extension module that encapsulates the wxWindows
696 GUI classes. Currently it is only available for the Win32 and GTK
697 ports of wxWindows, but as soon as the other ports are brought up to
698 the same level as Win32 and GTK, it should be fairly trivial to
699 enable wxPython to be used with the new GUI.
703 The wxPython extension module attempts to mirror the class heiarchy
704 of wxWindows as closely as possible. This means that there is a
705 wxFrame class in wxPython that looks, smells, tastes and acts almost
706 the same as the wxFrame class in the C++ version. Unfortunately,
707 because of differences in the languages, wxPython doesn't match
708 wxWindows exactly, but the differences should be easy to absorb
709 because they are natural to Python. For example, some methods that
710 return multiple values via argument pointers in C++ will return a
711 tuple of values in Python.
715 There is still much to be done for wxPython, many classes still need
716 to be mirrored. Also, wxWindows is still somewhat of a moving target
717 so it is a bit of an effort just keeping wxPython up to date. On the
718 other hand, there are enough of the core classes completed that
719 useful applications can be written.
723 wxPython is close enough to the C++ version that the majority of
724 the wxPython documentation is actually just notes attached to the C++
725 documents that describe the places where wxPython is different. There
726 is also a series of sample programs included, and a series of
727 documentation pages that assist the programmer in getting started
733 #----------------------------------------------------------------------------
734 #----------------------------------------------------------------------------
736 if __name__
== '__main__':
739 #----------------------------------------------------------------------------