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',
147 'wxStyledTextCtrl_1',
148 'wxStyledTextCtrl_2',
153 # How to lay out the controls in a frame/dialog
160 'wxLayoutConstraints',
163 'wxXmlResourceHandler',
164 'wxXmlResourceSubclass',
168 ('Process and Events', [
180 ('Clipboard and DnD', [
213 # need libs not coming with the demo
214 ('Objects using an external library', [
215 'ActiveXWrapper_Acrobat',
222 ('Check out the samples dir too', [
229 #---------------------------------------------------------------------------
230 # Show how to derive a custom wxLog class
232 class MyLog(wx
.PyLog
):
233 def __init__(self
, textCtrl
, logTime
=0):
234 wx
.PyLog
.__init
__(self
)
236 self
.logTime
= logTime
238 def DoLogString(self
, message
, timeStamp
):
240 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
243 self
.tc
.AppendText(message
+ '\n')
246 class MyTP(wx
.PyTipProvider
):
248 return "This is my tip"
250 #---------------------------------------------------------------------------
251 # A class to be used to display source code in the demo. Try using the
252 # wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
253 # if there is an error, such as the stc module not being present.
259 from wxStyledTextCtrl_2
import PythonSTC
260 class DemoCodeViewer(PythonSTC
):
261 def __init__(self
, parent
, ID
):
262 PythonSTC
.__init
__(self
, parent
, ID
)
263 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
264 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
265 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
267 # Some methods to make it compatible with how the wxTextCtrl is used
268 def SetValue(self
, value
):
269 self
.SetReadOnly(False)
271 self
.SetReadOnly(True)
276 def SetInsertionPoint(self
, pos
):
277 self
.SetCurrentPos(pos
)
279 def ShowPosition(self
, pos
):
282 def GetLastPosition(self
):
283 return self
.GetLength()
285 def GetRange(self
, start
, end
):
286 return self
.GetTextRange(start
, end
)
288 def GetSelection(self
):
289 return self
.GetAnchor(), self
.GetCurrentPos()
291 def SetSelection(self
, start
, end
):
292 self
.SetSelectionStart(start
)
293 self
.SetSelectionEnd(end
)
297 class DemoCodeViewer(wx
.TextCtrl
):
298 def __init__(self
, parent
, ID
):
299 wx
.TextCtrl
.__init
__(self
, parent
, ID
, style
=
300 wx
.TE_MULTILINE | wx
.TE_READONLY |
301 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
304 #---------------------------------------------------------------------------
307 """Convert paths to the platform-specific separator"""
308 return apply(os
.path
.join
, tuple(path
.split('/')))
311 #---------------------------------------------------------------------------
313 class wxPythonDemo(wx
.Frame
):
314 overviewText
= "wxPython Overview"
316 def __init__(self
, parent
, id, title
):
317 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
318 style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
)
320 self
.cwd
= os
.getcwd()
321 self
.curOverview
= ""
324 icon
= images
.getMondrianIcon()
327 if wx
.Platform
== '__WXMSW__':
328 # setup a taskbar icon, and catch some events from it
329 self
.tbicon
= wx
.TaskBarIcon()
330 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
331 wx
.EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
332 wx
.EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
333 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
334 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
336 wx
.CallAfter(self
.ShowTip
)
339 wx
.EVT_IDLE(self
, self
.OnIdle
)
340 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
341 wx
.EVT_ICONIZE(self
, self
.OnIconfiy
)
342 wx
.EVT_MAXIMIZE(self
, self
.OnMaximize
)
345 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
347 splitter
= wx
.SplitterWindow(self
, -1)
348 splitter2
= wx
.SplitterWindow(splitter
, -1)
350 def EmptyHandler(evt
): pass
351 #wx.EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
352 #wx.EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
354 # Prevent TreeCtrl from displaying all items after destruction when True
358 self
.mainmenu
= wx
.MenuBar()
361 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
362 wx
.EVT_MENU(self
, exitID
, self
.OnFileExit
)
363 wx
.App_SetMacExitMenuItemId(exitID
)
364 self
.mainmenu
.Append(menu
, '&File')
368 for item
in _treeList
:
370 for childItem
in item
[1]:
372 submenu
.Append(mID
, childItem
)
373 wx
.EVT_MENU(self
, mID
, self
.OnDemoMenu
)
374 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
375 self
.mainmenu
.Append(menu
, '&Demo')
381 findnextID
= wx
.NewId()
383 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
384 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
385 menu
.AppendSeparator()
386 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
387 wx
.App_SetMacAboutMenuItemId(helpID
)
388 wx
.EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
389 wx
.EVT_MENU(self
, findID
, self
.OnHelpFind
)
390 wx
.EVT_MENU(self
, findnextID
, self
.OnFindNext
)
391 wx
.EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
392 wx
.EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
393 wx
.EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
394 self
.mainmenu
.Append(menu
, '&Help')
395 self
.SetMenuBar(self
.mainmenu
)
397 self
.finddata
= wx
.FindReplaceData()
400 # This is another way to set Accelerators, in addition to
401 # using the '\t<key>' syntax in the menu items.
402 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
403 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
404 (wx
.ACCEL_CTRL
, ord('F'), findID
),
405 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
407 self
.SetAcceleratorTable(aTable
)
413 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
414 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
417 root
= self
.tree
.AddRoot("wxPython Overview")
419 for item
in _treeList
:
420 child
= self
.tree
.AppendItem(root
, item
[0])
421 if not firstChild
: firstChild
= child
422 for childItem
in item
[1]:
423 theDemo
= self
.tree
.AppendItem(child
, childItem
)
424 self
.treeMap
[childItem
] = theDemo
426 self
.tree
.Expand(root
)
427 self
.tree
.Expand(firstChild
)
428 wx
.EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
429 wx
.EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
430 wx
.EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
431 wx
.EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
434 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
436 # Set up a wx.html.HtmlWindow on the Overview Notebook page
437 # we put it in a panel first because there seems to be a
438 # refresh bug of some sort (wxGTK) when it is directly in
441 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
442 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
444 else: # hopefully I can remove this hacky code soon, see SF bug #216861
445 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
446 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
447 self
.nb
.AddPage(panel
, self
.overviewText
)
449 def OnOvrSize(evt
, ovr
=self
.ovr
):
450 ovr
.SetSize(evt
.GetSize())
452 wx
.EVT_SIZE(panel
, OnOvrSize
)
453 wx
.EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
456 self
.SetOverview(self
.overviewText
, overview
)
459 # Set up a notebook page for viewing the source code of each sample
460 self
.txt
= DemoCodeViewer(self
.nb
, -1)
461 self
.nb
.AddPage(self
.txt
, "Demo Code")
462 self
.GetDemoFile('Main.py')
465 # Set up a log on the View Log Notebook page
466 self
.log
= wx
.TextCtrl(splitter2
, -1,
467 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
469 # Set the wxWindows log target to be this textctrl
470 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
472 # But instead of the above we want to show how to use our own wx.Log class
473 wx
.Log_SetActiveTarget(MyLog(self
.log
))
475 # for serious debugging
476 #wx.Log_SetActiveTarget(wx.LogStderr())
477 #wx.Log_SetTraceMask(wx.TraceMessages)
482 # add the windows to the splitter and split it.
483 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -120)
484 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
486 splitter
.SetMinimumPaneSize(20)
487 splitter2
.SetMinimumPaneSize(20)
490 # Make the splitter on the right expand the top wind when resized
491 def SplitterOnSize(evt
):
492 splitter
= evt
.GetEventObject()
493 sz
= splitter
.GetSize()
494 splitter
.SetSashPosition(sz
.height
- 120, False)
496 wx
.EVT_SIZE(splitter2
, SplitterOnSize
)
499 # select initial items
500 self
.nb
.SetSelection(0)
501 self
.tree
.SelectItem(root
)
503 if len(sys
.argv
) == 2:
505 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
509 self
.tree
.SelectItem(selectedDemo
)
510 self
.tree
.EnsureVisible(selectedDemo
)
513 wx
.LogMessage('window handle: %s' % self
.GetHandle())
516 #---------------------------------------------
517 def WriteText(self
, text
):
518 if text
[-1:] == '\n':
523 def write(self
, txt
):
526 #---------------------------------------------
527 def OnItemExpanded(self
, event
):
528 item
= event
.GetItem()
529 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
532 #---------------------------------------------
533 def OnItemCollapsed(self
, event
):
534 item
= event
.GetItem()
535 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
538 #---------------------------------------------
539 def OnTreeLeftDown(self
, event
):
540 pt
= event
.GetPosition();
541 item
, flags
= self
.tree
.HitTest(pt
)
542 if item
== self
.tree
.GetSelection():
543 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
546 #---------------------------------------------
547 def OnSelChanged(self
, event
):
551 item
= event
.GetItem()
552 itemText
= self
.tree
.GetItemText(item
)
553 self
.RunDemo(itemText
)
556 #---------------------------------------------
557 def RunDemo(self
, itemText
):
559 if self
.nb
.GetPageCount() == 3:
560 if self
.nb
.GetSelection() == 2:
561 self
.nb
.SetSelection(0)
562 # inform the window that it's time to quit if it cares
563 if self
.window
is not None:
564 if hasattr(self
.window
, "ShutdownDemo"):
565 self
.window
.ShutdownDemo()
566 wx
.SafeYield() # in case the page has pending events
567 self
.nb
.DeletePage(2)
569 if itemText
== self
.overviewText
:
570 self
.GetDemoFile('Main.py')
571 self
.SetOverview(self
.overviewText
, overview
)
576 if os
.path
.exists(itemText
+ '.py'):
578 wx
.LogMessage("Running demo %s.py..." % itemText
)
580 self
.GetDemoFile(itemText
+ '.py')
581 module
= __import__(itemText
, globals())
582 self
.SetOverview(itemText
+ " Overview", module
.overview
)
587 # in case runTest is modal, make sure things look right...
591 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
592 if self
.window
is not None:
593 self
.nb
.AddPage(self
.window
, 'Demo')
594 self
.nb
.SetSelection(2)
595 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
604 #---------------------------------------------
606 def GetDemoFile(self
, filename
):
609 self
.txt
.SetValue(open(filename
).read())
611 self
.txt
.SetValue("Cannot open %s file." % filename
)
613 self
.txt
.SetInsertionPoint(0)
614 self
.txt
.ShowPosition(0)
616 #---------------------------------------------
617 def SetOverview(self
, name
, text
):
618 self
.curOverview
= text
620 if lead
!= '<html>' and lead
!= '<HTML>':
621 text
= '<br>'.join(text
.split('\n'))
622 self
.ovr
.SetPage(text
)
623 self
.nb
.SetPageText(0, name
)
625 #---------------------------------------------
627 def OnFileExit(self
, *event
):
630 def OnHelpAbout(self
, event
):
631 from About
import MyAboutBox
632 about
= MyAboutBox(self
)
636 def OnHelpFind(self
, event
):
637 self
.nb
.SetSelection(1)
638 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
642 self
.finddlg
.Show(True)
644 def OnFind(self
, event
):
645 self
.nb
.SetSelection(1)
646 end
= self
.txt
.GetLastPosition()
647 textstring
= self
.txt
.GetRange(0, end
).lower()
648 start
= self
.txt
.GetSelection()[1]
649 findstring
= self
.finddata
.GetFindString().lower()
650 loc
= textstring
.find(findstring
, start
)
651 if loc
== -1 and start
!= 0:
652 # string not found, start at beginning
654 loc
= textstring
.find(findstring
, start
)
656 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
657 'Find String Not Found in Demo File',
658 wx
.OK | wx
.ICON_INFORMATION
)
663 self
.finddlg
.SetFocus()
666 self
.finddlg
.Destroy()
667 self
.txt
.ShowPosition(loc
)
668 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
672 def OnFindNext(self
, event
):
673 if self
.finddata
.GetFindString():
676 self
.OnHelpFind(event
)
678 def OnFindClose(self
, event
):
679 event
.GetDialog().Destroy()
682 #---------------------------------------------
683 def OnCloseWindow(self
, event
):
687 if hasattr(self
, "tbicon"):
692 #---------------------------------------------
693 def OnIdle(self
, event
):
695 self
.otherWin
.Raise()
696 self
.window
= self
.otherWin
700 #---------------------------------------------
703 showTipText
= open(opj("data/showTips")).read()
704 showTip
, index
= eval(showTipText
)
706 showTip
, index
= (1, 0)
708 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
710 showTip
= wx
.ShowTip(self
, tp
)
711 index
= tp
.GetCurrentTip()
712 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
715 #---------------------------------------------
716 def OnDemoMenu(self
, event
):
718 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
722 self
.tree
.SelectItem(selectedDemo
)
723 self
.tree
.EnsureVisible(selectedDemo
)
726 #---------------------------------------------
727 def OnTaskBarActivate(self
, evt
):
728 if self
.IsIconized():
730 if not self
.IsShown():
734 #---------------------------------------------
736 TBMENU_RESTORE
= 1000
739 def OnTaskBarMenu(self
, evt
):
741 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
742 menu
.Append(self
.TBMENU_CLOSE
, "Close")
743 self
.tbicon
.PopupMenu(menu
)
746 #---------------------------------------------
747 def OnTaskBarClose(self
, evt
):
750 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
751 # prod the main idle handler a bit to get the window to actually close
752 wx
.GetApp().ProcessIdle()
755 #---------------------------------------------
756 def OnIconfiy(self
, evt
):
757 wx
.LogMessage("OnIconfiy")
760 #---------------------------------------------
761 def OnMaximize(self
, evt
):
762 wx
.LogMessage("OnMaximize")
768 #---------------------------------------------------------------------------
769 #---------------------------------------------------------------------------
771 class MySplashScreen(wx
.SplashScreen
):
773 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
774 wx
.SplashScreen
.__init
__(self
, bmp
,
775 wx
.SPLASH_CENTRE_ON_SCREEN|wx
.SPLASH_TIMEOUT
,
777 style
= wx
.SIMPLE_BORDER|wx
.FRAME_NO_TASKBAR|wx
.STAY_ON_TOP
)
778 wx
.EVT_CLOSE(self
, self
.OnClose
)
780 def OnClose(self
, evt
):
781 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
783 evt
.Skip() # Make sure the default handler runs too...
789 Create and show the splash screen. It will then create and show
790 the main frame when it is time to do so.
794 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
795 #locale.setlocale(locale.LC_ALL, 'fr')
797 wx
.InitAllImageHandlers()
798 splash
= MySplashScreen()
804 #---------------------------------------------------------------------------
808 demoPath
= os
.path
.dirname(__file__
)
812 app
= MyApp(0) #wx.Platform == "__WXMAC__")
816 #---------------------------------------------------------------------------
820 overview
= """<html><body>
823 <p> wxPython is a <b>GUI toolkit</b> for the <a
824 href="http://www.python.org/">Python</a> programming language. It
825 allows Python programmers to create programs with a robust, highly
826 functional graphical user interface, simply and easily. It is
827 implemented as a Python extension module (native code) that wraps the
828 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
829 platform GUI library, which is written in C++.
831 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
832 means that it is free for anyone to use and the source code is
833 available for anyone to look at and modify. Or anyone can contribute
834 fixes or enhancements to the project.
836 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
837 same program will run on multiple platforms without modification.
838 Currently supported platforms are 32-bit Microsoft Windows, most Unix
839 or unix-like systems, and Macintosh OS X. Since the language is
840 Python, wxPython programs are <b>simple, easy</b> to write and easy to
843 <p> <b>This demo</b> is not only a collection of test cases for
844 wxPython, but is also designed to help you learn about and how to use
845 wxPython. Each sample is listed in the tree control on the left.
846 When a sample is selected in the tree then a module is loaded and run
847 (usually in a tab of this notebook,) and the source code of the module
848 is loaded in another tab for you to browse and learn from.
853 #----------------------------------------------------------------------------
854 #----------------------------------------------------------------------------
856 if __name__
== '__main__':
859 #----------------------------------------------------------------------------