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 #----------------------------------------------------------------------------
15 from wxPython
.wx
import *
16 from wxPython
.html
import wxHtmlWindow
18 ##from wxPython.stc import *
23 #---------------------------------------------------------------------------
28 ('Recent Additions', [
34 # managed windows == things with a (optional) caption you can close
35 ('Base Frames and Dialogs', [
48 'wxFindReplaceDialog',
54 'wxSingleChoiceDialog',
58 # dialogs from libraries
62 'wxMultipleChoiceDialog',
63 'wxScrolledMessageDialog',
67 ('Core Windows/Controls', [
100 # controls coming from other librairies
101 ('More Windows/Controls', [
102 #'wxFloatBar', deprecated
103 #'wxMVCTree', deprecated
104 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
111 'PyCrustWithFilling',
118 'wxDynamicSashWindow',
125 'wxMimeTypesManager',
128 'wxStyledTextCtrl_1',
129 'wxStyledTextCtrl_2',
133 # How to lay out the controls in a frame/dialog
139 'wxLayoutConstraints',
142 'wxXmlResourceHandler',
146 ('Process and Events', [
158 ('Clipboard and DnD', [
189 # need libs not coming with the demo
190 ('Objects using an external library', [
191 'ActiveXWrapper_Acrobat',
198 ('Check out the samples dir too', [
205 #---------------------------------------------------------------------------
207 class MyLog(wxPyLog
):
208 def __init__(self
, textCtrl
, logTime
=0):
209 wxPyLog
.__init
__(self
)
211 self
.logTime
= logTime
213 def DoLogString(self
, message
, timeStamp
):
215 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
218 self
.tc
.AppendText(message
+ '\n')
221 class MyTP(wxPyTipProvider
):
223 return "This is my tip"
225 #---------------------------------------------------------------------------
228 """Convert paths to the platform-specific separator"""
229 return apply(os
.path
.join
, tuple(path
.split('/')))
232 #---------------------------------------------------------------------------
234 class wxPythonDemo(wxFrame
):
235 overviewText
= "wxPython Overview"
237 def __init__(self
, parent
, id, title
):
238 wxFrame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
239 style
=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE
)
241 self
.cwd
= os
.getcwd()
242 self
.curOverview
= ""
245 icon
= images
.getMondrianIcon()
248 if wxPlatform
== '__WXMSW__':
249 # setup a taskbar icon, and catch some events from it
250 self
.tbicon
= wxTaskBarIcon()
251 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
252 EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
253 EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
254 EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
255 EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
257 wxCallAfter(self
.ShowTip
)
260 EVT_IDLE(self
, self
.OnIdle
)
261 EVT_CLOSE(self
, self
.OnCloseWindow
)
262 EVT_ICONIZE(self
, self
.OnIconfiy
)
263 EVT_MAXIMIZE(self
, self
.OnMaximize
)
266 self
.CreateStatusBar(1, wxST_SIZEGRIP
)
268 splitter
= wxSplitterWindow(self
, -1, style
=wxNO_3D|wxSP_3D
)
269 splitter2
= wxSplitterWindow(splitter
, -1, style
=wxNO_3D|wxSP_3D
)
271 def EmptyHandler(evt
): pass
272 EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
273 EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
275 # Prevent TreeCtrl from displaying all items after destruction when True
279 self
.mainmenu
= wxMenuBar()
282 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
283 EVT_MENU(self
, exitID
, self
.OnFileExit
)
284 wxApp_SetMacExitMenuItemId(exitID
)
285 self
.mainmenu
.Append(menu
, '&File')
289 for item
in _treeList
:
291 for childItem
in item
[1]:
293 submenu
.Append(mID
, childItem
)
294 EVT_MENU(self
, mID
, self
.OnDemoMenu
)
295 menu
.AppendMenu(wxNewId(), item
[0], submenu
)
296 self
.mainmenu
.Append(menu
, '&Demo')
302 findnextID
= wxNewId()
304 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
305 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
306 menu
.AppendSeparator()
307 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
308 wxApp_SetMacAboutMenuItemId(helpID
)
309 EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
310 EVT_MENU(self
, findID
, self
.OnHelpFind
)
311 EVT_MENU(self
, findnextID
, self
.OnFindNext
)
312 EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
313 EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
314 EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
315 self
.mainmenu
.Append(menu
, '&Help')
316 self
.SetMenuBar(self
.mainmenu
)
318 self
.finddata
= wxFindReplaceData()
321 # This is another way to set Accelerators, in addition to
322 # using the '\t<key>' syntax in the menu items.
323 aTable
= wxAcceleratorTable([(wxACCEL_ALT
, ord('X'), exitID
),
324 (wxACCEL_CTRL
, ord('H'), helpID
),
325 (wxACCEL_CTRL
, ord('F'), findID
),
326 (wxACCEL_NORMAL
, WXK_F3
, findnextID
)])
327 self
.SetAcceleratorTable(aTable
)
333 self
.tree
= wxTreeCtrl(splitter
, tID
,
334 style
=wxTR_HAS_BUTTONS |
335 wxTR_HAS_VARIABLE_ROW_HEIGHT
338 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
339 root
= self
.tree
.AddRoot("wxPython Overview")
341 for item
in _treeList
:
342 child
= self
.tree
.AppendItem(root
, item
[0])
343 if not firstChild
: firstChild
= child
344 for childItem
in item
[1]:
345 theDemo
= self
.tree
.AppendItem(child
, childItem
)
346 self
.treeMap
[childItem
] = theDemo
348 self
.tree
.Expand(root
)
349 self
.tree
.Expand(firstChild
)
350 EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
351 EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
352 EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
353 EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
356 self
.nb
= wxNotebook(splitter2
, -1, style
=wxCLIP_CHILDREN
)
358 # Set up a wxHtmlWindow on the Overview Notebook page
359 # we put it in a panel first because there seems to be a
360 # refresh bug of some sort (wxGTK) when it is directly in
363 self
.ovr
= wxHtmlWindow(self
.nb
, -1, size
=(400, 400))
364 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
366 else: # hopefully I can remove this hacky code soon, see bug #216861
367 panel
= wxPanel(self
.nb
, -1, style
=wxCLIP_CHILDREN
)
368 self
.ovr
= wxHtmlWindow(panel
, -1, size
=(400, 400))
369 self
.nb
.AddPage(panel
, self
.overviewText
)
371 def OnOvrSize(evt
, ovr
=self
.ovr
):
372 ovr
.SetSize(evt
.GetSize())
374 EVT_SIZE(panel
, OnOvrSize
)
375 EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
378 self
.SetOverview(self
.overviewText
, overview
)
381 # Set up a TextCtrl on the Demo Code Notebook page
382 self
.txt
= wxTextCtrl(self
.nb
, -1,
383 style
= wxTE_MULTILINE|wxTE_READONLY|
384 wxHSCROLL|wxTE_RICH2|wxTE_NOHIDESEL
)
385 self
.nb
.AddPage(self
.txt
, "Demo Code")
388 # Set up a log on the View Log Notebook page
389 self
.log
= wxTextCtrl(splitter2
, -1,
390 style
= wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL
)
392 # Set the wxWindows log target to be this textctrl
393 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
395 # But instead of the above we want to show how to use our own wxLog class
396 wxLog_SetActiveTarget(MyLog(self
.log
))
398 # for serious debugging
399 #wxLog_SetActiveTarget(wxLogStderr())
400 #wxLog_SetTraceMask(wxTraceMessages)
405 # add the windows to the splitter and split it.
406 splitter2
.SplitHorizontally(self
.nb
, self
.log
, 450)
407 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
409 splitter
.SetMinimumPaneSize(20)
410 splitter2
.SetMinimumPaneSize(20)
414 # select initial items
415 self
.nb
.SetSelection(0)
416 self
.tree
.SelectItem(root
)
418 if len(sys
.argv
) == 2:
420 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
424 self
.tree
.SelectItem(selectedDemo
)
425 self
.tree
.EnsureVisible(selectedDemo
)
428 wxLogMessage('window handle: %s' % self
.GetHandle())
431 #---------------------------------------------
432 def WriteText(self
, text
):
433 if text
[-1:] == '\n':
438 def write(self
, txt
):
441 #---------------------------------------------
442 def OnItemExpanded(self
, event
):
443 item
= event
.GetItem()
444 wxLogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
447 #---------------------------------------------
448 def OnItemCollapsed(self
, event
):
449 item
= event
.GetItem()
450 wxLogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
453 #---------------------------------------------
454 def OnTreeLeftDown(self
, event
):
455 pt
= event
.GetPosition();
456 item
, flags
= self
.tree
.HitTest(pt
)
457 if item
== self
.tree
.GetSelection():
458 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
461 #---------------------------------------------
462 def OnSelChanged(self
, event
):
466 item
= event
.GetItem()
467 itemText
= self
.tree
.GetItemText(item
)
468 self
.RunDemo(itemText
)
471 #---------------------------------------------
472 def RunDemo(self
, itemText
):
474 if self
.nb
.GetPageCount() == 3:
475 if self
.nb
.GetSelection() == 2:
476 self
.nb
.SetSelection(0)
477 # inform the window that it's time to quit if it cares
478 if self
.window
is not None:
479 if hasattr(self
.window
, "ShutdownDemo"):
480 self
.window
.ShutdownDemo()
481 wxSafeYield() # in case the page has pending events
482 self
.nb
.DeletePage(2)
484 if itemText
== self
.overviewText
:
485 self
.GetDemoFile('Main.py')
486 self
.SetOverview(self
.overviewText
, overview
)
491 if os
.path
.exists(itemText
+ '.py'):
493 wxLogMessage("Running demo %s.py..." % itemText
)
495 self
.GetDemoFile(itemText
+ '.py')
496 module
= __import__(itemText
, globals())
497 self
.SetOverview(itemText
+ " Overview", module
.overview
)
502 # in case runTest is modal, make sure things look right...
506 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
507 if self
.window
is not None:
508 self
.nb
.AddPage(self
.window
, 'Demo')
509 self
.nb
.SetSelection(2)
510 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
519 #---------------------------------------------
521 def GetDemoFile(self
, filename
):
524 self
.txt
.SetValue(open(filename
).read())
526 self
.txt
.WriteText("Cannot open %s file." % filename
)
528 self
.txt
.SetInsertionPoint(0)
529 self
.txt
.ShowPosition(0)
531 #---------------------------------------------
532 def SetOverview(self
, name
, text
):
533 self
.curOverview
= text
535 if lead
!= '<html>' and lead
!= '<HTML>':
536 text
= '<br>'.join(text
.split('\n'))
537 self
.ovr
.SetPage(text
)
538 self
.nb
.SetPageText(0, name
)
540 #---------------------------------------------
542 def OnFileExit(self
, *event
):
545 def OnHelpAbout(self
, event
):
546 from About
import MyAboutBox
547 about
= MyAboutBox(self
)
551 def OnHelpFind(self
, event
):
552 self
.nb
.SetSelection(1)
553 self
.finddlg
= wxFindReplaceDialog(self
, self
.finddata
, "Find",
557 self
.finddlg
.Show(True)
559 def OnFind(self
, event
):
560 self
.nb
.SetSelection(1)
561 end
= self
.txt
.GetLastPosition()
562 textstring
= self
.txt
.GetRange(0, end
).lower()
563 start
= self
.txt
.GetSelection()[1]
564 findstring
= self
.finddata
.GetFindString().lower()
565 loc
= textstring
.find(findstring
, start
)
566 if loc
== -1 and start
!= 0:
567 # string not found, start at beginning
569 loc
= textstring
.find(findstring
, start
)
571 dlg
= wxMessageDialog(self
, 'Find String Not Found',
572 'Find String Not Found in Demo File',
573 wxOK | wxICON_INFORMATION
)
578 self
.finddlg
.SetFocus()
581 self
.finddlg
.Destroy()
582 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
583 self
.txt
.ShowPosition(loc
)
587 def OnFindNext(self
, event
):
588 if self
.finddata
.GetFindString():
591 self
.OnHelpFind(event
)
593 def OnFindClose(self
, event
):
594 event
.GetDialog().Destroy()
597 #---------------------------------------------
598 def OnCloseWindow(self
, event
):
602 if hasattr(self
, "tbicon"):
607 #---------------------------------------------
608 def OnIdle(self
, event
):
610 self
.otherWin
.Raise()
611 self
.window
= self
.otherWin
615 #---------------------------------------------
618 showTipText
= open(opj("data/showTips")).read()
619 showTip
, index
= eval(showTipText
)
621 showTip
, index
= (1, 0)
623 tp
= wxCreateFileTipProvider(opj("data/tips.txt"), index
)
625 showTip
= wxShowTip(self
, tp
)
626 index
= tp
.GetCurrentTip()
627 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
630 #---------------------------------------------
631 def OnDemoMenu(self
, event
):
633 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
637 self
.tree
.SelectItem(selectedDemo
)
638 self
.tree
.EnsureVisible(selectedDemo
)
641 #---------------------------------------------
642 def OnTaskBarActivate(self
, evt
):
643 if self
.IsIconized():
645 if not self
.IsShown():
649 #---------------------------------------------
651 TBMENU_RESTORE
= 1000
654 def OnTaskBarMenu(self
, evt
):
656 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
657 menu
.Append(self
.TBMENU_CLOSE
, "Close")
658 self
.tbicon
.PopupMenu(menu
)
661 #---------------------------------------------
662 def OnTaskBarClose(self
, evt
):
665 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
666 # prod the main idle handler a bit to get the window to actually close
667 wxGetApp().ProcessIdle()
670 #---------------------------------------------
671 def OnIconfiy(self
, evt
):
672 wxLogMessage("OnIconfiy")
675 #---------------------------------------------
676 def OnMaximize(self
, evt
):
677 wxLogMessage("OnMaximize")
683 #---------------------------------------------------------------------------
684 #---------------------------------------------------------------------------
686 class MySplashScreen(wxSplashScreen
):
688 bmp
= wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
689 wxSplashScreen
.__init
__(self
, bmp
,
690 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT
,
692 style
= wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP
)
693 EVT_CLOSE(self
, self
.OnClose
)
695 def OnClose(self
, evt
):
696 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
698 evt
.Skip() # Make sure the default handler runs too...
704 Create and show the splash screen. It will then create and show
705 the main frame when it is time to do so.
709 #self.locale = wxLocale(wxLANGUAGE_FRENCH)
710 #locale.setlocale(locale.LC_ALL, 'fr')
712 wxInitAllImageHandlers()
713 splash
= MySplashScreen()
719 #---------------------------------------------------------------------------
723 demoPath
= os
.path
.dirname(__file__
)
727 app
= MyApp(wxPlatform
== "__WXMAC__")
731 #---------------------------------------------------------------------------
735 overview
= """<html><body>
738 Python is an interpreted, interactive, object-oriented programming
739 language often compared to Tcl, Perl, Scheme, or Java.
741 <p> Python combines remarkable power with very clear syntax. It has
742 modules, classes, exceptions, very high level dynamic data types, and
743 dynamic typing. There are interfaces to many system calls and
744 libraries, and new built-in modules are easily written in C or
745 C++. Python is also usable as an extension language for applications
746 that need a programmable interface. <p>
750 wxWindows is a free C++ framework designed to make cross-platform
751 programming child's play. Well, almost. wxWindows 2 supports Windows
752 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
753 underway. Other ports are under consideration. <p>
755 wxWindows is a set of libraries that allows C++ applications to
756 compile and run on several different types of computers, with minimal
757 source code changes. There is one library per supported GUI (such as
758 Motif, or Windows). As well as providing a common API (Application
759 Programming Interface) for GUI functionality, it provides
760 functionality for accessing some commonly-used operating system
761 facilities, such as copying or deleting files. wxWindows is a
762 'framework' in the sense that it provides a lot of built-in
763 functionality, which the application can use or replace as required,
764 thus saving a great deal of coding effort. Basic data structures such
765 as strings, linked lists and hash tables are also supported.
770 wxPython is a Python extension module that encapsulates the wxWindows
771 GUI classes. Currently it is only available for the Win32 and GTK
772 ports of wxWindows, but as soon as the other ports are brought up to
773 the same level as Win32 and GTK, it should be fairly trivial to
774 enable wxPython to be used with the new GUI.
778 The wxPython extension module attempts to mirror the class heiarchy
779 of wxWindows as closely as possible. This means that there is a
780 wxFrame class in wxPython that looks, smells, tastes and acts almost
781 the same as the wxFrame class in the C++ version. Unfortunately,
782 because of differences in the languages, wxPython doesn't match
783 wxWindows exactly, but the differences should be easy to absorb
784 because they are natural to Python. For example, some methods that
785 return multiple values via argument pointers in C++ will return a
786 tuple of values in Python.
790 There is still much to be done for wxPython, many classes still need
791 to be mirrored. Also, wxWindows is still somewhat of a moving target
792 so it is a bit of an effort just keeping wxPython up to date. On the
793 other hand, there are enough of the core classes completed that
794 useful applications can be written.
798 wxPython is close enough to the C++ version that the majority of
799 the wxPython documentation is actually just notes attached to the C++
800 documents that describe the places where wxPython is different. There
801 is also a series of sample programs included, and a series of
802 documentation pages that assist the programmer in getting started
808 #----------------------------------------------------------------------------
809 #----------------------------------------------------------------------------
811 if __name__
== '__main__':
814 #----------------------------------------------------------------------------