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
)
454 # in case runTest is modal, make sure things look right...
458 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
460 self
.nb
.AddPage(self
.window
, 'Demo')
461 #wxYield() TODO: Is this still needed?
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 EVT_CLOSE(self
, self
.OnClose
)
606 def OnClose(self
, evt
):
607 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
609 evt
.Skip() # Make sure the default handler runs too...
615 Create and show the splash screen. It will then create and show
616 the main frame when it is time to do so.
618 wxInitAllImageHandlers()
619 splash
= MySplashScreen()
625 #---------------------------------------------------------------------------
629 demoPath
= os
.path
.dirname(__file__
)
633 app
= MyApp(wxPlatform
== "__WXMAC__")
637 #---------------------------------------------------------------------------
641 overview
= """<html><body>
644 Python is an interpreted, interactive, object-oriented programming
645 language often compared to Tcl, Perl, Scheme, or Java.
647 <p> Python combines remarkable power with very clear syntax. It has
648 modules, classes, exceptions, very high level dynamic data types, and
649 dynamic typing. There are interfaces to many system calls and
650 libraries, and new built-in modules are easily written in C or
651 C++. Python is also usable as an extension language for applications
652 that need a programmable interface. <p>
656 wxWindows is a free C++ framework designed to make cross-platform
657 programming child's play. Well, almost. wxWindows 2 supports Windows
658 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
659 underway. Other ports are under consideration. <p>
661 wxWindows is a set of libraries that allows C++ applications to
662 compile and run on several different types of computers, with minimal
663 source code changes. There is one library per supported GUI (such as
664 Motif, or Windows). As well as providing a common API (Application
665 Programming Interface) for GUI functionality, it provides
666 functionality for accessing some commonly-used operating system
667 facilities, such as copying or deleting files. wxWindows is a
668 'framework' in the sense that it provides a lot of built-in
669 functionality, which the application can use or replace as required,
670 thus saving a great deal of coding effort. Basic data structures such
671 as strings, linked lists and hash tables are also supported.
676 wxPython is a Python extension module that encapsulates the wxWindows
677 GUI classes. Currently it is only available for the Win32 and GTK
678 ports of wxWindows, but as soon as the other ports are brought up to
679 the same level as Win32 and GTK, it should be fairly trivial to
680 enable wxPython to be used with the new GUI.
684 The wxPython extension module attempts to mirror the class heiarchy
685 of wxWindows as closely as possible. This means that there is a
686 wxFrame class in wxPython that looks, smells, tastes and acts almost
687 the same as the wxFrame class in the C++ version. Unfortunately,
688 because of differences in the languages, wxPython doesn't match
689 wxWindows exactly, but the differences should be easy to absorb
690 because they are natural to Python. For example, some methods that
691 return multiple values via argument pointers in C++ will return a
692 tuple of values in Python.
696 There is still much to be done for wxPython, many classes still need
697 to be mirrored. Also, wxWindows is still somewhat of a moving target
698 so it is a bit of an effort just keeping wxPython up to date. On the
699 other hand, there are enough of the core classes completed that
700 useful applications can be written.
704 wxPython is close enough to the C++ version that the majority of
705 the wxPython documentation is actually just notes attached to the C++
706 documents that describe the places where wxPython is different. There
707 is also a series of sample programs included, and a series of
708 documentation pages that assist the programmer in getting started
714 #----------------------------------------------------------------------------
715 #----------------------------------------------------------------------------
717 if __name__
== '__main__':
720 #----------------------------------------------------------------------------