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 # Use Python's bool constants if available, make aliases if not
30 #---------------------------------------------------------------------------
35 ('Recent Additions', [
42 # managed windows == things with a (optional) caption you can close
43 ('Base Frames and Dialogs', [
57 'wxFindReplaceDialog',
63 'wxSingleChoiceDialog',
67 # dialogs from libraries
71 'wxMultipleChoiceDialog',
72 'wxScrolledMessageDialog',
76 ('Core Windows/Controls', [
112 # controls coming from other libraries
113 ('More Windows/Controls', [
114 #'wxFloatBar', deprecated
115 #'wxMVCTree', deprecated
116 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
124 'MaskedEditControls',
133 'wxDynamicSashWindow',
140 'wxMimeTypesManager',
144 'wxStyledTextCtrl_1',
145 'wxStyledTextCtrl_2',
151 # How to lay out the controls in a frame/dialog
157 'wxLayoutConstraints',
160 'wxXmlResourceHandler',
164 ('Process and Events', [
176 ('Clipboard and DnD', [
209 # need libs not coming with the demo
210 ('Objects using an external library', [
211 'ActiveXWrapper_Acrobat',
218 ('Check out the samples dir too', [
225 #---------------------------------------------------------------------------
226 # Show how to derive a custom wxLog class
228 class MyLog(wx
.PyLog
):
229 def __init__(self
, textCtrl
, logTime
=0):
230 wx
.PyLog
.__init
__(self
)
232 self
.logTime
= logTime
234 def DoLogString(self
, message
, timeStamp
):
236 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
239 self
.tc
.AppendText(message
+ '\n')
242 class MyTP(wx
.PyTipProvider
):
244 return "This is my tip"
246 #---------------------------------------------------------------------------
247 # A class to be used to display source code in the demo. Try using the
248 # wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
249 # if there is an error, such as the stc module not being present.
255 from wxStyledTextCtrl_2
import PythonSTC
256 class DemoCodeViewer(PythonSTC
):
257 def __init__(self
, parent
, ID
):
258 PythonSTC
.__init
__(self
, parent
, ID
)
259 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
260 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
261 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
263 # Some methods to make it compatible with how the wxTextCtrl is used
264 def SetValue(self
, value
):
265 self
.SetReadOnly(False)
267 self
.SetReadOnly(True)
272 def SetInsertionPoint(self
, pos
):
273 self
.SetCurrentPos(pos
)
275 def ShowPosition(self
, pos
):
278 def GetLastPosition(self
):
279 return self
.GetLength()
281 def GetRange(self
, start
, end
):
282 return self
.GetTextRange(start
, end
)
284 def GetSelection(self
):
285 return self
.GetAnchor(), self
.GetCurrentPos()
287 def SetSelection(self
, start
, end
):
288 self
.SetSelectionStart(start
)
289 self
.SetSelectionEnd(end
)
293 class DemoCodeViewer(wx
.TextCtrl
):
294 def __init__(self
, parent
, ID
):
295 wx
.TextCtrl
.__init
__(self
, parent
, ID
, style
=
296 wx
.TE_MULTILINE | wx
.TE_READONLY |
297 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
300 #---------------------------------------------------------------------------
303 """Convert paths to the platform-specific separator"""
304 return apply(os
.path
.join
, tuple(path
.split('/')))
307 #---------------------------------------------------------------------------
309 class wxPythonDemo(wx
.Frame
):
310 overviewText
= "wxPython Overview"
312 def __init__(self
, parent
, id, title
):
313 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
314 style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
)
316 self
.cwd
= os
.getcwd()
317 self
.curOverview
= ""
320 icon
= images
.getMondrianIcon()
323 if wx
.Platform
== '__WXMSW__':
324 # setup a taskbar icon, and catch some events from it
325 self
.tbicon
= wx
.TaskBarIcon()
326 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
327 wx
.EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
328 wx
.EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
329 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
330 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
332 wx
.CallAfter(self
.ShowTip
)
335 wx
.EVT_IDLE(self
, self
.OnIdle
)
336 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
337 wx
.EVT_ICONIZE(self
, self
.OnIconfiy
)
338 wx
.EVT_MAXIMIZE(self
, self
.OnMaximize
)
341 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
343 splitter
= wx
.SplitterWindow(self
, -1)
344 splitter2
= wx
.SplitterWindow(splitter
, -1)
346 def EmptyHandler(evt
): pass
347 #wx.EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
348 #wx.EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
350 # Prevent TreeCtrl from displaying all items after destruction when True
354 self
.mainmenu
= wx
.MenuBar()
357 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
358 wx
.EVT_MENU(self
, exitID
, self
.OnFileExit
)
359 wx
.App_SetMacExitMenuItemId(exitID
)
360 self
.mainmenu
.Append(menu
, '&File')
364 for item
in _treeList
:
366 for childItem
in item
[1]:
368 submenu
.Append(mID
, childItem
)
369 wx
.EVT_MENU(self
, mID
, self
.OnDemoMenu
)
370 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
371 self
.mainmenu
.Append(menu
, '&Demo')
377 findnextID
= wx
.NewId()
379 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
380 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
381 menu
.AppendSeparator()
382 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
383 wx
.App_SetMacAboutMenuItemId(helpID
)
384 wx
.EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
385 wx
.EVT_MENU(self
, findID
, self
.OnHelpFind
)
386 wx
.EVT_MENU(self
, findnextID
, self
.OnFindNext
)
387 wx
.EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
388 wx
.EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
389 wx
.EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
390 self
.mainmenu
.Append(menu
, '&Help')
391 self
.SetMenuBar(self
.mainmenu
)
393 self
.finddata
= wx
.FindReplaceData()
396 # This is another way to set Accelerators, in addition to
397 # using the '\t<key>' syntax in the menu items.
398 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
399 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
400 (wx
.ACCEL_CTRL
, ord('F'), findID
),
401 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
403 self
.SetAcceleratorTable(aTable
)
409 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
410 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
413 root
= self
.tree
.AddRoot("wxPython Overview")
415 for item
in _treeList
:
416 child
= self
.tree
.AppendItem(root
, item
[0])
417 if not firstChild
: firstChild
= child
418 for childItem
in item
[1]:
419 theDemo
= self
.tree
.AppendItem(child
, childItem
)
420 self
.treeMap
[childItem
] = theDemo
422 self
.tree
.Expand(root
)
423 self
.tree
.Expand(firstChild
)
424 wx
.EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
425 wx
.EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
426 wx
.EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
427 wx
.EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
430 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
432 # Set up a wx.html.HtmlWindow on the Overview Notebook page
433 # we put it in a panel first because there seems to be a
434 # refresh bug of some sort (wxGTK) when it is directly in
437 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
438 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
440 else: # hopefully I can remove this hacky code soon, see SF bug #216861
441 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
442 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
443 self
.nb
.AddPage(panel
, self
.overviewText
)
445 def OnOvrSize(evt
, ovr
=self
.ovr
):
446 ovr
.SetSize(evt
.GetSize())
448 wx
.EVT_SIZE(panel
, OnOvrSize
)
449 wx
.EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
452 self
.SetOverview(self
.overviewText
, overview
)
455 # Set up a notebook page for viewing the source code of each sample
456 self
.txt
= DemoCodeViewer(self
.nb
, -1)
457 self
.nb
.AddPage(self
.txt
, "Demo Code")
458 self
.GetDemoFile('Main.py')
461 # Set up a log on the View Log Notebook page
462 self
.log
= wx
.TextCtrl(splitter2
, -1,
463 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
465 # Set the wxWindows log target to be this textctrl
466 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
468 # But instead of the above we want to show how to use our own wx.Log class
469 wx
.Log_SetActiveTarget(MyLog(self
.log
))
471 # for serious debugging
472 #wx.Log_SetActiveTarget(wx.LogStderr())
473 #wx.Log_SetTraceMask(wx.TraceMessages)
478 # add the windows to the splitter and split it.
479 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -120)
480 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
482 splitter
.SetMinimumPaneSize(20)
483 splitter2
.SetMinimumPaneSize(20)
486 # Make the splitter on the right expand the top wind when resized
487 def SplitterOnSize(evt
):
488 splitter
= evt
.GetEventObject()
489 sz
= splitter
.GetSize()
490 splitter
.SetSashPosition(sz
.height
- 120, False)
492 wx
.EVT_SIZE(splitter2
, SplitterOnSize
)
495 # select initial items
496 self
.nb
.SetSelection(0)
497 self
.tree
.SelectItem(root
)
499 if len(sys
.argv
) == 2:
501 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
505 self
.tree
.SelectItem(selectedDemo
)
506 self
.tree
.EnsureVisible(selectedDemo
)
509 wx
.LogMessage('window handle: %s' % self
.GetHandle())
512 #---------------------------------------------
513 def WriteText(self
, text
):
514 if text
[-1:] == '\n':
519 def write(self
, txt
):
522 #---------------------------------------------
523 def OnItemExpanded(self
, event
):
524 item
= event
.GetItem()
525 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
528 #---------------------------------------------
529 def OnItemCollapsed(self
, event
):
530 item
= event
.GetItem()
531 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
534 #---------------------------------------------
535 def OnTreeLeftDown(self
, event
):
536 pt
= event
.GetPosition();
537 item
, flags
= self
.tree
.HitTest(pt
)
538 if item
== self
.tree
.GetSelection():
539 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
542 #---------------------------------------------
543 def OnSelChanged(self
, event
):
547 item
= event
.GetItem()
548 itemText
= self
.tree
.GetItemText(item
)
549 self
.RunDemo(itemText
)
552 #---------------------------------------------
553 def RunDemo(self
, itemText
):
555 if self
.nb
.GetPageCount() == 3:
556 if self
.nb
.GetSelection() == 2:
557 self
.nb
.SetSelection(0)
558 # inform the window that it's time to quit if it cares
559 if self
.window
is not None:
560 if hasattr(self
.window
, "ShutdownDemo"):
561 self
.window
.ShutdownDemo()
562 wx
.SafeYield() # in case the page has pending events
563 self
.nb
.DeletePage(2)
565 if itemText
== self
.overviewText
:
566 self
.GetDemoFile('Main.py')
567 self
.SetOverview(self
.overviewText
, overview
)
572 if os
.path
.exists(itemText
+ '.py'):
574 wx
.LogMessage("Running demo %s.py..." % itemText
)
576 self
.GetDemoFile(itemText
+ '.py')
577 module
= __import__(itemText
, globals())
578 self
.SetOverview(itemText
+ " Overview", module
.overview
)
583 # in case runTest is modal, make sure things look right...
587 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
588 if self
.window
is not None:
589 self
.nb
.AddPage(self
.window
, 'Demo')
590 self
.nb
.SetSelection(2)
591 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
600 #---------------------------------------------
602 def GetDemoFile(self
, filename
):
605 self
.txt
.SetValue(open(filename
).read())
607 self
.txt
.SetValue("Cannot open %s file." % filename
)
609 self
.txt
.SetInsertionPoint(0)
610 self
.txt
.ShowPosition(0)
612 #---------------------------------------------
613 def SetOverview(self
, name
, text
):
614 self
.curOverview
= text
616 if lead
!= '<html>' and lead
!= '<HTML>':
617 text
= '<br>'.join(text
.split('\n'))
618 self
.ovr
.SetPage(text
)
619 self
.nb
.SetPageText(0, name
)
621 #---------------------------------------------
623 def OnFileExit(self
, *event
):
626 def OnHelpAbout(self
, event
):
627 from About
import MyAboutBox
628 about
= MyAboutBox(self
)
632 def OnHelpFind(self
, event
):
633 self
.nb
.SetSelection(1)
634 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
638 self
.finddlg
.Show(True)
640 def OnFind(self
, event
):
641 self
.nb
.SetSelection(1)
642 end
= self
.txt
.GetLastPosition()
643 textstring
= self
.txt
.GetRange(0, end
).lower()
644 start
= self
.txt
.GetSelection()[1]
645 findstring
= self
.finddata
.GetFindString().lower()
646 loc
= textstring
.find(findstring
, start
)
647 if loc
== -1 and start
!= 0:
648 # string not found, start at beginning
650 loc
= textstring
.find(findstring
, start
)
652 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
653 'Find String Not Found in Demo File',
654 wx
.OK | wx
.ICON_INFORMATION
)
659 self
.finddlg
.SetFocus()
662 self
.finddlg
.Destroy()
663 self
.txt
.ShowPosition(loc
)
664 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
668 def OnFindNext(self
, event
):
669 if self
.finddata
.GetFindString():
672 self
.OnHelpFind(event
)
674 def OnFindClose(self
, event
):
675 event
.GetDialog().Destroy()
678 #---------------------------------------------
679 def OnCloseWindow(self
, event
):
683 if hasattr(self
, "tbicon"):
688 #---------------------------------------------
689 def OnIdle(self
, event
):
691 self
.otherWin
.Raise()
692 self
.window
= self
.otherWin
696 #---------------------------------------------
699 showTipText
= open(opj("data/showTips")).read()
700 showTip
, index
= eval(showTipText
)
702 showTip
, index
= (1, 0)
704 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
706 showTip
= wx
.ShowTip(self
, tp
)
707 index
= tp
.GetCurrentTip()
708 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
711 #---------------------------------------------
712 def OnDemoMenu(self
, event
):
714 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
718 self
.tree
.SelectItem(selectedDemo
)
719 self
.tree
.EnsureVisible(selectedDemo
)
722 #---------------------------------------------
723 def OnTaskBarActivate(self
, evt
):
724 if self
.IsIconized():
726 if not self
.IsShown():
730 #---------------------------------------------
732 TBMENU_RESTORE
= 1000
735 def OnTaskBarMenu(self
, evt
):
737 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
738 menu
.Append(self
.TBMENU_CLOSE
, "Close")
739 self
.tbicon
.PopupMenu(menu
)
742 #---------------------------------------------
743 def OnTaskBarClose(self
, evt
):
746 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
747 # prod the main idle handler a bit to get the window to actually close
748 wx
.GetApp().ProcessIdle()
751 #---------------------------------------------
752 def OnIconfiy(self
, evt
):
753 wx
.LogMessage("OnIconfiy")
756 #---------------------------------------------
757 def OnMaximize(self
, evt
):
758 wx
.LogMessage("OnMaximize")
764 #---------------------------------------------------------------------------
765 #---------------------------------------------------------------------------
767 class MySplashScreen(wx
.SplashScreen
):
769 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
770 wx
.SplashScreen
.__init
__(self
, bmp
,
771 wx
.SPLASH_CENTRE_ON_SCREEN|wx
.SPLASH_TIMEOUT
,
773 style
= wx
.SIMPLE_BORDER|wx
.FRAME_NO_TASKBAR|wx
.STAY_ON_TOP
)
774 wx
.EVT_CLOSE(self
, self
.OnClose
)
776 def OnClose(self
, evt
):
777 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
779 evt
.Skip() # Make sure the default handler runs too...
785 Create and show the splash screen. It will then create and show
786 the main frame when it is time to do so.
790 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
791 #locale.setlocale(locale.LC_ALL, 'fr')
793 wx
.InitAllImageHandlers()
794 splash
= MySplashScreen()
800 #---------------------------------------------------------------------------
804 demoPath
= os
.path
.dirname(__file__
)
808 app
= MyApp(wx
.Platform
== "__WXMAC__")
812 #---------------------------------------------------------------------------
816 overview
= """<html><body>
819 <p> wxPython is a <b>GUI toolkit</b> for the <a
820 href="http://www.python.org/">Python</a> programming language. It
821 allows Python programmers to create programs with a robust, highly
822 functional graphical user interface, simply and easily. It is
823 implemented as a Python extension module (native code) that wraps the
824 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
825 platform GUI library, which is written in C++.
827 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
828 means that it is free for anyone to use and the source code is
829 available for anyone to look at and modify. Or anyone can contribute
830 fixes or enhancements to the project.
832 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
833 same program will run on multiple platforms without modification.
834 Currently supported platforms are 32-bit Microsoft Windows, most Unix
835 or unix-like systems, and Macintosh OS X. Since the language is
836 Python, wxPython programs are <b>simple, easy</b> to write and easy to
839 <p> <b>This demo</b> is not only a collection of test cases for
840 wxPython, but is also designed to help you learn about and how to use
841 wxPython. Each sample is listed in the tree control on the left.
842 When a sample is selected in the tree then a module is loaded and run
843 (usually in a tab of this notebook,) and the source code of the module
844 is loaded in another tab for you to browse and learn from.
849 #----------------------------------------------------------------------------
850 #----------------------------------------------------------------------------
852 if __name__
== '__main__':
855 #----------------------------------------------------------------------------