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 #----------------------------------------------------------------------------
16 import wx
# This module uses the new wx namespace
23 #---------------------------------------------------------------------------
28 ('Recent Additions', [
35 # managed windows == things with a (optional) caption you can close
36 ('Base Frames and Dialogs', [
50 'wxFindReplaceDialog',
56 'wxSingleChoiceDialog',
60 # dialogs from libraries
64 'wxMultipleChoiceDialog',
65 'wxScrolledMessageDialog',
69 ('Core Windows/Controls', [
105 # controls coming from other libraries
106 ('More Windows/Controls', [
107 #'wxFloatBar', deprecated
108 #'wxMVCTree', deprecated
109 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
117 'MaskedEditControls',
126 'wxDynamicSashWindow',
133 'wxMimeTypesManager',
137 'wxStyledTextCtrl_1',
138 'wxStyledTextCtrl_2',
144 # How to lay out the controls in a frame/dialog
150 'wxLayoutConstraints',
153 'wxXmlResourceHandler',
157 ('Process and Events', [
169 ('Clipboard and DnD', [
202 # need libs not coming with the demo
203 ('Objects using an external library', [
204 'ActiveXWrapper_Acrobat',
211 ('Check out the samples dir too', [
218 #---------------------------------------------------------------------------
219 # Show how to derive a custom wxLog class
221 class MyLog(wx
.PyLog
):
222 def __init__(self
, textCtrl
, logTime
=0):
223 wx
.PyLog
.__init
__(self
)
225 self
.logTime
= logTime
227 def DoLogString(self
, message
, timeStamp
):
229 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
232 self
.tc
.AppendText(message
+ '\n')
235 class MyTP(wx
.PyTipProvider
):
237 return "This is my tip"
239 #---------------------------------------------------------------------------
240 # A class to be used to display source code in the demo. Try using the
241 # wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
242 # if there is an error, such as the stc module not being present.
248 from wxStyledTextCtrl_2
import PythonSTC
249 class DemoCodeViewer(PythonSTC
):
250 def __init__(self
, parent
, ID
):
251 PythonSTC
.__init
__(self
, parent
, ID
)
252 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
253 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
254 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
256 # Some methods to make it compatible with how the wxTextCtrl is used
257 def SetValue(self
, value
):
258 self
.SetReadOnly(False)
260 self
.SetReadOnly(True)
265 def SetInsertionPoint(self
, pos
):
266 self
.SetCurrentPos(pos
)
268 def ShowPosition(self
, pos
):
271 def GetLastPosition(self
):
272 return self
.GetLength()
274 def GetRange(self
, start
, end
):
275 return self
.GetTextRange(start
, end
)
277 def GetSelection(self
):
278 return self
.GetAnchor(), self
.GetCurrentPos()
280 def SetSelection(self
, start
, end
):
281 self
.SetSelectionStart(start
)
282 self
.SetSelectionEnd(end
)
286 class DemoCodeViewer(wx
.TextCtrl
):
287 def __init__(self
, parent
, ID
):
288 wx
.TextCtrl
.__init
__(self
, parent
, ID
, style
=
289 wx
.TE_MULTILINE | wx
.TE_READONLY |
290 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
293 #---------------------------------------------------------------------------
296 """Convert paths to the platform-specific separator"""
297 return apply(os
.path
.join
, tuple(path
.split('/')))
300 #---------------------------------------------------------------------------
302 class wxPythonDemo(wx
.Frame
):
303 overviewText
= "wxPython Overview"
305 def __init__(self
, parent
, id, title
):
306 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
307 style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
)
309 self
.cwd
= os
.getcwd()
310 self
.curOverview
= ""
313 icon
= images
.getMondrianIcon()
316 if wx
.Platform
== '__WXMSW__':
317 # setup a taskbar icon, and catch some events from it
318 self
.tbicon
= wx
.TaskBarIcon()
319 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
320 wx
.EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
321 wx
.EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
322 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
323 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
325 wx
.CallAfter(self
.ShowTip
)
328 wx
.EVT_IDLE(self
, self
.OnIdle
)
329 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
330 wx
.EVT_ICONIZE(self
, self
.OnIconfiy
)
331 wx
.EVT_MAXIMIZE(self
, self
.OnMaximize
)
334 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
336 splitter
= wx
.SplitterWindow(self
, -1)
337 splitter2
= wx
.SplitterWindow(splitter
, -1)
339 def EmptyHandler(evt
): pass
340 #wx.EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
341 #wx.EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
343 # Prevent TreeCtrl from displaying all items after destruction when True
347 self
.mainmenu
= wx
.MenuBar()
350 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
351 wx
.EVT_MENU(self
, exitID
, self
.OnFileExit
)
352 wx
.App_SetMacExitMenuItemId(exitID
)
353 self
.mainmenu
.Append(menu
, '&File')
357 for item
in _treeList
:
359 for childItem
in item
[1]:
361 submenu
.Append(mID
, childItem
)
362 wx
.EVT_MENU(self
, mID
, self
.OnDemoMenu
)
363 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
364 self
.mainmenu
.Append(menu
, '&Demo')
370 findnextID
= wx
.NewId()
372 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
373 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
374 menu
.AppendSeparator()
375 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
376 wx
.App_SetMacAboutMenuItemId(helpID
)
377 wx
.EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
378 wx
.EVT_MENU(self
, findID
, self
.OnHelpFind
)
379 wx
.EVT_MENU(self
, findnextID
, self
.OnFindNext
)
380 wx
.EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
381 wx
.EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
382 wx
.EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
383 self
.mainmenu
.Append(menu
, '&Help')
384 self
.SetMenuBar(self
.mainmenu
)
386 self
.finddata
= wx
.FindReplaceData()
389 # This is another way to set Accelerators, in addition to
390 # using the '\t<key>' syntax in the menu items.
391 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
392 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
393 (wx
.ACCEL_CTRL
, ord('F'), findID
),
394 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
396 self
.SetAcceleratorTable(aTable
)
402 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
403 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
406 root
= self
.tree
.AddRoot("wxPython Overview")
408 for item
in _treeList
:
409 child
= self
.tree
.AppendItem(root
, item
[0])
410 if not firstChild
: firstChild
= child
411 for childItem
in item
[1]:
412 theDemo
= self
.tree
.AppendItem(child
, childItem
)
413 self
.treeMap
[childItem
] = theDemo
415 self
.tree
.Expand(root
)
416 self
.tree
.Expand(firstChild
)
417 wx
.EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
418 wx
.EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
419 wx
.EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
420 wx
.EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
423 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
425 # Set up a wx.html.HtmlWindow on the Overview Notebook page
426 # we put it in a panel first because there seems to be a
427 # refresh bug of some sort (wxGTK) when it is directly in
430 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
431 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
433 else: # hopefully I can remove this hacky code soon, see SF bug #216861
434 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
435 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
436 self
.nb
.AddPage(panel
, self
.overviewText
)
438 def OnOvrSize(evt
, ovr
=self
.ovr
):
439 ovr
.SetSize(evt
.GetSize())
441 wx
.EVT_SIZE(panel
, OnOvrSize
)
442 wx
.EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
445 self
.SetOverview(self
.overviewText
, overview
)
448 # Set up a notebook page for viewing the source code of each sample
449 self
.txt
= DemoCodeViewer(self
.nb
, -1)
450 self
.nb
.AddPage(self
.txt
, "Demo Code")
451 self
.GetDemoFile('Main.py')
454 # Set up a log on the View Log Notebook page
455 self
.log
= wx
.TextCtrl(splitter2
, -1,
456 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
458 # Set the wxWindows log target to be this textctrl
459 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
461 # But instead of the above we want to show how to use our own wx.Log class
462 wx
.Log_SetActiveTarget(MyLog(self
.log
))
464 # for serious debugging
465 #wx.Log_SetActiveTarget(wx.LogStderr())
466 #wx.Log_SetTraceMask(wx.TraceMessages)
471 # add the windows to the splitter and split it.
472 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -120)
473 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
475 splitter
.SetMinimumPaneSize(20)
476 splitter2
.SetMinimumPaneSize(20)
479 # Make the splitter on the right expand the top wind when resized
480 def SplitterOnSize(evt
):
481 splitter
= evt
.GetEventObject()
482 sz
= splitter
.GetSize()
483 splitter
.SetSashPosition(sz
.height
- 120, False)
485 wx
.EVT_SIZE(splitter2
, SplitterOnSize
)
488 # select initial items
489 self
.nb
.SetSelection(0)
490 self
.tree
.SelectItem(root
)
492 if len(sys
.argv
) == 2:
494 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
498 self
.tree
.SelectItem(selectedDemo
)
499 self
.tree
.EnsureVisible(selectedDemo
)
502 wx
.LogMessage('window handle: %s' % self
.GetHandle())
505 #---------------------------------------------
506 def WriteText(self
, text
):
507 if text
[-1:] == '\n':
512 def write(self
, txt
):
515 #---------------------------------------------
516 def OnItemExpanded(self
, event
):
517 item
= event
.GetItem()
518 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
521 #---------------------------------------------
522 def OnItemCollapsed(self
, event
):
523 item
= event
.GetItem()
524 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
527 #---------------------------------------------
528 def OnTreeLeftDown(self
, event
):
529 pt
= event
.GetPosition();
530 item
, flags
= self
.tree
.HitTest(pt
)
531 if item
== self
.tree
.GetSelection():
532 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
535 #---------------------------------------------
536 def OnSelChanged(self
, event
):
540 item
= event
.GetItem()
541 itemText
= self
.tree
.GetItemText(item
)
542 self
.RunDemo(itemText
)
545 #---------------------------------------------
546 def RunDemo(self
, itemText
):
548 if self
.nb
.GetPageCount() == 3:
549 if self
.nb
.GetSelection() == 2:
550 self
.nb
.SetSelection(0)
551 # inform the window that it's time to quit if it cares
552 if self
.window
is not None:
553 if hasattr(self
.window
, "ShutdownDemo"):
554 self
.window
.ShutdownDemo()
555 wx
.SafeYield() # in case the page has pending events
556 self
.nb
.DeletePage(2)
558 if itemText
== self
.overviewText
:
559 self
.GetDemoFile('Main.py')
560 self
.SetOverview(self
.overviewText
, overview
)
565 if os
.path
.exists(itemText
+ '.py'):
567 wx
.LogMessage("Running demo %s.py..." % itemText
)
569 self
.GetDemoFile(itemText
+ '.py')
570 module
= __import__(itemText
, globals())
571 self
.SetOverview(itemText
+ " Overview", module
.overview
)
576 # in case runTest is modal, make sure things look right...
580 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
581 if self
.window
is not None:
582 self
.nb
.AddPage(self
.window
, 'Demo')
583 self
.nb
.SetSelection(2)
584 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
593 #---------------------------------------------
595 def GetDemoFile(self
, filename
):
598 self
.txt
.SetValue(open(filename
).read())
600 self
.txt
.SetValue("Cannot open %s file." % filename
)
602 self
.txt
.SetInsertionPoint(0)
603 self
.txt
.ShowPosition(0)
605 #---------------------------------------------
606 def SetOverview(self
, name
, text
):
607 self
.curOverview
= text
609 if lead
!= '<html>' and lead
!= '<HTML>':
610 text
= '<br>'.join(text
.split('\n'))
611 self
.ovr
.SetPage(text
)
612 self
.nb
.SetPageText(0, name
)
614 #---------------------------------------------
616 def OnFileExit(self
, *event
):
619 def OnHelpAbout(self
, event
):
620 from About
import MyAboutBox
621 about
= MyAboutBox(self
)
625 def OnHelpFind(self
, event
):
626 self
.nb
.SetSelection(1)
627 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
631 self
.finddlg
.Show(True)
633 def OnFind(self
, event
):
634 self
.nb
.SetSelection(1)
635 end
= self
.txt
.GetLastPosition()
636 textstring
= self
.txt
.GetRange(0, end
).lower()
637 start
= self
.txt
.GetSelection()[1]
638 findstring
= self
.finddata
.GetFindString().lower()
639 loc
= textstring
.find(findstring
, start
)
640 if loc
== -1 and start
!= 0:
641 # string not found, start at beginning
643 loc
= textstring
.find(findstring
, start
)
645 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
646 'Find String Not Found in Demo File',
647 wx
.OK | wx
.ICON_INFORMATION
)
652 self
.finddlg
.SetFocus()
655 self
.finddlg
.Destroy()
656 self
.txt
.ShowPosition(loc
)
657 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
661 def OnFindNext(self
, event
):
662 if self
.finddata
.GetFindString():
665 self
.OnHelpFind(event
)
667 def OnFindClose(self
, event
):
668 event
.GetDialog().Destroy()
671 #---------------------------------------------
672 def OnCloseWindow(self
, event
):
676 if hasattr(self
, "tbicon"):
681 #---------------------------------------------
682 def OnIdle(self
, event
):
684 self
.otherWin
.Raise()
685 self
.window
= self
.otherWin
689 #---------------------------------------------
692 showTipText
= open(opj("data/showTips")).read()
693 showTip
, index
= eval(showTipText
)
695 showTip
, index
= (1, 0)
697 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
699 showTip
= wx
.ShowTip(self
, tp
)
700 index
= tp
.GetCurrentTip()
701 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
704 #---------------------------------------------
705 def OnDemoMenu(self
, event
):
707 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
711 self
.tree
.SelectItem(selectedDemo
)
712 self
.tree
.EnsureVisible(selectedDemo
)
715 #---------------------------------------------
716 def OnTaskBarActivate(self
, evt
):
717 if self
.IsIconized():
719 if not self
.IsShown():
723 #---------------------------------------------
725 TBMENU_RESTORE
= 1000
728 def OnTaskBarMenu(self
, evt
):
730 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
731 menu
.Append(self
.TBMENU_CLOSE
, "Close")
732 self
.tbicon
.PopupMenu(menu
)
735 #---------------------------------------------
736 def OnTaskBarClose(self
, evt
):
739 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
740 # prod the main idle handler a bit to get the window to actually close
741 wx
.GetApp().ProcessIdle()
744 #---------------------------------------------
745 def OnIconfiy(self
, evt
):
746 wx
.LogMessage("OnIconfiy")
749 #---------------------------------------------
750 def OnMaximize(self
, evt
):
751 wx
.LogMessage("OnMaximize")
757 #---------------------------------------------------------------------------
758 #---------------------------------------------------------------------------
760 class MySplashScreen(wx
.SplashScreen
):
762 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
763 wx
.SplashScreen
.__init
__(self
, bmp
,
764 wx
.SPLASH_CENTRE_ON_SCREEN|wx
.SPLASH_TIMEOUT
,
766 style
= wx
.SIMPLE_BORDER|wx
.FRAME_NO_TASKBAR|wx
.STAY_ON_TOP
)
767 wx
.EVT_CLOSE(self
, self
.OnClose
)
769 def OnClose(self
, evt
):
770 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
772 evt
.Skip() # Make sure the default handler runs too...
778 Create and show the splash screen. It will then create and show
779 the main frame when it is time to do so.
783 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
784 #locale.setlocale(locale.LC_ALL, 'fr')
786 wx
.InitAllImageHandlers()
787 splash
= MySplashScreen()
793 #---------------------------------------------------------------------------
797 demoPath
= os
.path
.dirname(__file__
)
801 app
= MyApp(wx
.Platform
== "__WXMAC__")
805 #---------------------------------------------------------------------------
809 overview
= """<html><body>
812 <p> wxPython is a <b>GUI toolkit</b> for the <a
813 href="http://www.python.org/">Python</a> programming language. It
814 allows Python programmers to create programs with a robust, highly
815 functional graphical user interface, simply and easily. It is
816 implemented as a Python extension module (native code) that wraps the
817 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
818 platform GUI library, which is written in C++.
820 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
821 means that it is free for anyone to use and the source code is
822 available for anyone to look at and modify. Or anyone can contribute
823 fixes or enhancements to the project.
825 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
826 same program will run on multiple platforms without modification.
827 Currently supported platforms are 32-bit Microsoft Windows, most Unix
828 or unix-like systems, and Macintosh OS X. Since the language is
829 Python, wxPython programs are <b>simple, easy</b> to write and easy to
832 <p> <b>This demo</b> is not only a collection of test cases for
833 wxPython, but is also designed to help you learn about and how to use
834 wxPython. Each sample is listed in the tree control on the left.
835 When a sample is selected in the tree then a module is loaded and run
836 (usually in a tab of this notebook,) and the source code of the module
837 is loaded in another tab for you to browse and learn from.
842 #----------------------------------------------------------------------------
843 #----------------------------------------------------------------------------
845 if __name__
== '__main__':
848 #----------------------------------------------------------------------------