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
22 #---------------------------------------------------------------------------
27 ('Recent Additions', [
38 # managed windows == things with a (optional) caption you can close
39 ('Base Frames and Dialogs', [
53 'wxFindReplaceDialog',
59 'wxSingleChoiceDialog',
63 # dialogs from libraries
67 'wxMultipleChoiceDialog',
68 'wxScrolledMessageDialog',
72 ('Core Windows/Controls', [
107 # controls coming from other librairies
108 ('More Windows/Controls', [
109 #'wxFloatBar', deprecated
110 #'wxMVCTree', deprecated
111 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
118 'MaskedEditControls',
127 'wxDynamicSashWindow',
134 'wxMimeTypesManager',
137 'wxStyledTextCtrl_1',
138 'wxStyledTextCtrl_2',
143 # How to lay out the controls in a frame/dialog
149 'wxLayoutConstraints',
152 'wxXmlResourceHandler',
156 ('Process and Events', [
168 ('Clipboard and DnD', [
199 # need libs not coming with the demo
200 ('Objects using an external library', [
201 'ActiveXWrapper_Acrobat',
208 ('Check out the samples dir too', [
215 #---------------------------------------------------------------------------
217 class MyLog(wx
.PyLog
):
218 def __init__(self
, textCtrl
, logTime
=0):
219 wx
.PyLog
.__init
__(self
)
221 self
.logTime
= logTime
223 def DoLogString(self
, message
, timeStamp
):
225 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
228 self
.tc
.AppendText(message
+ '\n')
231 class MyTP(wx
.PyTipProvider
):
233 return "This is my tip"
235 #---------------------------------------------------------------------------
236 # A class to be used to display source code in the demo. Try using the
237 # wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
238 # if there is an error, such as the stc module not being present.
243 from wxStyledTextCtrl_2
import PythonSTC
244 class DemoCodeViewer(PythonSTC
):
245 def __init__(self
, parent
, ID
):
246 PythonSTC
.__init
__(self
, parent
, ID
)
247 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
248 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
249 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
251 # Some methods to make it compatible with how the wxTextCtrl is used
252 def SetValue(self
, value
):
253 self
.SetReadOnly(False)
255 self
.SetReadOnly(True)
260 def SetInsertionPoint(self
, pos
):
261 self
.SetCurrentPos(pos
)
263 def ShowPosition(self
, pos
):
266 def GetLastPosition(self
):
267 return self
.GetLength()
269 def GetRange(self
, start
, end
):
270 return self
.GetTextRange(start
, end
)
272 def GetSelection(self
):
273 return self
.GetAnchor(), self
.GetCurrentPos()
275 def SetSelection(self
, start
, end
):
276 self
.SetSelectionStart(start
)
277 self
.SetSelectionEnd(end
)
281 class DemoCodeViewer(wx
.TextCtrl
):
282 def __init__(self
, parent
, ID
):
283 wx
.TextCtrl
.__init
__(self
, parent
, ID
, style
=
284 wx
.TE_MULTILINE | wx
.TE_READONLY |
285 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
288 #---------------------------------------------------------------------------
291 """Convert paths to the platform-specific separator"""
292 return apply(os
.path
.join
, tuple(path
.split('/')))
295 #---------------------------------------------------------------------------
297 class wxPythonDemo(wx
.Frame
):
298 overviewText
= "wxPython Overview"
300 def __init__(self
, parent
, id, title
):
301 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
302 style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
)
304 self
.cwd
= os
.getcwd()
305 self
.curOverview
= ""
308 icon
= images
.getMondrianIcon()
311 if wx
.Platform
== '__WXMSW__':
312 # setup a taskbar icon, and catch some events from it
313 self
.tbicon
= wx
.TaskBarIcon()
314 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
315 wx
.EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
316 wx
.EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
317 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
318 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
320 wx
.CallAfter(self
.ShowTip
)
323 wx
.EVT_IDLE(self
, self
.OnIdle
)
324 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
325 wx
.EVT_ICONIZE(self
, self
.OnIconfiy
)
326 wx
.EVT_MAXIMIZE(self
, self
.OnMaximize
)
329 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
331 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.NO_3D|wx
.SP_3D
)
332 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.NO_3D|wx
.SP_3D
)
334 def EmptyHandler(evt
): pass
335 wx
.EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
336 wx
.EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
338 # Prevent TreeCtrl from displaying all items after destruction when True
342 self
.mainmenu
= wx
.MenuBar()
345 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
346 wx
.EVT_MENU(self
, exitID
, self
.OnFileExit
)
347 wx
.App_SetMacExitMenuItemId(exitID
)
348 self
.mainmenu
.Append(menu
, '&File')
352 for item
in _treeList
:
354 for childItem
in item
[1]:
356 submenu
.Append(mID
, childItem
)
357 wx
.EVT_MENU(self
, mID
, self
.OnDemoMenu
)
358 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
359 self
.mainmenu
.Append(menu
, '&Demo')
365 findnextID
= wx
.NewId()
367 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
368 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
369 menu
.AppendSeparator()
370 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
371 wx
.App_SetMacAboutMenuItemId(helpID
)
372 wx
.EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
373 wx
.EVT_MENU(self
, findID
, self
.OnHelpFind
)
374 wx
.EVT_MENU(self
, findnextID
, self
.OnFindNext
)
375 wx
.EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
376 wx
.EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
377 wx
.EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
378 self
.mainmenu
.Append(menu
, '&Help')
379 self
.SetMenuBar(self
.mainmenu
)
381 self
.finddata
= wx
.FindReplaceData()
384 # This is another way to set Accelerators, in addition to
385 # using the '\t<key>' syntax in the menu items.
386 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
387 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
388 (wx
.ACCEL_CTRL
, ord('F'), findID
),
389 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
391 self
.SetAcceleratorTable(aTable
)
397 self
.tree
= wx
.TreeCtrl(splitter
, tID
,
398 style
=wx
.TR_HAS_BUTTONS |
399 wx
.TR_HAS_VARIABLE_ROW_HEIGHT
402 root
= self
.tree
.AddRoot("wxPython Overview")
404 for item
in _treeList
:
405 child
= self
.tree
.AppendItem(root
, item
[0])
406 if not firstChild
: firstChild
= child
407 for childItem
in item
[1]:
408 theDemo
= self
.tree
.AppendItem(child
, childItem
)
409 self
.treeMap
[childItem
] = theDemo
411 self
.tree
.Expand(root
)
412 self
.tree
.Expand(firstChild
)
413 wx
.EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
414 wx
.EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
415 wx
.EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
416 wx
.EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
419 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
421 # Set up a wx.html.HtmlWindow on the Overview Notebook page
422 # we put it in a panel first because there seems to be a
423 # refresh bug of some sort (wxGTK) when it is directly in
426 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
427 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
429 else: # hopefully I can remove this hacky code soon, see SF bug #216861
430 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
431 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
432 self
.nb
.AddPage(panel
, self
.overviewText
)
434 def OnOvrSize(evt
, ovr
=self
.ovr
):
435 ovr
.SetSize(evt
.GetSize())
437 wx
.EVT_SIZE(panel
, OnOvrSize
)
438 wx
.EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
441 self
.SetOverview(self
.overviewText
, overview
)
444 # Set up a notebook page for viewing the source code of each sample
445 self
.txt
= DemoCodeViewer(self
.nb
, -1)
446 self
.nb
.AddPage(self
.txt
, "Demo Code")
447 self
.GetDemoFile('Main.py')
450 # Set up a log on the View Log Notebook page
451 self
.log
= wx
.TextCtrl(splitter2
, -1,
452 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
454 # Set the wxWindows log target to be this textctrl
455 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
457 # But instead of the above we want to show how to use our own wx.Log class
458 wx
.Log_SetActiveTarget(MyLog(self
.log
))
460 # for serious debugging
461 #wx.Log_SetActiveTarget(wx.LogStderr())
462 #wx.Log_SetTraceMask(wx.TraceMessages)
467 # add the windows to the splitter and split it.
468 splitter2
.SplitHorizontally(self
.nb
, self
.log
, 450)
469 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
471 splitter
.SetMinimumPaneSize(20)
472 splitter2
.SetMinimumPaneSize(20)
476 # select initial items
477 self
.nb
.SetSelection(0)
478 self
.tree
.SelectItem(root
)
480 if len(sys
.argv
) == 2:
482 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
486 self
.tree
.SelectItem(selectedDemo
)
487 self
.tree
.EnsureVisible(selectedDemo
)
490 wx
.LogMessage('window handle: %s' % self
.GetHandle())
493 #---------------------------------------------
494 def WriteText(self
, text
):
495 if text
[-1:] == '\n':
500 def write(self
, txt
):
503 #---------------------------------------------
504 def OnItemExpanded(self
, event
):
505 item
= event
.GetItem()
506 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
509 #---------------------------------------------
510 def OnItemCollapsed(self
, event
):
511 item
= event
.GetItem()
512 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
515 #---------------------------------------------
516 def OnTreeLeftDown(self
, event
):
517 pt
= event
.GetPosition();
518 item
, flags
= self
.tree
.HitTest(pt
)
519 if item
== self
.tree
.GetSelection():
520 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
523 #---------------------------------------------
524 def OnSelChanged(self
, event
):
528 item
= event
.GetItem()
529 itemText
= self
.tree
.GetItemText(item
)
530 self
.RunDemo(itemText
)
533 #---------------------------------------------
534 def RunDemo(self
, itemText
):
536 if self
.nb
.GetPageCount() == 3:
537 if self
.nb
.GetSelection() == 2:
538 self
.nb
.SetSelection(0)
539 # inform the window that it's time to quit if it cares
540 if self
.window
is not None:
541 if hasattr(self
.window
, "ShutdownDemo"):
542 self
.window
.ShutdownDemo()
543 wx
.SafeYield() # in case the page has pending events
544 self
.nb
.DeletePage(2)
546 if itemText
== self
.overviewText
:
547 self
.GetDemoFile('Main.py')
548 self
.SetOverview(self
.overviewText
, overview
)
553 if os
.path
.exists(itemText
+ '.py'):
555 wx
.LogMessage("Running demo %s.py..." % itemText
)
557 self
.GetDemoFile(itemText
+ '.py')
558 module
= __import__(itemText
, globals())
559 self
.SetOverview(itemText
+ " Overview", module
.overview
)
564 # in case runTest is modal, make sure things look right...
568 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
569 if self
.window
is not None:
570 self
.nb
.AddPage(self
.window
, 'Demo')
571 self
.nb
.SetSelection(2)
572 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
581 #---------------------------------------------
583 def GetDemoFile(self
, filename
):
586 self
.txt
.SetValue(open(filename
).read())
588 self
.txt
.SetValue("Cannot open %s file." % filename
)
590 self
.txt
.SetInsertionPoint(0)
591 self
.txt
.ShowPosition(0)
593 #---------------------------------------------
594 def SetOverview(self
, name
, text
):
595 self
.curOverview
= text
597 if lead
!= '<html>' and lead
!= '<HTML>':
598 text
= '<br>'.join(text
.split('\n'))
599 self
.ovr
.SetPage(text
)
600 self
.nb
.SetPageText(0, name
)
602 #---------------------------------------------
604 def OnFileExit(self
, *event
):
607 def OnHelpAbout(self
, event
):
608 from About
import MyAboutBox
609 about
= MyAboutBox(self
)
613 def OnHelpFind(self
, event
):
614 self
.nb
.SetSelection(1)
615 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
619 self
.finddlg
.Show(True)
621 def OnFind(self
, event
):
622 self
.nb
.SetSelection(1)
623 end
= self
.txt
.GetLastPosition()
624 textstring
= self
.txt
.GetRange(0, end
).lower()
625 start
= self
.txt
.GetSelection()[1]
626 findstring
= self
.finddata
.GetFindString().lower()
627 loc
= textstring
.find(findstring
, start
)
628 if loc
== -1 and start
!= 0:
629 # string not found, start at beginning
631 loc
= textstring
.find(findstring
, start
)
633 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
634 'Find String Not Found in Demo File',
635 wx
.OK | wx
.ICON_INFORMATION
)
640 self
.finddlg
.SetFocus()
643 self
.finddlg
.Destroy()
644 self
.txt
.ShowPosition(loc
)
645 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
649 def OnFindNext(self
, event
):
650 if self
.finddata
.GetFindString():
653 self
.OnHelpFind(event
)
655 def OnFindClose(self
, event
):
656 event
.GetDialog().Destroy()
659 #---------------------------------------------
660 def OnCloseWindow(self
, event
):
664 if hasattr(self
, "tbicon"):
669 #---------------------------------------------
670 def OnIdle(self
, event
):
672 self
.otherWin
.Raise()
673 self
.window
= self
.otherWin
677 #---------------------------------------------
680 showTipText
= open(opj("data/showTips")).read()
681 showTip
, index
= eval(showTipText
)
683 showTip
, index
= (1, 0)
685 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
687 showTip
= wx
.ShowTip(self
, tp
)
688 index
= tp
.GetCurrentTip()
689 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
692 #---------------------------------------------
693 def OnDemoMenu(self
, event
):
695 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
699 self
.tree
.SelectItem(selectedDemo
)
700 self
.tree
.EnsureVisible(selectedDemo
)
703 #---------------------------------------------
704 def OnTaskBarActivate(self
, evt
):
705 if self
.IsIconized():
707 if not self
.IsShown():
711 #---------------------------------------------
713 TBMENU_RESTORE
= 1000
716 def OnTaskBarMenu(self
, evt
):
718 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
719 menu
.Append(self
.TBMENU_CLOSE
, "Close")
720 self
.tbicon
.PopupMenu(menu
)
723 #---------------------------------------------
724 def OnTaskBarClose(self
, evt
):
727 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
728 # prod the main idle handler a bit to get the window to actually close
729 wx
.GetApp().ProcessIdle()
732 #---------------------------------------------
733 def OnIconfiy(self
, evt
):
734 wx
.LogMessage("OnIconfiy")
737 #---------------------------------------------
738 def OnMaximize(self
, evt
):
739 wx
.LogMessage("OnMaximize")
745 #---------------------------------------------------------------------------
746 #---------------------------------------------------------------------------
748 class MySplashScreen(wx
.SplashScreen
):
750 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
751 wx
.SplashScreen
.__init
__(self
, bmp
,
752 wx
.SPLASH_CENTRE_ON_SCREEN|wx
.SPLASH_TIMEOUT
,
754 style
= wx
.SIMPLE_BORDER|wx
.FRAME_NO_TASKBAR|wx
.STAY_ON_TOP
)
755 wx
.EVT_CLOSE(self
, self
.OnClose
)
757 def OnClose(self
, evt
):
758 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
760 evt
.Skip() # Make sure the default handler runs too...
766 Create and show the splash screen. It will then create and show
767 the main frame when it is time to do so.
771 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
772 #locale.setlocale(locale.LC_ALL, 'fr')
774 wx
.InitAllImageHandlers()
775 splash
= MySplashScreen()
781 #---------------------------------------------------------------------------
785 demoPath
= os
.path
.dirname(__file__
)
789 app
= MyApp(wx
.Platform
== "__WXMAC__")
793 #---------------------------------------------------------------------------
797 overview
= """<html><body>
800 <p> wxPython is a <b>GUI toolkit</b> for the <a
801 href="http://www.python.org/">Python</a> programming language. It
802 allows Python programmers to create programs with a robust, highly
803 functional graphical user interface, simply and easily. It is
804 implemented as a Python extension module (native code) that wraps the
805 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
806 platform GUI library, which is written in C++.
808 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
809 means that it is free for anyone to use and the source code is
810 available for anyone to look at and modify. Or anyone can contribute
811 fixes or enhnacments to the project.
813 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
814 same program will run on multiple platforms without modification.
815 Currently supported platforms are 32-bit Microsoft Windows, most Unix
816 or unix-like systems, and Macintosh OS X. Since the language is
817 Python, wxPython programs are <b>simple, easy</b> to write and easy to
820 <p> <b>This demo</b> is not only a collection of test cases for
821 wxPython, but is also designed to help you learn about and how to use
822 wxPython. Each sample is listed in the tree control on the left.
823 When a sample is selected in the tree then a module is loaded and run
824 (usually in a tab of this notebook,) and the source code of the module
825 is loaded in another tab for you to browse and learn from.
830 #----------------------------------------------------------------------------
831 #----------------------------------------------------------------------------
833 if __name__
== '__main__':
836 #----------------------------------------------------------------------------