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 ##print os.getpid(); raw_input("Press a key...")
26 #---------------------------------------------------------------------------
31 ('Recent Additions', [
36 'wxXmlResourceSubclass',
40 # managed windows == things with a (optional) caption you can close
41 ('Base Frames and Dialogs', [
55 'wxFindReplaceDialog',
61 'wxSingleChoiceDialog',
65 # dialogs from libraries
69 'wxMultipleChoiceDialog',
70 'wxScrolledMessageDialog',
74 ('Core Windows/Controls', [
109 ('Custom Controls', [
122 # controls coming from other libraries
123 ('More Windows/Controls', [
124 #'wxFloatBar', deprecated
125 #'wxMVCTree', deprecated
126 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
131 'MaskedEditControls',
139 'wxDynamicSashWindow',
144 'wxMimeTypesManager',
146 'wxStyledTextCtrl_1',
147 'wxStyledTextCtrl_2',
152 # How to lay out the controls in a frame/dialog
159 'wxLayoutConstraints',
162 'wxXmlResourceHandler',
163 'wxXmlResourceSubclass',
167 ('Process and Events', [
179 ('Clipboard and DnD', [
212 # need libs not coming with the demo
213 ('Objects using an external library', [
214 'ActiveXWrapper_Acrobat',
221 ('Check out the samples dir too', [
228 #---------------------------------------------------------------------------
229 # Show how to derive a custom wxLog class
231 class MyLog(wx
.PyLog
):
232 def __init__(self
, textCtrl
, logTime
=0):
233 wx
.PyLog
.__init
__(self
)
235 self
.logTime
= logTime
237 def DoLogString(self
, message
, timeStamp
):
239 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
242 self
.tc
.AppendText(message
+ '\n')
245 class MyTP(wx
.PyTipProvider
):
247 return "This is my tip"
249 #---------------------------------------------------------------------------
250 # A class to be used to display source code in the demo. Try using the
251 # wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
252 # if there is an error, such as the stc module not being present.
258 from wxStyledTextCtrl_2
import PythonSTC
259 class DemoCodeViewer(PythonSTC
):
260 def __init__(self
, parent
, ID
):
261 PythonSTC
.__init
__(self
, parent
, ID
)
262 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
263 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
264 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
266 # Some methods to make it compatible with how the wxTextCtrl is used
267 def SetValue(self
, value
):
268 self
.SetReadOnly(False)
270 self
.SetReadOnly(True)
275 def SetInsertionPoint(self
, pos
):
276 self
.SetCurrentPos(pos
)
278 def ShowPosition(self
, pos
):
281 def GetLastPosition(self
):
282 return self
.GetLength()
284 def GetRange(self
, start
, end
):
285 return self
.GetTextRange(start
, end
)
287 def GetSelection(self
):
288 return self
.GetAnchor(), self
.GetCurrentPos()
290 def SetSelection(self
, start
, end
):
291 self
.SetSelectionStart(start
)
292 self
.SetSelectionEnd(end
)
296 class DemoCodeViewer(wx
.TextCtrl
):
297 def __init__(self
, parent
, ID
):
298 wx
.TextCtrl
.__init
__(self
, parent
, ID
, style
=
299 wx
.TE_MULTILINE | wx
.TE_READONLY |
300 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
303 #---------------------------------------------------------------------------
306 """Convert paths to the platform-specific separator"""
307 return apply(os
.path
.join
, tuple(path
.split('/')))
310 #---------------------------------------------------------------------------
312 class wxPythonDemo(wx
.Frame
):
313 overviewText
= "wxPython Overview"
315 def __init__(self
, parent
, id, title
):
316 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
317 style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
)
319 self
.cwd
= os
.getcwd()
320 self
.curOverview
= ""
323 icon
= images
.getMondrianIcon()
326 if wx
.Platform
== '__WXMSW__':
327 # setup a taskbar icon, and catch some events from it
328 self
.tbicon
= wx
.TaskBarIcon()
329 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
330 wx
.EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
331 wx
.EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
332 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
333 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
335 wx
.CallAfter(self
.ShowTip
)
338 wx
.EVT_IDLE(self
, self
.OnIdle
)
339 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
340 wx
.EVT_ICONIZE(self
, self
.OnIconfiy
)
341 wx
.EVT_MAXIMIZE(self
, self
.OnMaximize
)
344 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
346 splitter
= wx
.SplitterWindow(self
, -1)
347 splitter2
= wx
.SplitterWindow(splitter
, -1)
349 def EmptyHandler(evt
): pass
350 #wx.EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
351 #wx.EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
353 # Prevent TreeCtrl from displaying all items after destruction when True
357 self
.mainmenu
= wx
.MenuBar()
360 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
361 wx
.EVT_MENU(self
, exitID
, self
.OnFileExit
)
362 wx
.App_SetMacExitMenuItemId(exitID
)
363 self
.mainmenu
.Append(menu
, '&File')
367 for item
in _treeList
:
369 for childItem
in item
[1]:
371 submenu
.Append(mID
, childItem
)
372 wx
.EVT_MENU(self
, mID
, self
.OnDemoMenu
)
373 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
374 self
.mainmenu
.Append(menu
, '&Demo')
380 findnextID
= wx
.NewId()
382 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
383 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
384 menu
.AppendSeparator()
385 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
386 wx
.App_SetMacAboutMenuItemId(helpID
)
387 wx
.EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
388 wx
.EVT_MENU(self
, findID
, self
.OnHelpFind
)
389 wx
.EVT_MENU(self
, findnextID
, self
.OnFindNext
)
390 wx
.EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
391 wx
.EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
392 wx
.EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
393 self
.mainmenu
.Append(menu
, '&Help')
394 self
.SetMenuBar(self
.mainmenu
)
396 self
.finddata
= wx
.FindReplaceData()
399 # This is another way to set Accelerators, in addition to
400 # using the '\t<key>' syntax in the menu items.
401 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
402 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
403 (wx
.ACCEL_CTRL
, ord('F'), findID
),
404 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
406 self
.SetAcceleratorTable(aTable
)
412 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
413 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
416 root
= self
.tree
.AddRoot("wxPython Overview")
418 for item
in _treeList
:
419 child
= self
.tree
.AppendItem(root
, item
[0])
420 if not firstChild
: firstChild
= child
421 for childItem
in item
[1]:
422 theDemo
= self
.tree
.AppendItem(child
, childItem
)
423 self
.treeMap
[childItem
] = theDemo
425 self
.tree
.Expand(root
)
426 self
.tree
.Expand(firstChild
)
427 wx
.EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
428 wx
.EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
429 wx
.EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
430 wx
.EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
433 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
435 # Set up a wx.html.HtmlWindow on the Overview Notebook page
436 # we put it in a panel first because there seems to be a
437 # refresh bug of some sort (wxGTK) when it is directly in
440 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
441 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
443 else: # hopefully I can remove this hacky code soon, see SF bug #216861
444 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
445 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
446 self
.nb
.AddPage(panel
, self
.overviewText
)
448 def OnOvrSize(evt
, ovr
=self
.ovr
):
449 ovr
.SetSize(evt
.GetSize())
451 wx
.EVT_SIZE(panel
, OnOvrSize
)
452 wx
.EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
455 self
.SetOverview(self
.overviewText
, overview
)
458 # Set up a notebook page for viewing the source code of each sample
459 self
.txt
= DemoCodeViewer(self
.nb
, -1)
460 self
.nb
.AddPage(self
.txt
, "Demo Code")
461 self
.GetDemoFile('Main.py')
464 # Set up a log on the View Log Notebook page
465 self
.log
= wx
.TextCtrl(splitter2
, -1,
466 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
468 # Set the wxWindows log target to be this textctrl
469 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
471 # But instead of the above we want to show how to use our own wx.Log class
472 wx
.Log_SetActiveTarget(MyLog(self
.log
))
474 # for serious debugging
475 #wx.Log_SetActiveTarget(wx.LogStderr())
476 #wx.Log_SetTraceMask(wx.TraceMessages)
481 # add the windows to the splitter and split it.
482 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -120)
483 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
485 splitter
.SetMinimumPaneSize(20)
486 splitter2
.SetMinimumPaneSize(20)
489 # Make the splitter on the right expand the top wind when resized
490 def SplitterOnSize(evt
):
491 splitter
= evt
.GetEventObject()
492 sz
= splitter
.GetSize()
493 splitter
.SetSashPosition(sz
.height
- 120, False)
495 wx
.EVT_SIZE(splitter2
, SplitterOnSize
)
498 # select initial items
499 self
.nb
.SetSelection(0)
500 self
.tree
.SelectItem(root
)
502 if len(sys
.argv
) == 2:
504 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
508 self
.tree
.SelectItem(selectedDemo
)
509 self
.tree
.EnsureVisible(selectedDemo
)
512 wx
.LogMessage('window handle: %s' % self
.GetHandle())
515 #---------------------------------------------
516 def WriteText(self
, text
):
517 if text
[-1:] == '\n':
522 def write(self
, txt
):
525 #---------------------------------------------
526 def OnItemExpanded(self
, event
):
527 item
= event
.GetItem()
528 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
531 #---------------------------------------------
532 def OnItemCollapsed(self
, event
):
533 item
= event
.GetItem()
534 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
537 #---------------------------------------------
538 def OnTreeLeftDown(self
, event
):
539 pt
= event
.GetPosition();
540 item
, flags
= self
.tree
.HitTest(pt
)
541 if item
== self
.tree
.GetSelection():
542 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
545 #---------------------------------------------
546 def OnSelChanged(self
, event
):
550 item
= event
.GetItem()
551 itemText
= self
.tree
.GetItemText(item
)
552 self
.RunDemo(itemText
)
555 #---------------------------------------------
556 def RunDemo(self
, itemText
):
558 if self
.nb
.GetPageCount() == 3:
559 if self
.nb
.GetSelection() == 2:
560 self
.nb
.SetSelection(0)
561 # inform the window that it's time to quit if it cares
562 if self
.window
is not None:
563 if hasattr(self
.window
, "ShutdownDemo"):
564 self
.window
.ShutdownDemo()
565 wx
.SafeYield() # in case the page has pending events
566 self
.nb
.DeletePage(2)
568 if itemText
== self
.overviewText
:
569 self
.GetDemoFile('Main.py')
570 self
.SetOverview(self
.overviewText
, overview
)
575 if os
.path
.exists(itemText
+ '.py'):
577 wx
.LogMessage("Running demo %s.py..." % itemText
)
579 self
.GetDemoFile(itemText
+ '.py')
580 module
= __import__(itemText
, globals())
581 self
.SetOverview(itemText
+ " Overview", module
.overview
)
586 # in case runTest is modal, make sure things look right...
590 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
591 if self
.window
is not None:
592 self
.nb
.AddPage(self
.window
, 'Demo')
593 self
.nb
.SetSelection(2)
594 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
603 #---------------------------------------------
605 def GetDemoFile(self
, filename
):
608 self
.txt
.SetValue(open(filename
).read())
610 self
.txt
.SetValue("Cannot open %s file." % filename
)
612 self
.txt
.SetInsertionPoint(0)
613 self
.txt
.ShowPosition(0)
615 #---------------------------------------------
616 def SetOverview(self
, name
, text
):
617 self
.curOverview
= text
619 if lead
!= '<html>' and lead
!= '<HTML>':
620 text
= '<br>'.join(text
.split('\n'))
621 self
.ovr
.SetPage(text
)
622 self
.nb
.SetPageText(0, name
)
624 #---------------------------------------------
626 def OnFileExit(self
, *event
):
629 def OnHelpAbout(self
, event
):
630 from About
import MyAboutBox
631 about
= MyAboutBox(self
)
635 def OnHelpFind(self
, event
):
636 self
.nb
.SetSelection(1)
637 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
641 self
.finddlg
.Show(True)
643 def OnFind(self
, event
):
644 self
.nb
.SetSelection(1)
645 end
= self
.txt
.GetLastPosition()
646 textstring
= self
.txt
.GetRange(0, end
).lower()
647 start
= self
.txt
.GetSelection()[1]
648 findstring
= self
.finddata
.GetFindString().lower()
649 loc
= textstring
.find(findstring
, start
)
650 if loc
== -1 and start
!= 0:
651 # string not found, start at beginning
653 loc
= textstring
.find(findstring
, start
)
655 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
656 'Find String Not Found in Demo File',
657 wx
.OK | wx
.ICON_INFORMATION
)
662 self
.finddlg
.SetFocus()
665 self
.finddlg
.Destroy()
666 self
.txt
.ShowPosition(loc
)
667 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
671 def OnFindNext(self
, event
):
672 if self
.finddata
.GetFindString():
675 self
.OnHelpFind(event
)
677 def OnFindClose(self
, event
):
678 event
.GetDialog().Destroy()
681 #---------------------------------------------
682 def OnCloseWindow(self
, event
):
686 if hasattr(self
, "tbicon"):
691 #---------------------------------------------
692 def OnIdle(self
, event
):
694 self
.otherWin
.Raise()
695 self
.window
= self
.otherWin
699 #---------------------------------------------
702 showTipText
= open(opj("data/showTips")).read()
703 showTip
, index
= eval(showTipText
)
705 showTip
, index
= (1, 0)
707 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
709 showTip
= wx
.ShowTip(self
, tp
)
710 index
= tp
.GetCurrentTip()
711 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
714 #---------------------------------------------
715 def OnDemoMenu(self
, event
):
717 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
721 self
.tree
.SelectItem(selectedDemo
)
722 self
.tree
.EnsureVisible(selectedDemo
)
725 #---------------------------------------------
726 def OnTaskBarActivate(self
, evt
):
727 if self
.IsIconized():
729 if not self
.IsShown():
733 #---------------------------------------------
735 TBMENU_RESTORE
= 1000
738 def OnTaskBarMenu(self
, evt
):
740 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
741 menu
.Append(self
.TBMENU_CLOSE
, "Close")
742 self
.tbicon
.PopupMenu(menu
)
745 #---------------------------------------------
746 def OnTaskBarClose(self
, evt
):
749 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
750 # prod the main idle handler a bit to get the window to actually close
751 wx
.GetApp().ProcessIdle()
754 #---------------------------------------------
755 def OnIconfiy(self
, evt
):
756 wx
.LogMessage("OnIconfiy")
759 #---------------------------------------------
760 def OnMaximize(self
, evt
):
761 wx
.LogMessage("OnMaximize")
767 #---------------------------------------------------------------------------
768 #---------------------------------------------------------------------------
770 class MySplashScreen(wx
.SplashScreen
):
772 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
773 wx
.SplashScreen
.__init
__(self
, bmp
,
774 wx
.SPLASH_CENTRE_ON_SCREEN|wx
.SPLASH_TIMEOUT
,
776 style
= wx
.SIMPLE_BORDER|wx
.FRAME_NO_TASKBAR|wx
.STAY_ON_TOP
)
777 wx
.EVT_CLOSE(self
, self
.OnClose
)
779 def OnClose(self
, evt
):
780 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
782 evt
.Skip() # Make sure the default handler runs too...
788 Create and show the splash screen. It will then create and show
789 the main frame when it is time to do so.
793 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
794 #locale.setlocale(locale.LC_ALL, 'fr')
796 wx
.InitAllImageHandlers()
797 splash
= MySplashScreen()
803 #---------------------------------------------------------------------------
807 demoPath
= os
.path
.dirname(__file__
)
811 app
= MyApp(0) #wx.Platform == "__WXMAC__")
815 #---------------------------------------------------------------------------
819 overview
= """<html><body>
822 <p> wxPython is a <b>GUI toolkit</b> for the <a
823 href="http://www.python.org/">Python</a> programming language. It
824 allows Python programmers to create programs with a robust, highly
825 functional graphical user interface, simply and easily. It is
826 implemented as a Python extension module (native code) that wraps the
827 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
828 platform GUI library, which is written in C++.
830 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
831 means that it is free for anyone to use and the source code is
832 available for anyone to look at and modify. Or anyone can contribute
833 fixes or enhancements to the project.
835 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
836 same program will run on multiple platforms without modification.
837 Currently supported platforms are 32-bit Microsoft Windows, most Unix
838 or unix-like systems, and Macintosh OS X. Since the language is
839 Python, wxPython programs are <b>simple, easy</b> to write and easy to
842 <p> <b>This demo</b> is not only a collection of test cases for
843 wxPython, but is also designed to help you learn about and how to use
844 wxPython. Each sample is listed in the tree control on the left.
845 When a sample is selected in the tree then a module is loaded and run
846 (usually in a tab of this notebook,) and the source code of the module
847 is loaded in another tab for you to browse and learn from.
852 #----------------------------------------------------------------------------
853 #----------------------------------------------------------------------------
855 if __name__
== '__main__':
858 #----------------------------------------------------------------------------