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', [
33 # managed windows == things with a (optional) caption you can close
34 ('Base Frames and Dialogs', [
48 'wxFindReplaceDialog',
54 'wxSingleChoiceDialog',
58 # dialogs from libraries
62 'wxMultipleChoiceDialog',
63 'wxScrolledMessageDialog',
67 ('Core Windows/Controls', [
103 # controls coming from other librairies
104 ('More Windows/Controls', [
105 #'wxFloatBar', deprecated
106 #'wxMVCTree', deprecated
107 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
114 'MaskedEditControls',
123 'wxDynamicSashWindow',
130 'wxMimeTypesManager',
133 'wxStyledTextCtrl_1',
134 'wxStyledTextCtrl_2',
140 # How to lay out the controls in a frame/dialog
146 'wxLayoutConstraints',
149 'wxXmlResourceHandler',
153 ('Process and Events', [
165 ('Clipboard and DnD', [
198 # need libs not coming with the demo
199 ('Objects using an external library', [
200 'ActiveXWrapper_Acrobat',
207 ('Check out the samples dir too', [
214 #---------------------------------------------------------------------------
216 class MyLog(wx
.PyLog
):
217 def __init__(self
, textCtrl
, logTime
=0):
218 wx
.PyLog
.__init
__(self
)
220 self
.logTime
= logTime
222 def DoLogString(self
, message
, timeStamp
):
224 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
227 self
.tc
.AppendText(message
+ '\n')
230 class MyTP(wx
.PyTipProvider
):
232 return "This is my tip"
234 #---------------------------------------------------------------------------
235 # A class to be used to display source code in the demo. Try using the
236 # wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
237 # if there is an error, such as the stc module not being present.
242 from wxStyledTextCtrl_2
import PythonSTC
243 class DemoCodeViewer(PythonSTC
):
244 def __init__(self
, parent
, ID
):
245 PythonSTC
.__init
__(self
, parent
, ID
)
246 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
247 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
248 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
250 # Some methods to make it compatible with how the wxTextCtrl is used
251 def SetValue(self
, value
):
252 self
.SetReadOnly(False)
254 self
.SetReadOnly(True)
259 def SetInsertionPoint(self
, pos
):
260 self
.SetCurrentPos(pos
)
262 def ShowPosition(self
, pos
):
265 def GetLastPosition(self
):
266 return self
.GetLength()
268 def GetRange(self
, start
, end
):
269 return self
.GetTextRange(start
, end
)
271 def GetSelection(self
):
272 return self
.GetAnchor(), self
.GetCurrentPos()
274 def SetSelection(self
, start
, end
):
275 self
.SetSelectionStart(start
)
276 self
.SetSelectionEnd(end
)
280 class DemoCodeViewer(wx
.TextCtrl
):
281 def __init__(self
, parent
, ID
):
282 wx
.TextCtrl
.__init
__(self
, parent
, ID
, style
=
283 wx
.TE_MULTILINE | wx
.TE_READONLY |
284 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
287 #---------------------------------------------------------------------------
290 """Convert paths to the platform-specific separator"""
291 return apply(os
.path
.join
, tuple(path
.split('/')))
294 #---------------------------------------------------------------------------
296 class wxPythonDemo(wx
.Frame
):
297 overviewText
= "wxPython Overview"
299 def __init__(self
, parent
, id, title
):
300 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
301 style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
)
303 self
.cwd
= os
.getcwd()
304 self
.curOverview
= ""
307 icon
= images
.getMondrianIcon()
310 if wx
.Platform
== '__WXMSW__':
311 # setup a taskbar icon, and catch some events from it
312 self
.tbicon
= wx
.TaskBarIcon()
313 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
314 wx
.EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
315 wx
.EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
316 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
317 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
319 wx
.CallAfter(self
.ShowTip
)
322 wx
.EVT_IDLE(self
, self
.OnIdle
)
323 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
324 wx
.EVT_ICONIZE(self
, self
.OnIconfiy
)
325 wx
.EVT_MAXIMIZE(self
, self
.OnMaximize
)
328 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
330 splitter
= wx
.SplitterWindow(self
, -1)
331 splitter2
= wx
.SplitterWindow(splitter
, -1)
333 def EmptyHandler(evt
): pass
334 #wx.EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
335 #wx.EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
337 # Prevent TreeCtrl from displaying all items after destruction when True
341 self
.mainmenu
= wx
.MenuBar()
344 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
345 wx
.EVT_MENU(self
, exitID
, self
.OnFileExit
)
346 wx
.App_SetMacExitMenuItemId(exitID
)
347 self
.mainmenu
.Append(menu
, '&File')
351 for item
in _treeList
:
353 for childItem
in item
[1]:
355 submenu
.Append(mID
, childItem
)
356 wx
.EVT_MENU(self
, mID
, self
.OnDemoMenu
)
357 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
358 self
.mainmenu
.Append(menu
, '&Demo')
364 findnextID
= wx
.NewId()
366 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
367 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
368 menu
.AppendSeparator()
369 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
370 wx
.App_SetMacAboutMenuItemId(helpID
)
371 wx
.EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
372 wx
.EVT_MENU(self
, findID
, self
.OnHelpFind
)
373 wx
.EVT_MENU(self
, findnextID
, self
.OnFindNext
)
374 wx
.EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
375 wx
.EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
376 wx
.EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
377 self
.mainmenu
.Append(menu
, '&Help')
378 self
.SetMenuBar(self
.mainmenu
)
380 self
.finddata
= wx
.FindReplaceData()
383 # This is another way to set Accelerators, in addition to
384 # using the '\t<key>' syntax in the menu items.
385 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
386 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
387 (wx
.ACCEL_CTRL
, ord('F'), findID
),
388 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
390 self
.SetAcceleratorTable(aTable
)
396 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
397 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
400 root
= self
.tree
.AddRoot("wxPython Overview")
402 for item
in _treeList
:
403 child
= self
.tree
.AppendItem(root
, item
[0])
404 if not firstChild
: firstChild
= child
405 for childItem
in item
[1]:
406 theDemo
= self
.tree
.AppendItem(child
, childItem
)
407 self
.treeMap
[childItem
] = theDemo
409 self
.tree
.Expand(root
)
410 self
.tree
.Expand(firstChild
)
411 wx
.EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
412 wx
.EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
413 wx
.EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
414 wx
.EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
417 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
419 # Set up a wx.html.HtmlWindow on the Overview Notebook page
420 # we put it in a panel first because there seems to be a
421 # refresh bug of some sort (wxGTK) when it is directly in
424 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
425 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
427 else: # hopefully I can remove this hacky code soon, see SF bug #216861
428 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
429 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
430 self
.nb
.AddPage(panel
, self
.overviewText
)
432 def OnOvrSize(evt
, ovr
=self
.ovr
):
433 ovr
.SetSize(evt
.GetSize())
435 wx
.EVT_SIZE(panel
, OnOvrSize
)
436 wx
.EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
439 self
.SetOverview(self
.overviewText
, overview
)
442 # Set up a notebook page for viewing the source code of each sample
443 self
.txt
= DemoCodeViewer(self
.nb
, -1)
444 self
.nb
.AddPage(self
.txt
, "Demo Code")
445 self
.GetDemoFile('Main.py')
448 # Set up a log on the View Log Notebook page
449 self
.log
= wx
.TextCtrl(splitter2
, -1,
450 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
452 # Set the wxWindows log target to be this textctrl
453 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
455 # But instead of the above we want to show how to use our own wx.Log class
456 wx
.Log_SetActiveTarget(MyLog(self
.log
))
458 # for serious debugging
459 #wx.Log_SetActiveTarget(wx.LogStderr())
460 #wx.Log_SetTraceMask(wx.TraceMessages)
465 # add the windows to the splitter and split it.
466 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -120)
467 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
469 splitter
.SetMinimumPaneSize(20)
470 splitter2
.SetMinimumPaneSize(20)
473 # Make the splitter on the right expand the top wind when resized
474 def SplitterOnSize(evt
):
475 splitter
= evt
.GetEventObject()
476 sz
= splitter
.GetSize()
477 splitter
.SetSashPosition(sz
.height
- 120, False)
479 wx
.EVT_SIZE(splitter2
, SplitterOnSize
)
482 # select initial items
483 self
.nb
.SetSelection(0)
484 self
.tree
.SelectItem(root
)
486 if len(sys
.argv
) == 2:
488 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
492 self
.tree
.SelectItem(selectedDemo
)
493 self
.tree
.EnsureVisible(selectedDemo
)
496 wx
.LogMessage('window handle: %s' % self
.GetHandle())
499 #---------------------------------------------
500 def WriteText(self
, text
):
501 if text
[-1:] == '\n':
506 def write(self
, txt
):
509 #---------------------------------------------
510 def OnItemExpanded(self
, event
):
511 item
= event
.GetItem()
512 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
515 #---------------------------------------------
516 def OnItemCollapsed(self
, event
):
517 item
= event
.GetItem()
518 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
521 #---------------------------------------------
522 def OnTreeLeftDown(self
, event
):
523 pt
= event
.GetPosition();
524 item
, flags
= self
.tree
.HitTest(pt
)
525 if item
== self
.tree
.GetSelection():
526 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
529 #---------------------------------------------
530 def OnSelChanged(self
, event
):
534 item
= event
.GetItem()
535 itemText
= self
.tree
.GetItemText(item
)
536 self
.RunDemo(itemText
)
539 #---------------------------------------------
540 def RunDemo(self
, itemText
):
542 if self
.nb
.GetPageCount() == 3:
543 if self
.nb
.GetSelection() == 2:
544 self
.nb
.SetSelection(0)
545 # inform the window that it's time to quit if it cares
546 if self
.window
is not None:
547 if hasattr(self
.window
, "ShutdownDemo"):
548 self
.window
.ShutdownDemo()
549 wx
.SafeYield() # in case the page has pending events
550 self
.nb
.DeletePage(2)
552 if itemText
== self
.overviewText
:
553 self
.GetDemoFile('Main.py')
554 self
.SetOverview(self
.overviewText
, overview
)
559 if os
.path
.exists(itemText
+ '.py'):
561 wx
.LogMessage("Running demo %s.py..." % itemText
)
563 self
.GetDemoFile(itemText
+ '.py')
564 module
= __import__(itemText
, globals())
565 self
.SetOverview(itemText
+ " Overview", module
.overview
)
570 # in case runTest is modal, make sure things look right...
574 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
575 if self
.window
is not None:
576 self
.nb
.AddPage(self
.window
, 'Demo')
577 self
.nb
.SetSelection(2)
578 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
587 #---------------------------------------------
589 def GetDemoFile(self
, filename
):
592 self
.txt
.SetValue(open(filename
).read())
594 self
.txt
.SetValue("Cannot open %s file." % filename
)
596 self
.txt
.SetInsertionPoint(0)
597 self
.txt
.ShowPosition(0)
599 #---------------------------------------------
600 def SetOverview(self
, name
, text
):
601 self
.curOverview
= text
603 if lead
!= '<html>' and lead
!= '<HTML>':
604 text
= '<br>'.join(text
.split('\n'))
605 self
.ovr
.SetPage(text
)
606 self
.nb
.SetPageText(0, name
)
608 #---------------------------------------------
610 def OnFileExit(self
, *event
):
613 def OnHelpAbout(self
, event
):
614 from About
import MyAboutBox
615 about
= MyAboutBox(self
)
619 def OnHelpFind(self
, event
):
620 self
.nb
.SetSelection(1)
621 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
625 self
.finddlg
.Show(True)
627 def OnFind(self
, event
):
628 self
.nb
.SetSelection(1)
629 end
= self
.txt
.GetLastPosition()
630 textstring
= self
.txt
.GetRange(0, end
).lower()
631 start
= self
.txt
.GetSelection()[1]
632 findstring
= self
.finddata
.GetFindString().lower()
633 loc
= textstring
.find(findstring
, start
)
634 if loc
== -1 and start
!= 0:
635 # string not found, start at beginning
637 loc
= textstring
.find(findstring
, start
)
639 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
640 'Find String Not Found in Demo File',
641 wx
.OK | wx
.ICON_INFORMATION
)
646 self
.finddlg
.SetFocus()
649 self
.finddlg
.Destroy()
650 self
.txt
.ShowPosition(loc
)
651 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
655 def OnFindNext(self
, event
):
656 if self
.finddata
.GetFindString():
659 self
.OnHelpFind(event
)
661 def OnFindClose(self
, event
):
662 event
.GetDialog().Destroy()
665 #---------------------------------------------
666 def OnCloseWindow(self
, event
):
670 if hasattr(self
, "tbicon"):
675 #---------------------------------------------
676 def OnIdle(self
, event
):
678 self
.otherWin
.Raise()
679 self
.window
= self
.otherWin
683 #---------------------------------------------
686 showTipText
= open(opj("data/showTips")).read()
687 showTip
, index
= eval(showTipText
)
689 showTip
, index
= (1, 0)
691 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
693 showTip
= wx
.ShowTip(self
, tp
)
694 index
= tp
.GetCurrentTip()
695 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
698 #---------------------------------------------
699 def OnDemoMenu(self
, event
):
701 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
705 self
.tree
.SelectItem(selectedDemo
)
706 self
.tree
.EnsureVisible(selectedDemo
)
709 #---------------------------------------------
710 def OnTaskBarActivate(self
, evt
):
711 if self
.IsIconized():
713 if not self
.IsShown():
717 #---------------------------------------------
719 TBMENU_RESTORE
= 1000
722 def OnTaskBarMenu(self
, evt
):
724 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
725 menu
.Append(self
.TBMENU_CLOSE
, "Close")
726 self
.tbicon
.PopupMenu(menu
)
729 #---------------------------------------------
730 def OnTaskBarClose(self
, evt
):
733 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
734 # prod the main idle handler a bit to get the window to actually close
735 wx
.GetApp().ProcessIdle()
738 #---------------------------------------------
739 def OnIconfiy(self
, evt
):
740 wx
.LogMessage("OnIconfiy")
743 #---------------------------------------------
744 def OnMaximize(self
, evt
):
745 wx
.LogMessage("OnMaximize")
751 #---------------------------------------------------------------------------
752 #---------------------------------------------------------------------------
754 class MySplashScreen(wx
.SplashScreen
):
756 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
757 wx
.SplashScreen
.__init
__(self
, bmp
,
758 wx
.SPLASH_CENTRE_ON_SCREEN|wx
.SPLASH_TIMEOUT
,
760 style
= wx
.SIMPLE_BORDER|wx
.FRAME_NO_TASKBAR|wx
.STAY_ON_TOP
)
761 wx
.EVT_CLOSE(self
, self
.OnClose
)
763 def OnClose(self
, evt
):
764 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
766 evt
.Skip() # Make sure the default handler runs too...
772 Create and show the splash screen. It will then create and show
773 the main frame when it is time to do so.
777 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
778 #locale.setlocale(locale.LC_ALL, 'fr')
780 wx
.InitAllImageHandlers()
781 splash
= MySplashScreen()
787 #---------------------------------------------------------------------------
791 demoPath
= os
.path
.dirname(__file__
)
795 app
= MyApp(wx
.Platform
== "__WXMAC__")
799 #---------------------------------------------------------------------------
803 overview
= """<html><body>
806 <p> wxPython is a <b>GUI toolkit</b> for the <a
807 href="http://www.python.org/">Python</a> programming language. It
808 allows Python programmers to create programs with a robust, highly
809 functional graphical user interface, simply and easily. It is
810 implemented as a Python extension module (native code) that wraps the
811 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
812 platform GUI library, which is written in C++.
814 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
815 means that it is free for anyone to use and the source code is
816 available for anyone to look at and modify. Or anyone can contribute
817 fixes or enhnacments to the project.
819 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
820 same program will run on multiple platforms without modification.
821 Currently supported platforms are 32-bit Microsoft Windows, most Unix
822 or unix-like systems, and Macintosh OS X. Since the language is
823 Python, wxPython programs are <b>simple, easy</b> to write and easy to
826 <p> <b>This demo</b> is not only a collection of test cases for
827 wxPython, but is also designed to help you learn about and how to use
828 wxPython. Each sample is listed in the tree control on the left.
829 When a sample is selected in the tree then a module is loaded and run
830 (usually in a tab of this notebook,) and the source code of the module
831 is loaded in another tab for you to browse and learn from.
836 #----------------------------------------------------------------------------
837 #----------------------------------------------------------------------------
839 if __name__
== '__main__':
842 #----------------------------------------------------------------------------