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', [
38 # managed windows == things with a caption you can close
39 ('Base Frames and Dialogs', [
51 'wxFindReplaceDialog',
57 'wxSingleChoiceDialog',
61 # dialogs form libraries
65 'wxMultipleChoiceDialog',
66 'wxScrolledMessageDialog',
70 ('Core Windows/Controls', [
102 # controls coming from other librairies
103 ('More Windows/Controls', [
110 'PyCrustWithFilling',
115 'wxDynamicSashWindow',
121 'wxMimeTypesManager',
123 'wxStyledTextCtrl_1',
124 'wxStyledTextCtrl_2',
128 # How to lay out the controls in a frame/dialog
135 'wxLayoutConstraints',
140 ('Process and Events', [
150 ('Clipboard and DnD', [
179 # need libs not coming with the demo
180 ('Objects using an external library', [
181 'ActiveXWrapper_Acrobat',
187 # pyTree, hangman, ... in the samples dir
188 ('Check out the samples dir too', [
195 #---------------------------------------------------------------------------
197 class MyLog(wxPyLog
):
198 def __init__(self
, textCtrl
, logTime
=0):
199 wxPyLog
.__init
__(self
)
201 self
.logTime
= logTime
203 def DoLogString(self
, message
, timeStamp
):
205 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
207 self
.tc
.AppendText(message
+ '\n')
210 #---------------------------------------------------------------------------
213 """Convert paths to the platform-specific separator"""
214 return apply(os
.path
.join
, tuple(string
.split(path
, '/')))
217 #---------------------------------------------------------------------------
219 class wxPythonDemo(wxFrame
):
220 overviewText
= "wxPython Overview"
222 def __init__(self
, parent
, id, title
):
223 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
224 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
226 self
.cwd
= os
.getcwd()
227 self
.curOverview
= ""
229 icon
= images
.getMondrianIcon()
232 if wxPlatform
== '__WXMSW__':
233 # setup a taskbar icon, and catch some events from it
234 self
.tbicon
= wxTaskBarIcon()
235 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
236 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
237 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
238 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
239 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
244 EVT_IDLE(self
, self
.OnIdle
)
245 EVT_CLOSE(self
, self
.OnCloseWindow
)
246 EVT_ICONIZE(self
, self
.OnIconfiy
)
247 EVT_MAXIMIZE(self
, self
.OnMaximize
)
250 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
252 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
253 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
255 def EmptyHandler(evt
): pass
256 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
257 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
259 # Prevent TreeCtrl from displaying all items after destruction when true
263 self
.mainmenu
= wxMenuBar()
266 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
267 EVT_MENU(self
, exitID
, self
.OnFileExit
)
268 self
.mainmenu
.Append(menu
, '&File')
272 for item
in _treeList
:
274 for childItem
in item
[1]:
276 submenu
.Append(mID
, childItem
)
277 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
278 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
279 self
.mainmenu
.Append(menu
, '&Demo')
285 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
286 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
287 self
.mainmenu
.Append(menu
, '&Help')
288 self
.SetMenuBar(self
.mainmenu
)
290 # set the menu accellerator table...
291 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
292 (wxACCEL_CTRL
, ord('H'), helpID
)])
293 self
.SetAcceleratorTable(aTable
)
299 self
.tree
= wxTreeCtrl(splitter
, tID
,
300 style
=wxTR_HAS_BUTTONS |
302 wxTR_HAS_VARIABLE_ROW_HEIGHT
)
304 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
305 root
= self
.tree
.AddRoot("wxPython Overview")
307 for item
in _treeList
:
308 child
= self
.tree
.AppendItem(root
, item
[0])
309 if not firstChild
: firstChild
= child
310 for childItem
in item
[1]:
311 theDemo
= self
.tree
.AppendItem(child
, childItem
)
312 self
.treeMap
[childItem
] = theDemo
314 self
.tree
.Expand(root
)
315 self
.tree
.Expand(firstChild
)
316 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
317 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
318 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
319 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
322 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
324 # Set up a wxHtmlWindow on the Overview Notebook page
325 # we put it in a panel first because there seems to be a
326 # refresh bug of some sort (wxGTK) when it is directly in
329 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
330 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
332 else: # hopefully I can remove this hacky code soon, see bug #216861
333 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
334 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
335 self
.nb
.AddPage(panel
, self
.overviewText
)
337 def OnOvrSize(evt
, ovr
=self
.ovr
):
338 ovr
.SetSize(evt
.GetSize())
340 EVT_SIZE(panel
, OnOvrSize
)
341 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
344 self
.SetOverview(self
.overviewText
, overview
)
347 # Set up a TextCtrl on the Demo Code Notebook page
348 self
.txt
= wxTextCtrl(self
.nb
, -1,
349 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
350 self
.nb
.AddPage(self
.txt
, "Demo Code")
353 # Set up a log on the View Log Notebook page
354 self
.log
= wxTextCtrl(splitter2
, -1,
355 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
357 # Set the wxWindows log target to be this textctrl
358 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
360 # But instead of the above we want to show how to use our own wxLog class
361 wxLog_SetActiveTarget(MyLog(self
.log
))
363 # for serious debugging
364 #wxLog_SetActiveTarget(wxLogStderr())
365 #wxLog_SetTraceMask(wxTraceMessages)
370 # add the windows to the splitter and split it.
371 splitter2
.SplitHorizontally(self
.nb
, self
.log
)
372 splitter
.SplitVertically(self
.tree
, splitter2
)
374 splitter
.SetSashPosition(180, true
)
375 splitter
.SetMinimumPaneSize(20)
376 splitter2
.SetSashPosition(450, true
)
377 splitter2
.SetMinimumPaneSize(20)
381 # select initial items
382 self
.nb
.SetSelection(0)
383 self
.tree
.SelectItem(root
)
385 if len(sys
.argv
) == 2:
387 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
391 self
.tree
.SelectItem(selectedDemo
)
392 self
.tree
.EnsureVisible(selectedDemo
)
395 wxLogMessage('window handle: %s' % self
.GetHandle())
398 #---------------------------------------------
399 def WriteText(self
, text
):
400 if text
[-1:] == '\n':
405 def write(self
, txt
):
408 #---------------------------------------------
409 def OnItemExpanded(self
, event
):
410 item
= event
.GetItem()
411 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
414 #---------------------------------------------
415 def OnItemCollapsed(self
, event
):
416 item
= event
.GetItem()
417 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
420 #---------------------------------------------
421 def OnTreeLeftDown(self
, event
):
422 pt
= event
.GetPosition();
423 item
, flags
= self
.tree
.HitTest(pt
)
424 if item
== self
.tree
.GetSelection():
425 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
428 #---------------------------------------------
429 def OnSelChanged(self
, event
):
433 item
= event
.GetItem()
434 itemText
= self
.tree
.GetItemText(item
)
435 self
.RunDemo(itemText
)
438 #---------------------------------------------
439 def RunDemo(self
, itemText
):
441 if self
.nb
.GetPageCount() == 3:
442 if self
.nb
.GetSelection() == 2:
443 self
.nb
.SetSelection(0)
444 self
.nb
.DeletePage(2)
446 if itemText
== self
.overviewText
:
447 self
.GetDemoFile('Main.py')
448 self
.SetOverview(self
.overviewText
, overview
)
453 if os
.path
.exists(itemText
+ '.py'):
455 wxLogMessage("Running demo %s.py..." % itemText
)
457 self
.GetDemoFile(itemText
+ '.py')
458 module
= __import__(itemText
, globals())
459 self
.SetOverview(itemText
+ " Overview", module
.overview
)
464 # in case runTest is modal, make sure things look right...
468 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
470 self
.nb
.AddPage(self
.window
, 'Demo')
471 self
.nb
.SetSelection(2)
472 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
481 #---------------------------------------------
483 def GetDemoFile(self
, filename
):
486 self
.txt
.SetValue(open(filename
).read())
488 self
.txt
.WriteText("Cannot open %s file." % filename
)
490 self
.txt
.SetInsertionPoint(0)
491 self
.txt
.ShowPosition(0)
493 #---------------------------------------------
494 def SetOverview(self
, name
, text
):
495 self
.curOverview
= text
497 if lead
!= '<html>' and lead
!= '<HTML>':
498 text
= string
.join(string
.split(text
, '\n'), '<br>')
499 self
.ovr
.SetPage(text
)
500 self
.nb
.SetPageText(0, name
)
502 #---------------------------------------------
504 def OnFileExit(self
, *event
):
508 def OnHelpAbout(self
, event
):
509 from About
import MyAboutBox
510 about
= MyAboutBox(self
)
515 #---------------------------------------------
516 def OnCloseWindow(self
, event
):
520 if hasattr(self
, "tbicon"):
525 #---------------------------------------------
526 def OnIdle(self
, event
):
528 self
.otherWin
.Raise()
529 self
.window
= self
.otherWin
537 #---------------------------------------------
540 showTipText
= open(opj("data/showTips")).read()
541 showTip
, index
= eval(showTipText
)
543 showTip
, index
= (1, 0)
545 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
546 showTip
= wxShowTip(self
, tp
)
547 index
= tp
.GetCurrentTip()
548 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
551 #---------------------------------------------
552 def OnDemoMenu(self
, event
):
554 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
558 self
.tree
.SelectItem(selectedDemo
)
559 self
.tree
.EnsureVisible(selectedDemo
)
562 #---------------------------------------------
563 def OnTaskBarActivate(self
, evt
):
564 if self
.IsIconized():
566 if not self
.IsShown():
570 #---------------------------------------------
572 TBMENU_RESTORE
= 1000
575 def OnTaskBarMenu(self
, evt
):
577 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
578 menu
.Append(self
.TBMENU_CLOSE
, "Close")
579 self
.tbicon
.PopupMenu(menu
)
582 #---------------------------------------------
583 def OnTaskBarClose(self
, evt
):
586 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
587 # prod the main idle handler a bit to get the window to actually close
588 wxGetApp().ProcessIdle()
591 #---------------------------------------------
592 def OnIconfiy(self
, evt
):
593 wxLogMessage("OnIconfiy")
596 #---------------------------------------------
597 def OnMaximize(self
, evt
):
598 wxLogMessage("OnMaximize")
604 #---------------------------------------------------------------------------
605 #---------------------------------------------------------------------------
607 class MySplashScreen(wxSplashScreen
):
609 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
610 wxSplashScreen
.__init
__(self
, bmp
,
611 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
613 style
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
)
614 EVT_CLOSE(self
, self
.OnClose
)
616 def OnClose(self
, evt
):
617 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
619 evt
.Skip() # Make sure the default handler runs too...
625 Create and show the splash screen. It will then create and show
626 the main frame when it is time to do so.
628 wxInitAllImageHandlers()
629 splash
= MySplashScreen()
635 #---------------------------------------------------------------------------
639 demoPath
= os
.path
.dirname(__file__
)
643 app
= MyApp(wxPlatform
== "__WXMAC__")
647 #---------------------------------------------------------------------------
651 overview
= """<html><body>
654 Python is an interpreted, interactive, object-oriented programming
655 language often compared to Tcl, Perl, Scheme, or Java.
657 <p> Python combines remarkable power with very clear syntax. It has
658 modules, classes, exceptions, very high level dynamic data types, and
659 dynamic typing. There are interfaces to many system calls and
660 libraries, and new built-in modules are easily written in C or
661 C++. Python is also usable as an extension language for applications
662 that need a programmable interface. <p>
666 wxWindows is a free C++ framework designed to make cross-platform
667 programming child's play. Well, almost. wxWindows 2 supports Windows
668 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
669 underway. Other ports are under consideration. <p>
671 wxWindows is a set of libraries that allows C++ applications to
672 compile and run on several different types of computers, with minimal
673 source code changes. There is one library per supported GUI (such as
674 Motif, or Windows). As well as providing a common API (Application
675 Programming Interface) for GUI functionality, it provides
676 functionality for accessing some commonly-used operating system
677 facilities, such as copying or deleting files. wxWindows is a
678 'framework' in the sense that it provides a lot of built-in
679 functionality, which the application can use or replace as required,
680 thus saving a great deal of coding effort. Basic data structures such
681 as strings, linked lists and hash tables are also supported.
686 wxPython is a Python extension module that encapsulates the wxWindows
687 GUI classes. Currently it is only available for the Win32 and GTK
688 ports of wxWindows, but as soon as the other ports are brought up to
689 the same level as Win32 and GTK, it should be fairly trivial to
690 enable wxPython to be used with the new GUI.
694 The wxPython extension module attempts to mirror the class heiarchy
695 of wxWindows as closely as possible. This means that there is a
696 wxFrame class in wxPython that looks, smells, tastes and acts almost
697 the same as the wxFrame class in the C++ version. Unfortunately,
698 because of differences in the languages, wxPython doesn't match
699 wxWindows exactly, but the differences should be easy to absorb
700 because they are natural to Python. For example, some methods that
701 return multiple values via argument pointers in C++ will return a
702 tuple of values in Python.
706 There is still much to be done for wxPython, many classes still need
707 to be mirrored. Also, wxWindows is still somewhat of a moving target
708 so it is a bit of an effort just keeping wxPython up to date. On the
709 other hand, there are enough of the core classes completed that
710 useful applications can be written.
714 wxPython is close enough to the C++ version that the majority of
715 the wxPython documentation is actually just notes attached to the C++
716 documents that describe the places where wxPython is different. There
717 is also a series of sample programs included, and a series of
718 documentation pages that assist the programmer in getting started
724 #----------------------------------------------------------------------------
725 #----------------------------------------------------------------------------
727 if __name__
== '__main__':
730 #----------------------------------------------------------------------------