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',
41 # managed windows == things with a (optional) caption you can close
42 ('Base Frames and Dialogs', [
56 'wxFindReplaceDialog',
62 'wxSingleChoiceDialog',
66 # dialogs from libraries
70 'wxMultipleChoiceDialog',
71 'wxScrolledMessageDialog',
75 ('Core Windows/Controls', [
110 ('Custom Controls', [
123 # controls coming from other libraries
124 ('More Windows/Controls', [
125 #'wxFloatBar', deprecated
126 #'wxMVCTree', deprecated
127 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
132 'MaskedEditControls',
140 'wxDynamicSashWindow',
145 'wxMimeTypesManager',
148 'wxStyledTextCtrl_1',
149 'wxStyledTextCtrl_2',
154 # How to lay out the controls in a frame/dialog
161 'wxLayoutConstraints',
164 'wxXmlResourceHandler',
165 'wxXmlResourceSubclass',
169 ('Process and Events', [
181 ('Clipboard and DnD', [
215 # need libs not coming with the demo
216 ('Objects using an external library', [
217 'ActiveXWrapper_Acrobat',
224 ('Check out the samples dir too', [
231 #---------------------------------------------------------------------------
232 # Show how to derive a custom wxLog class
234 class MyLog(wx
.PyLog
):
235 def __init__(self
, textCtrl
, logTime
=0):
236 wx
.PyLog
.__init
__(self
)
238 self
.logTime
= logTime
240 def DoLogString(self
, message
, timeStamp
):
242 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
245 self
.tc
.AppendText(message
+ '\n')
248 class MyTP(wx
.PyTipProvider
):
250 return "This is my tip"
252 #---------------------------------------------------------------------------
253 # A class to be used to display source code in the demo. Try using the
254 # wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
255 # if there is an error, such as the stc module not being present.
261 from wxStyledTextCtrl_2
import PythonSTC
262 class DemoCodeViewer(PythonSTC
):
263 def __init__(self
, parent
, ID
):
264 PythonSTC
.__init
__(self
, parent
, ID
)
265 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
266 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
267 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
269 # Some methods to make it compatible with how the wxTextCtrl is used
270 def SetValue(self
, value
):
271 self
.SetReadOnly(False)
273 self
.SetReadOnly(True)
278 def SetInsertionPoint(self
, pos
):
279 self
.SetCurrentPos(pos
)
281 def ShowPosition(self
, pos
):
284 def GetLastPosition(self
):
285 return self
.GetLength()
287 def GetRange(self
, start
, end
):
288 return self
.GetTextRange(start
, end
)
290 def GetSelection(self
):
291 return self
.GetAnchor(), self
.GetCurrentPos()
293 def SetSelection(self
, start
, end
):
294 self
.SetSelectionStart(start
)
295 self
.SetSelectionEnd(end
)
299 class DemoCodeViewer(wx
.TextCtrl
):
300 def __init__(self
, parent
, ID
):
301 wx
.TextCtrl
.__init
__(self
, parent
, ID
, style
=
302 wx
.TE_MULTILINE | wx
.TE_READONLY |
303 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
306 #---------------------------------------------------------------------------
309 """Convert paths to the platform-specific separator"""
310 return apply(os
.path
.join
, tuple(path
.split('/')))
313 #---------------------------------------------------------------------------
315 class wxPythonDemo(wx
.Frame
):
316 overviewText
= "wxPython Overview"
318 def __init__(self
, parent
, id, title
):
319 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
320 style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
)
322 self
.cwd
= os
.getcwd()
323 self
.curOverview
= ""
326 icon
= images
.getMondrianIcon()
329 if wx
.Platform
== '__WXMSW__':
330 # setup a taskbar icon, and catch some events from it
331 self
.tbicon
= wx
.TaskBarIcon()
332 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
333 wx
.EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
334 wx
.EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
335 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
336 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
338 wx
.CallAfter(self
.ShowTip
)
341 wx
.EVT_IDLE(self
, self
.OnIdle
)
342 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
343 wx
.EVT_ICONIZE(self
, self
.OnIconfiy
)
344 wx
.EVT_MAXIMIZE(self
, self
.OnMaximize
)
347 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
349 splitter
= wx
.SplitterWindow(self
, -1)
350 splitter2
= wx
.SplitterWindow(splitter
, -1)
352 def EmptyHandler(evt
): pass
353 #wx.EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
354 #wx.EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
356 # Prevent TreeCtrl from displaying all items after destruction when True
360 self
.mainmenu
= wx
.MenuBar()
363 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
364 wx
.EVT_MENU(self
, exitID
, self
.OnFileExit
)
365 wx
.App_SetMacExitMenuItemId(exitID
)
366 self
.mainmenu
.Append(menu
, '&File')
370 for item
in _treeList
:
372 for childItem
in item
[1]:
374 submenu
.Append(mID
, childItem
)
375 wx
.EVT_MENU(self
, mID
, self
.OnDemoMenu
)
376 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
377 self
.mainmenu
.Append(menu
, '&Demo')
383 findnextID
= wx
.NewId()
385 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
386 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
387 menu
.AppendSeparator()
388 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
389 wx
.App_SetMacAboutMenuItemId(helpID
)
390 wx
.EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
391 wx
.EVT_MENU(self
, findID
, self
.OnHelpFind
)
392 wx
.EVT_MENU(self
, findnextID
, self
.OnFindNext
)
393 wx
.EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
394 wx
.EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
395 wx
.EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
396 self
.mainmenu
.Append(menu
, '&Help')
397 self
.SetMenuBar(self
.mainmenu
)
399 self
.finddata
= wx
.FindReplaceData()
402 # This is another way to set Accelerators, in addition to
403 # using the '\t<key>' syntax in the menu items.
404 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
405 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
406 (wx
.ACCEL_CTRL
, ord('F'), findID
),
407 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
409 self
.SetAcceleratorTable(aTable
)
415 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
416 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
419 root
= self
.tree
.AddRoot("wxPython Overview")
421 for item
in _treeList
:
422 child
= self
.tree
.AppendItem(root
, item
[0])
423 if not firstChild
: firstChild
= child
424 for childItem
in item
[1]:
425 theDemo
= self
.tree
.AppendItem(child
, childItem
)
426 self
.treeMap
[childItem
] = theDemo
428 self
.tree
.Expand(root
)
429 self
.tree
.Expand(firstChild
)
430 wx
.EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
431 wx
.EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
432 wx
.EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
433 wx
.EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
436 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
438 # Set up a wx.html.HtmlWindow on the Overview Notebook page
439 # we put it in a panel first because there seems to be a
440 # refresh bug of some sort (wxGTK) when it is directly in
443 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
444 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
446 else: # hopefully I can remove this hacky code soon, see SF bug #216861
447 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
448 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
449 self
.nb
.AddPage(panel
, self
.overviewText
)
451 def OnOvrSize(evt
, ovr
=self
.ovr
):
452 ovr
.SetSize(evt
.GetSize())
454 wx
.EVT_SIZE(panel
, OnOvrSize
)
455 wx
.EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
458 self
.SetOverview(self
.overviewText
, overview
)
461 # Set up a notebook page for viewing the source code of each sample
462 self
.txt
= DemoCodeViewer(self
.nb
, -1)
463 self
.nb
.AddPage(self
.txt
, "Demo Code")
464 self
.GetDemoFile('Main.py')
467 # Set up a log on the View Log Notebook page
468 self
.log
= wx
.TextCtrl(splitter2
, -1,
469 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
471 # Set the wxWindows log target to be this textctrl
472 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
474 # But instead of the above we want to show how to use our own wx.Log class
475 wx
.Log_SetActiveTarget(MyLog(self
.log
))
477 # for serious debugging
478 #wx.Log_SetActiveTarget(wx.LogStderr())
479 #wx.Log_SetTraceMask(wx.TraceMessages)
484 # add the windows to the splitter and split it.
485 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -120)
486 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
488 splitter
.SetMinimumPaneSize(20)
489 splitter2
.SetMinimumPaneSize(20)
492 # Make the splitter on the right expand the top wind when resized
493 def SplitterOnSize(evt
):
494 splitter
= evt
.GetEventObject()
495 sz
= splitter
.GetSize()
496 splitter
.SetSashPosition(sz
.height
- 120, False)
498 wx
.EVT_SIZE(splitter2
, SplitterOnSize
)
501 # select initial items
502 self
.nb
.SetSelection(0)
503 self
.tree
.SelectItem(root
)
505 if len(sys
.argv
) == 2:
507 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
511 self
.tree
.SelectItem(selectedDemo
)
512 self
.tree
.EnsureVisible(selectedDemo
)
515 wx
.LogMessage('window handle: %s' % self
.GetHandle())
518 #---------------------------------------------
519 def WriteText(self
, text
):
520 if text
[-1:] == '\n':
525 def write(self
, txt
):
528 #---------------------------------------------
529 def OnItemExpanded(self
, event
):
530 item
= event
.GetItem()
531 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
534 #---------------------------------------------
535 def OnItemCollapsed(self
, event
):
536 item
= event
.GetItem()
537 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
540 #---------------------------------------------
541 def OnTreeLeftDown(self
, event
):
542 pt
= event
.GetPosition();
543 item
, flags
= self
.tree
.HitTest(pt
)
544 if item
== self
.tree
.GetSelection():
545 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
548 #---------------------------------------------
549 def OnSelChanged(self
, event
):
553 item
= event
.GetItem()
554 itemText
= self
.tree
.GetItemText(item
)
555 self
.RunDemo(itemText
)
558 #---------------------------------------------
559 def RunDemo(self
, itemText
):
561 if self
.nb
.GetPageCount() == 3:
562 if self
.nb
.GetSelection() == 2:
563 self
.nb
.SetSelection(0)
564 # inform the window that it's time to quit if it cares
565 if self
.window
is not None:
566 if hasattr(self
.window
, "ShutdownDemo"):
567 self
.window
.ShutdownDemo()
568 wx
.SafeYield() # in case the page has pending events
569 self
.nb
.DeletePage(2)
571 if itemText
== self
.overviewText
:
572 self
.GetDemoFile('Main.py')
573 self
.SetOverview(self
.overviewText
, overview
)
578 if os
.path
.exists(itemText
+ '.py'):
580 wx
.LogMessage("Running demo %s.py..." % itemText
)
582 self
.GetDemoFile(itemText
+ '.py')
583 module
= __import__(itemText
, globals())
584 self
.SetOverview(itemText
+ " Overview", module
.overview
)
589 # in case runTest is modal, make sure things look right...
593 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
594 if self
.window
is not None:
595 self
.nb
.AddPage(self
.window
, 'Demo')
596 self
.nb
.SetSelection(2)
597 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
606 #---------------------------------------------
608 def GetDemoFile(self
, filename
):
611 self
.txt
.SetValue(open(filename
).read())
613 self
.txt
.SetValue("Cannot open %s file." % filename
)
615 self
.txt
.SetInsertionPoint(0)
616 self
.txt
.ShowPosition(0)
618 #---------------------------------------------
619 def SetOverview(self
, name
, text
):
620 self
.curOverview
= text
622 if lead
!= '<html>' and lead
!= '<HTML>':
623 text
= '<br>'.join(text
.split('\n'))
624 self
.ovr
.SetPage(text
)
625 self
.nb
.SetPageText(0, name
)
627 #---------------------------------------------
629 def OnFileExit(self
, *event
):
632 def OnHelpAbout(self
, event
):
633 from About
import MyAboutBox
634 about
= MyAboutBox(self
)
638 def OnHelpFind(self
, event
):
639 self
.nb
.SetSelection(1)
640 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
644 self
.finddlg
.Show(True)
646 def OnFind(self
, event
):
647 self
.nb
.SetSelection(1)
648 end
= self
.txt
.GetLastPosition()
649 textstring
= self
.txt
.GetRange(0, end
).lower()
650 start
= self
.txt
.GetSelection()[1]
651 findstring
= self
.finddata
.GetFindString().lower()
652 loc
= textstring
.find(findstring
, start
)
653 if loc
== -1 and start
!= 0:
654 # string not found, start at beginning
656 loc
= textstring
.find(findstring
, start
)
658 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
659 'Find String Not Found in Demo File',
660 wx
.OK | wx
.ICON_INFORMATION
)
665 self
.finddlg
.SetFocus()
668 self
.finddlg
.Destroy()
669 self
.txt
.ShowPosition(loc
)
670 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
674 def OnFindNext(self
, event
):
675 if self
.finddata
.GetFindString():
678 self
.OnHelpFind(event
)
680 def OnFindClose(self
, event
):
681 event
.GetDialog().Destroy()
684 #---------------------------------------------
685 def OnCloseWindow(self
, event
):
689 if hasattr(self
, "tbicon"):
694 #---------------------------------------------
695 def OnIdle(self
, event
):
697 self
.otherWin
.Raise()
698 self
.window
= self
.otherWin
702 #---------------------------------------------
705 showTipText
= open(opj("data/showTips")).read()
706 showTip
, index
= eval(showTipText
)
708 showTip
, index
= (1, 0)
710 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
712 showTip
= wx
.ShowTip(self
, tp
)
713 index
= tp
.GetCurrentTip()
714 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
717 #---------------------------------------------
718 def OnDemoMenu(self
, event
):
720 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
724 self
.tree
.SelectItem(selectedDemo
)
725 self
.tree
.EnsureVisible(selectedDemo
)
728 #---------------------------------------------
729 def OnTaskBarActivate(self
, evt
):
730 if self
.IsIconized():
732 if not self
.IsShown():
736 #---------------------------------------------
738 TBMENU_RESTORE
= 1000
741 def OnTaskBarMenu(self
, evt
):
743 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
744 menu
.Append(self
.TBMENU_CLOSE
, "Close")
745 self
.tbicon
.PopupMenu(menu
)
748 #---------------------------------------------
749 def OnTaskBarClose(self
, evt
):
752 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
753 # prod the main idle handler a bit to get the window to actually close
754 wx
.GetApp().ProcessIdle()
757 #---------------------------------------------
758 def OnIconfiy(self
, evt
):
759 wx
.LogMessage("OnIconfiy")
762 #---------------------------------------------
763 def OnMaximize(self
, evt
):
764 wx
.LogMessage("OnMaximize")
770 #---------------------------------------------------------------------------
771 #---------------------------------------------------------------------------
773 class MySplashScreen(wx
.SplashScreen
):
775 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
776 wx
.SplashScreen
.__init
__(self
, bmp
,
777 wx
.SPLASH_CENTRE_ON_SCREEN|wx
.SPLASH_TIMEOUT
,
779 style
= wx
.SIMPLE_BORDER|wx
.FRAME_NO_TASKBAR|wx
.STAY_ON_TOP
)
780 wx
.EVT_CLOSE(self
, self
.OnClose
)
782 def OnClose(self
, evt
):
783 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
785 evt
.Skip() # Make sure the default handler runs too...
791 Create and show the splash screen. It will then create and show
792 the main frame when it is time to do so.
796 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
797 #locale.setlocale(locale.LC_ALL, 'fr')
799 wx
.InitAllImageHandlers()
800 splash
= MySplashScreen()
806 #---------------------------------------------------------------------------
810 demoPath
= os
.path
.dirname(__file__
)
814 app
= MyApp(0) #wx.Platform == "__WXMAC__")
818 #---------------------------------------------------------------------------
822 overview
= """<html><body>
825 <p> wxPython is a <b>GUI toolkit</b> for the <a
826 href="http://www.python.org/">Python</a> programming language. It
827 allows Python programmers to create programs with a robust, highly
828 functional graphical user interface, simply and easily. It is
829 implemented as a Python extension module (native code) that wraps the
830 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
831 platform GUI library, which is written in C++.
833 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
834 means that it is free for anyone to use and the source code is
835 available for anyone to look at and modify. Or anyone can contribute
836 fixes or enhancements to the project.
838 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
839 same program will run on multiple platforms without modification.
840 Currently supported platforms are 32-bit Microsoft Windows, most Unix
841 or unix-like systems, and Macintosh OS X. Since the language is
842 Python, wxPython programs are <b>simple, easy</b> to write and easy to
845 <p> <b>This demo</b> is not only a collection of test cases for
846 wxPython, but is also designed to help you learn about and how to use
847 wxPython. Each sample is listed in the tree control on the left.
848 When a sample is selected in the tree then a module is loaded and run
849 (usually in a tab of this notebook,) and the source code of the module
850 is loaded in another tab for you to browse and learn from.
855 #----------------------------------------------------------------------------
856 #----------------------------------------------------------------------------
858 if __name__
== '__main__':
861 #----------------------------------------------------------------------------