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 'wxXmlResourceHandler',
42 # managed windows == things with a caption you can close
43 ('Base Frames and Dialogs', [
56 'wxFindReplaceDialog',
62 'wxSingleChoiceDialog',
66 # dialogs from libraries
70 'wxMultipleChoiceDialog',
71 'wxScrolledMessageDialog',
75 ('Core Windows/Controls', [
107 # controls coming from other librairies
108 ('More Windows/Controls', [
115 'PyCrustWithFilling',
120 'wxDynamicSashWindow',
123 #'wxFloatBar', deprecated
127 'wxMimeTypesManager',
128 #'wxMVCTree', deprecated
130 'wxStyledTextCtrl_1',
131 'wxStyledTextCtrl_2',
134 # How to lay out the controls in a frame/dialog
141 'wxLayoutConstraints',
143 'wxXmlResourceHandler',
147 ('Process and Events', [
158 ('Clipboard and DnD', [
187 # need libs not coming with the demo
188 ('Objects using an external library', [
189 'ActiveXWrapper_Acrobat',
196 ('Check out the samples dir too', [
203 #---------------------------------------------------------------------------
205 class MyLog(wxPyLog
):
206 def __init__(self
, textCtrl
, logTime
=0):
207 wxPyLog
.__init
__(self
)
209 self
.logTime
= logTime
211 def DoLogString(self
, message
, timeStamp
):
213 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
215 self
.tc
.AppendText(message
+ '\n')
218 class MyTP(wxPyTipProvider
):
220 return "This is my tip"
222 #---------------------------------------------------------------------------
225 """Convert paths to the platform-specific separator"""
226 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
229 #---------------------------------------------------------------------------
231 class wxPythonDemo(wxFrame
):
232 overviewText
= "wxPython Overview"
234 def __init__(self
, parent
, id, title
):
235 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
236 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
238 self
.cwd
= os
.getcwd()
239 self
.curOverview
= ""
241 icon
= images
.getMondrianIcon()
244 if wxPlatform
== '__WXMSW__':
245 # setup a taskbar icon, and catch some events from it
246 self
.tbicon
= wxTaskBarIcon()
247 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
248 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
249 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
250 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
251 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
256 EVT_IDLE(self
, self
.OnIdle
)
257 EVT_CLOSE(self
, self
.OnCloseWindow
)
258 EVT_ICONIZE(self
, self
.OnIconfiy
)
259 EVT_MAXIMIZE(self
, self
.OnMaximize
)
262 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
264 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
265 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
267 def EmptyHandler(evt
): pass
268 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
269 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
271 # Prevent TreeCtrl from displaying all items after destruction when true
275 self
.mainmenu
= wxMenuBar()
278 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
279 EVT_MENU(self
, exitID
, self
.OnFileExit
)
280 self
.mainmenu
.Append(menu
, '&File')
284 for item
in _treeList
:
286 for childItem
in item
[1]:
288 submenu
.Append(mID
, childItem
)
289 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
290 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
291 self
.mainmenu
.Append(menu
, '&Demo')
297 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
298 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
299 self
.mainmenu
.Append(menu
, '&Help')
300 self
.SetMenuBar(self
.mainmenu
)
302 # set the menu accellerator table...
303 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
304 (wxACCEL_CTRL
, ord('H'), helpID
)])
305 self
.SetAcceleratorTable(aTable
)
311 self
.tree
= wxTreeCtrl(splitter
, tID
,
312 style
=wxTR_HAS_BUTTONS |
313 wxTR_HAS_VARIABLE_ROW_HEIGHT
316 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
317 root
= self
.tree
.AddRoot("wxPython Overview")
319 for item
in _treeList
:
320 child
= self
.tree
.AppendItem(root
, item
[0])
321 if not firstChild
: firstChild
= child
322 for childItem
in item
[1]:
323 theDemo
= self
.tree
.AppendItem(child
, childItem
)
324 self
.treeMap
[childItem
] = theDemo
326 self
.tree
.Expand(root
)
327 self
.tree
.Expand(firstChild
)
328 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
329 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
330 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
331 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
334 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
336 # Set up a wxHtmlWindow on the Overview Notebook page
337 # we put it in a panel first because there seems to be a
338 # refresh bug of some sort (wxGTK) when it is directly in
341 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
342 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
344 else: # hopefully I can remove this hacky code soon, see bug #216861
345 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
346 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
347 self
.nb
.AddPage(panel
, self
.overviewText
)
349 def OnOvrSize(evt
, ovr
=self
.ovr
):
350 ovr
.SetSize(evt
.GetSize())
352 EVT_SIZE(panel
, OnOvrSize
)
353 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
356 self
.SetOverview(self
.overviewText
, overview
)
359 # Set up a TextCtrl on the Demo Code Notebook page
360 self
.txt
= wxTextCtrl(self
.nb
, -1,
361 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
362 self
.nb
.AddPage(self
.txt
, "Demo Code")
365 # Set up a log on the View Log Notebook page
366 self
.log
= wxTextCtrl(splitter2
, -1,
367 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
369 # Set the wxWindows log target to be this textctrl
370 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
372 # But instead of the above we want to show how to use our own wxLog class
373 wxLog_SetActiveTarget(MyLog(self
.log
))
375 # for serious debugging
376 #wxLog_SetActiveTarget(wxLogStderr())
377 #wxLog_SetTraceMask(wxTraceMessages)
382 # add the windows to the splitter and split it.
383 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
384 splitter
.SplitVertically(self
.tree
, splitter2
)
386 splitter
.SetSashPosition(180, true
)
387 splitter
.SetMinimumPaneSize(20)
388 splitter2
.SetSashPosition(450, true
)
389 splitter2
.SetMinimumPaneSize(20)
393 # select initial items
394 self
.nb
.SetSelection(0)
395 self
.tree
.SelectItem(root
)
397 if len(sys
.argv
) == 2:
399 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
403 self
.tree
.SelectItem(selectedDemo
)
404 self
.tree
.EnsureVisible(selectedDemo
)
407 wxLogMessage('window handle: %s' % self
.GetHandle())
410 #---------------------------------------------
411 def WriteText(self
, text
):
412 if text
[-1:] == '\n':
417 def write(self
, txt
):
420 #---------------------------------------------
421 def OnItemExpanded(self
, event
):
422 item
= event
.GetItem()
423 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
426 #---------------------------------------------
427 def OnItemCollapsed(self
, event
):
428 item
= event
.GetItem()
429 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
432 #---------------------------------------------
433 def OnTreeLeftDown(self
, event
):
434 pt
= event
.GetPosition();
435 item
, flags
= self
.tree
.HitTest(pt
)
436 if item
== self
.tree
.GetSelection():
437 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
440 #---------------------------------------------
441 def OnSelChanged(self
, event
):
445 item
= event
.GetItem()
446 itemText
= self
.tree
.GetItemText(item
)
447 self
.RunDemo(itemText
)
450 #---------------------------------------------
451 def RunDemo(self
, itemText
):
453 if self
.nb
.GetPageCount() == 3:
454 if self
.nb
.GetSelection() == 2:
455 self
.nb
.SetSelection(0)
456 self
.nb
.DeletePage(2)
458 if itemText
== self
.overviewText
:
459 self
.GetDemoFile('Main.py')
460 self
.SetOverview(self
.overviewText
, overview
)
465 if os
.path
.exists(itemText
+ '.py'):
467 wxLogMessage("Running demo %s.py..." % itemText
)
469 self
.GetDemoFile(itemText
+ '.py')
470 module
= __import__(itemText
, globals())
471 self
.SetOverview(itemText
+ " Overview", module
.overview
)
476 # in case runTest is modal, make sure things look right...
480 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
482 self
.nb
.AddPage(self
.window
, 'Demo')
483 self
.nb
.SetSelection(2)
484 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
493 #---------------------------------------------
495 def GetDemoFile(self
, filename
):
498 self
.txt
.SetValue(open(filename
).read())
500 self
.txt
.WriteText("Cannot open %s file." % filename
)
502 self
.txt
.SetInsertionPoint(0)
503 self
.txt
.ShowPosition(0)
505 #---------------------------------------------
506 def SetOverview(self
, name
, text
):
507 self
.curOverview
= text
509 if lead
!= '<html>' and lead
!= '<HTML>':
510 text
= string
.join(string
.split(text
, '\n'), '<br>')
511 self
.ovr
.SetPage(text
)
512 self
.nb
.SetPageText(0, name
)
514 #---------------------------------------------
516 def OnFileExit(self
, *event
):
520 def OnHelpAbout(self
, event
):
521 from About
import MyAboutBox
522 about
= MyAboutBox(self
)
527 #---------------------------------------------
528 def OnCloseWindow(self
, event
):
532 if hasattr(self
, "tbicon"):
537 #---------------------------------------------
538 def OnIdle(self
, event
):
540 self
.otherWin
.Raise()
541 self
.window
= self
.otherWin
549 #---------------------------------------------
552 showTipText
= open(opj("data/showTips")).read()
553 showTip
, index
= eval(showTipText
)
555 showTip
, index
= (1, 0)
557 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
559 showTip
= wxShowTip(self
, tp
)
560 index
= tp
.GetCurrentTip()
561 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
564 #---------------------------------------------
565 def OnDemoMenu(self
, event
):
567 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
571 self
.tree
.SelectItem(selectedDemo
)
572 self
.tree
.EnsureVisible(selectedDemo
)
575 #---------------------------------------------
576 def OnTaskBarActivate(self
, evt
):
577 if self
.IsIconized():
579 if not self
.IsShown():
583 #---------------------------------------------
585 TBMENU_RESTORE
= 1000
588 def OnTaskBarMenu(self
, evt
):
590 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
591 menu
.Append(self
.TBMENU_CLOSE
, "Close")
592 self
.tbicon
.PopupMenu(menu
)
595 #---------------------------------------------
596 def OnTaskBarClose(self
, evt
):
599 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
600 # prod the main idle handler a bit to get the window to actually close
601 wxGetApp().ProcessIdle()
604 #---------------------------------------------
605 def OnIconfiy(self
, evt
):
606 wxLogMessage("OnIconfiy")
609 #---------------------------------------------
610 def OnMaximize(self
, evt
):
611 wxLogMessage("OnMaximize")
617 #---------------------------------------------------------------------------
618 #---------------------------------------------------------------------------
620 class MySplashScreen(wxSplashScreen
):
622 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
623 wxSplashScreen
.__init
__(self
, bmp
,
624 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
626 style
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
)
627 EVT_CLOSE(self
, self
.OnClose
)
629 def OnClose(self
, evt
):
630 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
632 evt
.Skip() # Make sure the default handler runs too...
638 Create and show the splash screen. It will then create and show
639 the main frame when it is time to do so.
641 wxInitAllImageHandlers()
642 splash
= MySplashScreen()
648 #---------------------------------------------------------------------------
652 demoPath
= os
.path
.dirname(__file__
)
656 app
= MyApp(wxPlatform
== "__WXMAC__")
660 #---------------------------------------------------------------------------
664 overview
= """<html><body>
667 Python is an interpreted, interactive, object-oriented programming
668 language often compared to Tcl, Perl, Scheme, or Java.
670 <p> Python combines remarkable power with very clear syntax. It has
671 modules, classes, exceptions, very high level dynamic data types, and
672 dynamic typing. There are interfaces to many system calls and
673 libraries, and new built-in modules are easily written in C or
674 C++. Python is also usable as an extension language for applications
675 that need a programmable interface. <p>
679 wxWindows is a free C++ framework designed to make cross-platform
680 programming child's play. Well, almost. wxWindows 2 supports Windows
681 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
682 underway. Other ports are under consideration. <p>
684 wxWindows is a set of libraries that allows C++ applications to
685 compile and run on several different types of computers, with minimal
686 source code changes. There is one library per supported GUI (such as
687 Motif, or Windows). As well as providing a common API (Application
688 Programming Interface) for GUI functionality, it provides
689 functionality for accessing some commonly-used operating system
690 facilities, such as copying or deleting files. wxWindows is a
691 'framework' in the sense that it provides a lot of built-in
692 functionality, which the application can use or replace as required,
693 thus saving a great deal of coding effort. Basic data structures such
694 as strings, linked lists and hash tables are also supported.
699 wxPython is a Python extension module that encapsulates the wxWindows
700 GUI classes. Currently it is only available for the Win32 and GTK
701 ports of wxWindows, but as soon as the other ports are brought up to
702 the same level as Win32 and GTK, it should be fairly trivial to
703 enable wxPython to be used with the new GUI.
707 The wxPython extension module attempts to mirror the class heiarchy
708 of wxWindows as closely as possible. This means that there is a
709 wxFrame class in wxPython that looks, smells, tastes and acts almost
710 the same as the wxFrame class in the C++ version. Unfortunately,
711 because of differences in the languages, wxPython doesn't match
712 wxWindows exactly, but the differences should be easy to absorb
713 because they are natural to Python. For example, some methods that
714 return multiple values via argument pointers in C++ will return a
715 tuple of values in Python.
719 There is still much to be done for wxPython, many classes still need
720 to be mirrored. Also, wxWindows is still somewhat of a moving target
721 so it is a bit of an effort just keeping wxPython up to date. On the
722 other hand, there are enough of the core classes completed that
723 useful applications can be written.
727 wxPython is close enough to the C++ version that the majority of
728 the wxPython documentation is actually just notes attached to the C++
729 documents that describe the places where wxPython is different. There
730 is also a series of sample programs included, and a series of
731 documentation pages that assist the programmer in getting started
737 #----------------------------------------------------------------------------
738 #----------------------------------------------------------------------------
740 if __name__
== '__main__':
743 #----------------------------------------------------------------------------