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', [
35 # managed windows == things with a caption you can close
36 ('Base Frames and Dialogs', [
48 'wxFindReplaceDialog',
54 'wxSingleChoiceDialog',
58 # dialogs form libraries
62 'wxMultipleChoiceDialog',
63 'wxScrolledMessageDialog',
67 ('Core Windows/Controls', [
98 # controls coming from other librairies
99 ('More Windows/Controls', [
106 'PyCrustWithFilling',
111 'wxDynamicSashWindow',
117 'wxMimeTypesManager',
119 'wxStyledTextCtrl_1',
120 'wxStyledTextCtrl_2',
124 # How to lay out the controls in a frame/dialog
130 'wxLayoutConstraints',
135 ('Process and Events', [
145 ('Clipboard and DnD', [
173 # need libs not coming with the demo
174 ('Objects using an external library', [
175 'ActiveXWrapper_Acrobat',
181 # pyTree, hangman, ... in the samples dir
182 ('Check out the samples dir too', [
189 #---------------------------------------------------------------------------
191 class MyLog(wxPyLog
):
192 def __init__(self
, textCtrl
, logTime
=0):
193 wxPyLog
.__init
__(self
)
195 self
.logTime
= logTime
197 def DoLogString(self
, message
, timeStamp
):
199 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
201 self
.tc
.AppendText(message
+ '\n')
204 #---------------------------------------------------------------------------
207 """Convert paths to the platform-specific separator"""
208 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
211 #---------------------------------------------------------------------------
213 class wxPythonDemo(wxFrame
):
214 overviewText
= "wxPython Overview"
216 def __init__(self
, parent
, id, title
):
217 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
218 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
220 self
.cwd
= os
.getcwd()
221 self
.curOverview
= ""
223 icon
= images
.getMondrianIcon()
226 if wxPlatform
== '__WXMSW__':
227 # setup a taskbar icon, and catch some events from it
228 self
.tbicon
= wxTaskBarIcon()
229 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
230 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
231 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
232 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
233 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
238 EVT_IDLE(self
, self
.OnIdle
)
239 EVT_CLOSE(self
, self
.OnCloseWindow
)
240 EVT_ICONIZE(self
, self
.OnIconfiy
)
241 EVT_MAXIMIZE(self
, self
.OnMaximize
)
244 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
246 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
247 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
249 def EmptyHandler(evt
): pass
250 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
251 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
253 # Prevent TreeCtrl from displaying all items after destruction when true
257 self
.mainmenu
= wxMenuBar()
260 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
261 EVT_MENU(self
, exitID
, self
.OnFileExit
)
262 self
.mainmenu
.Append(menu
, '&File')
266 for item
in _treeList
:
268 for childItem
in item
[1]:
270 submenu
.Append(mID
, childItem
)
271 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
272 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
273 self
.mainmenu
.Append(menu
, '&Demo')
279 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
280 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
281 self
.mainmenu
.Append(menu
, '&Help')
282 self
.SetMenuBar(self
.mainmenu
)
284 # set the menu accellerator table...
285 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
286 (wxACCEL_CTRL
, ord('H'), helpID
)])
287 self
.SetAcceleratorTable(aTable
)
293 self
.tree
= wxTreeCtrl(splitter
, tID
,
294 style
=wxTR_HAS_BUTTONS |
296 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
298 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
299 root
= self
.tree
.AddRoot("wxPython Overview")
301 for item
in _treeList
:
302 child
= self
.tree
.AppendItem(root
, item
[0])
303 if not firstChild
: firstChild
= child
304 for childItem
in item
[1]:
305 theDemo
= self
.tree
.AppendItem(child
, childItem
)
306 self
.treeMap
[childItem
] = theDemo
308 self
.tree
.Expand(root
)
309 self
.tree
.Expand(firstChild
)
310 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
311 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
312 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
313 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
316 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
318 # Set up a wxHtmlWindow on the Overview Notebook page
319 # we put it in a panel first because there seems to be a
320 # refresh bug of some sort (wxGTK) when it is directly in
323 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
324 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
326 else: # hopefully I can remove this hacky code soon, see bug #216861
327 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
328 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
329 self
.nb
.AddPage(panel
, self
.overviewText
)
331 def OnOvrSize(evt
, ovr
=self
.ovr
):
332 ovr
.SetSize(evt
.GetSize())
334 EVT_SIZE(panel
, OnOvrSize
)
335 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
338 self
.SetOverview(self
.overviewText
, overview
)
341 # Set up a TextCtrl on the Demo Code Notebook page
342 self
.txt
= wxTextCtrl(self
.nb
, -1,
343 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
344 self
.nb
.AddPage(self
.txt
, "Demo Code")
347 # Set up a log on the View Log Notebook page
348 self
.log
= wxTextCtrl(splitter2
, -1,
349 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
351 # Set the wxWindows log target to be this textctrl
352 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
354 # But instead of the above we want to show how to use our own wxLog class
355 wxLog_SetActiveTarget(MyLog(self
.log
))
361 # add the windows to the splitter and split it.
362 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
363 splitter
.SplitVertically(self
.tree
, splitter2
)
365 splitter
.SetSashPosition(180, true
)
366 splitter
.SetMinimumPaneSize(20)
367 splitter2
.SetSashPosition(450, true
)
368 splitter2
.SetMinimumPaneSize(20)
372 # select initial items
373 self
.nb
.SetSelection(0)
374 self
.tree
.SelectItem(root
)
376 if len(sys
.argv
) == 2:
378 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
382 self
.tree
.SelectItem(selectedDemo
)
383 self
.tree
.EnsureVisible(selectedDemo
)
386 wxLogMessage('window handle: %s' % self
.GetHandle())
389 #---------------------------------------------
390 def WriteText(self
, text
):
391 if text
[-1:] == '\n':
396 def write(self
, txt
):
399 #---------------------------------------------
400 def OnItemExpanded(self
, event
):
401 item
= event
.GetItem()
402 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
405 #---------------------------------------------
406 def OnItemCollapsed(self
, event
):
407 item
= event
.GetItem()
408 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
411 #---------------------------------------------
412 def OnTreeLeftDown(self
, event
):
413 pt
= event
.GetPosition();
414 item
, flags
= self
.tree
.HitTest(pt
)
415 if item
== self
.tree
.GetSelection():
416 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
419 #---------------------------------------------
420 def OnSelChanged(self
, event
):
424 item
= event
.GetItem()
425 itemText
= self
.tree
.GetItemText(item
)
426 self
.RunDemo(itemText
)
429 #---------------------------------------------
430 def RunDemo(self
, itemText
):
432 if self
.nb
.GetPageCount() == 3:
433 if self
.nb
.GetSelection() == 2:
434 self
.nb
.SetSelection(0)
435 self
.nb
.DeletePage(2)
437 if itemText
== self
.overviewText
:
438 self
.GetDemoFile('Main.py')
439 self
.SetOverview(self
.overviewText
, overview
)
444 if os
.path
.exists(itemText
+ '.py'):
446 wxLogMessage("Running demo %s.py..." % itemText
)
448 self
.GetDemoFile(itemText
+ '.py')
449 module
= __import__(itemText
, globals())
450 self
.SetOverview(itemText
+ " Overview", module
.overview
)
455 # in case runTest is modal, make sure things look right...
459 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
461 self
.nb
.AddPage(self
.window
, 'Demo')
462 self
.nb
.SetSelection(2)
463 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
472 #---------------------------------------------
474 def GetDemoFile(self
, filename
):
477 self
.txt
.SetValue(open(filename
).read())
479 self
.txt
.WriteText("Cannot open %s file." % filename
)
481 self
.txt
.SetInsertionPoint(0)
482 self
.txt
.ShowPosition(0)
484 #---------------------------------------------
485 def SetOverview(self
, name
, text
):
486 self
.curOverview
= text
488 if lead
!= '<html>' and lead
!= '<HTML>':
489 text
= string
.join(string
.split(text
, '\n'), '<br>')
490 self
.ovr
.SetPage(text
)
491 self
.nb
.SetPageText(0, name
)
493 #---------------------------------------------
495 def OnFileExit(self
, *event
):
499 def OnHelpAbout(self
, event
):
500 from About
import MyAboutBox
501 about
= MyAboutBox(self
)
506 #---------------------------------------------
507 def OnCloseWindow(self
, event
):
511 if hasattr(self
, "tbicon"):
516 #---------------------------------------------
517 def OnIdle(self
, event
):
519 self
.otherWin
.Raise()
520 self
.window
= self
.otherWin
528 #---------------------------------------------
531 showTipText
= open(opj("data/showTips")).read()
532 showTip
, index
= eval(showTipText
)
534 showTip
, index
= (1, 0)
536 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
537 showTip
= wxShowTip(self
, tp
)
538 index
= tp
.GetCurrentTip()
539 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
542 #---------------------------------------------
543 def OnDemoMenu(self
, event
):
545 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
549 self
.tree
.SelectItem(selectedDemo
)
550 self
.tree
.EnsureVisible(selectedDemo
)
553 #---------------------------------------------
554 def OnTaskBarActivate(self
, evt
):
555 if self
.IsIconized():
557 if not self
.IsShown():
561 #---------------------------------------------
563 TBMENU_RESTORE
= 1000
566 def OnTaskBarMenu(self
, evt
):
568 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
569 menu
.Append(self
.TBMENU_CLOSE
, "Close")
570 self
.tbicon
.PopupMenu(menu
)
573 #---------------------------------------------
574 def OnTaskBarClose(self
, evt
):
577 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
578 # prod the main idle handler a bit to get the window to actually close
579 wxGetApp().ProcessIdle()
582 #---------------------------------------------
583 def OnIconfiy(self
, evt
):
584 wxLogMessage("OnIconfiy")
587 #---------------------------------------------
588 def OnMaximize(self
, evt
):
589 wxLogMessage("OnMaximize")
595 #---------------------------------------------------------------------------
596 #---------------------------------------------------------------------------
598 class MySplashScreen(wxSplashScreen
):
600 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
601 wxSplashScreen
.__init
__(self
, bmp
,
602 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
604 style
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
)
605 EVT_CLOSE(self
, self
.OnClose
)
607 def OnClose(self
, evt
):
608 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
610 evt
.Skip() # Make sure the default handler runs too...
616 Create and show the splash screen. It will then create and show
617 the main frame when it is time to do so.
619 wxInitAllImageHandlers()
620 splash
= MySplashScreen()
626 #---------------------------------------------------------------------------
630 demoPath
= os
.path
.dirname(__file__
)
634 app
= MyApp(wxPlatform
== "__WXMAC__")
638 #---------------------------------------------------------------------------
642 overview
= """<html><body>
645 Python is an interpreted, interactive, object-oriented programming
646 language often compared to Tcl, Perl, Scheme, or Java.
648 <p> Python combines remarkable power with very clear syntax. It has
649 modules, classes, exceptions, very high level dynamic data types, and
650 dynamic typing. There are interfaces to many system calls and
651 libraries, and new built-in modules are easily written in C or
652 C++. Python is also usable as an extension language for applications
653 that need a programmable interface. <p>
657 wxWindows is a free C++ framework designed to make cross-platform
658 programming child's play. Well, almost. wxWindows 2 supports Windows
659 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
660 underway. Other ports are under consideration. <p>
662 wxWindows is a set of libraries that allows C++ applications to
663 compile and run on several different types of computers, with minimal
664 source code changes. There is one library per supported GUI (such as
665 Motif, or Windows). As well as providing a common API (Application
666 Programming Interface) for GUI functionality, it provides
667 functionality for accessing some commonly-used operating system
668 facilities, such as copying or deleting files. wxWindows is a
669 'framework' in the sense that it provides a lot of built-in
670 functionality, which the application can use or replace as required,
671 thus saving a great deal of coding effort. Basic data structures such
672 as strings, linked lists and hash tables are also supported.
677 wxPython is a Python extension module that encapsulates the wxWindows
678 GUI classes. Currently it is only available for the Win32 and GTK
679 ports of wxWindows, but as soon as the other ports are brought up to
680 the same level as Win32 and GTK, it should be fairly trivial to
681 enable wxPython to be used with the new GUI.
685 The wxPython extension module attempts to mirror the class heiarchy
686 of wxWindows as closely as possible. This means that there is a
687 wxFrame class in wxPython that looks, smells, tastes and acts almost
688 the same as the wxFrame class in the C++ version. Unfortunately,
689 because of differences in the languages, wxPython doesn't match
690 wxWindows exactly, but the differences should be easy to absorb
691 because they are natural to Python. For example, some methods that
692 return multiple values via argument pointers in C++ will return a
693 tuple of values in Python.
697 There is still much to be done for wxPython, many classes still need
698 to be mirrored. Also, wxWindows is still somewhat of a moving target
699 so it is a bit of an effort just keeping wxPython up to date. On the
700 other hand, there are enough of the core classes completed that
701 useful applications can be written.
705 wxPython is close enough to the C++ version that the majority of
706 the wxPython documentation is actually just notes attached to the C++
707 documents that describe the places where wxPython is different. There
708 is also a series of sample programs included, and a series of
709 documentation pages that assist the programmer in getting started
715 #----------------------------------------------------------------------------
716 #----------------------------------------------------------------------------
718 if __name__
== '__main__':
721 #----------------------------------------------------------------------------