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', [
31 # managed windows == things with a (optional) caption you can close
32 ('Base Frames and Dialogs', [
46 'wxFindReplaceDialog',
52 'wxSingleChoiceDialog',
56 # dialogs from libraries
60 'wxMultipleChoiceDialog',
61 'wxScrolledMessageDialog',
65 ('Core Windows/Controls', [
100 # controls coming from other librairies
101 ('More Windows/Controls', [
102 #'wxFloatBar', deprecated
103 #'wxMVCTree', deprecated
104 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
111 'MaskedEditControls',
120 'wxDynamicSashWindow',
127 'wxMimeTypesManager',
130 'wxStyledTextCtrl_1',
131 'wxStyledTextCtrl_2',
137 # How to lay out the controls in a frame/dialog
143 'wxLayoutConstraints',
146 'wxXmlResourceHandler',
150 ('Process and Events', [
162 ('Clipboard and DnD', [
195 # need libs not coming with the demo
196 ('Objects using an external library', [
197 'ActiveXWrapper_Acrobat',
204 ('Check out the samples dir too', [
211 #---------------------------------------------------------------------------
213 class MyLog(wx
.PyLog
):
214 def __init__(self
, textCtrl
, logTime
=0):
215 wx
.PyLog
.__init
__(self
)
217 self
.logTime
= logTime
219 def DoLogString(self
, message
, timeStamp
):
221 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
224 self
.tc
.AppendText(message
+ '\n')
227 class MyTP(wx
.PyTipProvider
):
229 return "This is my tip"
231 #---------------------------------------------------------------------------
232 # A class to be used to display source code in the demo. Try using the
233 # wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
234 # if there is an error, such as the stc module not being present.
239 from wxStyledTextCtrl_2
import PythonSTC
240 class DemoCodeViewer(PythonSTC
):
241 def __init__(self
, parent
, ID
):
242 PythonSTC
.__init
__(self
, parent
, ID
)
243 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
244 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
245 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
247 # Some methods to make it compatible with how the wxTextCtrl is used
248 def SetValue(self
, value
):
249 self
.SetReadOnly(False)
251 self
.SetReadOnly(True)
256 def SetInsertionPoint(self
, pos
):
257 self
.SetCurrentPos(pos
)
259 def ShowPosition(self
, pos
):
262 def GetLastPosition(self
):
263 return self
.GetLength()
265 def GetRange(self
, start
, end
):
266 return self
.GetTextRange(start
, end
)
268 def GetSelection(self
):
269 return self
.GetAnchor(), self
.GetCurrentPos()
271 def SetSelection(self
, start
, end
):
272 self
.SetSelectionStart(start
)
273 self
.SetSelectionEnd(end
)
277 class DemoCodeViewer(wx
.TextCtrl
):
278 def __init__(self
, parent
, ID
):
279 wx
.TextCtrl
.__init
__(self
, parent
, ID
, style
=
280 wx
.TE_MULTILINE | wx
.TE_READONLY |
281 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
284 #---------------------------------------------------------------------------
287 """Convert paths to the platform-specific separator"""
288 return apply(os
.path
.join
, tuple(path
.split('/')))
291 #---------------------------------------------------------------------------
293 class wxPythonDemo(wx
.Frame
):
294 overviewText
= "wxPython Overview"
296 def __init__(self
, parent
, id, title
):
297 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (800, 600),
298 style
=wx
.DEFAULT_FRAME_STYLE|wx
.NO_FULL_REPAINT_ON_RESIZE
)
300 self
.cwd
= os
.getcwd()
301 self
.curOverview
= ""
304 icon
= images
.getMondrianIcon()
307 if wx
.Platform
== '__WXMSW__':
308 # setup a taskbar icon, and catch some events from it
309 self
.tbicon
= wx
.TaskBarIcon()
310 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
311 wx
.EVT_TASKBAR_LEFT_DCLICK(self
.tbicon
, self
.OnTaskBarActivate
)
312 wx
.EVT_TASKBAR_RIGHT_UP(self
.tbicon
, self
.OnTaskBarMenu
)
313 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_RESTORE
, self
.OnTaskBarActivate
)
314 wx
.EVT_MENU(self
.tbicon
, self
.TBMENU_CLOSE
, self
.OnTaskBarClose
)
316 wx
.CallAfter(self
.ShowTip
)
319 wx
.EVT_IDLE(self
, self
.OnIdle
)
320 wx
.EVT_CLOSE(self
, self
.OnCloseWindow
)
321 wx
.EVT_ICONIZE(self
, self
.OnIconfiy
)
322 wx
.EVT_MAXIMIZE(self
, self
.OnMaximize
)
325 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
327 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.NO_3D|wx
.SP_3D
)
328 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.NO_3D|wx
.SP_3D
)
330 def EmptyHandler(evt
): pass
331 wx
.EVT_ERASE_BACKGROUND(splitter
, EmptyHandler
)
332 wx
.EVT_ERASE_BACKGROUND(splitter2
, EmptyHandler
)
334 # Prevent TreeCtrl from displaying all items after destruction when True
338 self
.mainmenu
= wx
.MenuBar()
341 menu
.Append(exitID
, 'E&xit\tAlt-X', 'Get the heck outta here!')
342 wx
.EVT_MENU(self
, exitID
, self
.OnFileExit
)
343 wx
.App_SetMacExitMenuItemId(exitID
)
344 self
.mainmenu
.Append(menu
, '&File')
348 for item
in _treeList
:
350 for childItem
in item
[1]:
352 submenu
.Append(mID
, childItem
)
353 wx
.EVT_MENU(self
, mID
, self
.OnDemoMenu
)
354 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
355 self
.mainmenu
.Append(menu
, '&Demo')
361 findnextID
= wx
.NewId()
363 menu
.Append(findID
, '&Find\tCtrl-F', 'Find in the Demo Code')
364 menu
.Append(findnextID
, 'Find &Next\tF3', 'Find Next')
365 menu
.AppendSeparator()
366 menu
.Append(helpID
, '&About\tCtrl-H', 'wxPython RULES!!!')
367 wx
.App_SetMacAboutMenuItemId(helpID
)
368 wx
.EVT_MENU(self
, helpID
, self
.OnHelpAbout
)
369 wx
.EVT_MENU(self
, findID
, self
.OnHelpFind
)
370 wx
.EVT_MENU(self
, findnextID
, self
.OnFindNext
)
371 wx
.EVT_COMMAND_FIND(self
, -1, self
.OnFind
)
372 wx
.EVT_COMMAND_FIND_NEXT(self
, -1, self
.OnFind
)
373 wx
.EVT_COMMAND_FIND_CLOSE(self
, -1 , self
.OnFindClose
)
374 self
.mainmenu
.Append(menu
, '&Help')
375 self
.SetMenuBar(self
.mainmenu
)
377 self
.finddata
= wx
.FindReplaceData()
380 # This is another way to set Accelerators, in addition to
381 # using the '\t<key>' syntax in the menu items.
382 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
383 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
384 (wx
.ACCEL_CTRL
, ord('F'), findID
),
385 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
387 self
.SetAcceleratorTable(aTable
)
393 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
394 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
397 root
= self
.tree
.AddRoot("wxPython Overview")
399 for item
in _treeList
:
400 child
= self
.tree
.AppendItem(root
, item
[0])
401 if not firstChild
: firstChild
= child
402 for childItem
in item
[1]:
403 theDemo
= self
.tree
.AppendItem(child
, childItem
)
404 self
.treeMap
[childItem
] = theDemo
406 self
.tree
.Expand(root
)
407 self
.tree
.Expand(firstChild
)
408 wx
.EVT_TREE_ITEM_EXPANDED (self
.tree
, tID
, self
.OnItemExpanded
)
409 wx
.EVT_TREE_ITEM_COLLAPSED (self
.tree
, tID
, self
.OnItemCollapsed
)
410 wx
.EVT_TREE_SEL_CHANGED (self
.tree
, tID
, self
.OnSelChanged
)
411 wx
.EVT_LEFT_DOWN (self
.tree
, self
.OnTreeLeftDown
)
414 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
416 # Set up a wx.html.HtmlWindow on the Overview Notebook page
417 # we put it in a panel first because there seems to be a
418 # refresh bug of some sort (wxGTK) when it is directly in
421 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
422 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
424 else: # hopefully I can remove this hacky code soon, see SF bug #216861
425 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
426 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
427 self
.nb
.AddPage(panel
, self
.overviewText
)
429 def OnOvrSize(evt
, ovr
=self
.ovr
):
430 ovr
.SetSize(evt
.GetSize())
432 wx
.EVT_SIZE(panel
, OnOvrSize
)
433 wx
.EVT_ERASE_BACKGROUND(panel
, EmptyHandler
)
436 self
.SetOverview(self
.overviewText
, overview
)
439 # Set up a notebook page for viewing the source code of each sample
440 self
.txt
= DemoCodeViewer(self
.nb
, -1)
441 self
.nb
.AddPage(self
.txt
, "Demo Code")
442 self
.GetDemoFile('Main.py')
445 # Set up a log on the View Log Notebook page
446 self
.log
= wx
.TextCtrl(splitter2
, -1,
447 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
449 # Set the wxWindows log target to be this textctrl
450 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
452 # But instead of the above we want to show how to use our own wx.Log class
453 wx
.Log_SetActiveTarget(MyLog(self
.log
))
455 # for serious debugging
456 #wx.Log_SetActiveTarget(wx.LogStderr())
457 #wx.Log_SetTraceMask(wx.TraceMessages)
462 # add the windows to the splitter and split it.
463 splitter2
.SplitHorizontally(self
.nb
, self
.log
, 450)
464 splitter
.SplitVertically(self
.tree
, splitter2
, 180)
466 splitter
.SetMinimumPaneSize(20)
467 splitter2
.SetMinimumPaneSize(20)
471 # select initial items
472 self
.nb
.SetSelection(0)
473 self
.tree
.SelectItem(root
)
475 if len(sys
.argv
) == 2:
477 selectedDemo
= self
.treeMap
[sys
.argv
[1]]
481 self
.tree
.SelectItem(selectedDemo
)
482 self
.tree
.EnsureVisible(selectedDemo
)
485 wx
.LogMessage('window handle: %s' % self
.GetHandle())
488 #---------------------------------------------
489 def WriteText(self
, text
):
490 if text
[-1:] == '\n':
495 def write(self
, txt
):
498 #---------------------------------------------
499 def OnItemExpanded(self
, event
):
500 item
= event
.GetItem()
501 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
504 #---------------------------------------------
505 def OnItemCollapsed(self
, event
):
506 item
= event
.GetItem()
507 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
510 #---------------------------------------------
511 def OnTreeLeftDown(self
, event
):
512 pt
= event
.GetPosition();
513 item
, flags
= self
.tree
.HitTest(pt
)
514 if item
== self
.tree
.GetSelection():
515 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
518 #---------------------------------------------
519 def OnSelChanged(self
, event
):
523 item
= event
.GetItem()
524 itemText
= self
.tree
.GetItemText(item
)
525 self
.RunDemo(itemText
)
528 #---------------------------------------------
529 def RunDemo(self
, itemText
):
531 if self
.nb
.GetPageCount() == 3:
532 if self
.nb
.GetSelection() == 2:
533 self
.nb
.SetSelection(0)
534 # inform the window that it's time to quit if it cares
535 if self
.window
is not None:
536 if hasattr(self
.window
, "ShutdownDemo"):
537 self
.window
.ShutdownDemo()
538 wx
.SafeYield() # in case the page has pending events
539 self
.nb
.DeletePage(2)
541 if itemText
== self
.overviewText
:
542 self
.GetDemoFile('Main.py')
543 self
.SetOverview(self
.overviewText
, overview
)
548 if os
.path
.exists(itemText
+ '.py'):
550 wx
.LogMessage("Running demo %s.py..." % itemText
)
552 self
.GetDemoFile(itemText
+ '.py')
553 module
= __import__(itemText
, globals())
554 self
.SetOverview(itemText
+ " Overview", module
.overview
)
559 # in case runTest is modal, make sure things look right...
563 self
.window
= module
.runTest(self
, self
.nb
, self
) ###
564 if self
.window
is not None:
565 self
.nb
.AddPage(self
.window
, 'Demo')
566 self
.nb
.SetSelection(2)
567 self
.nb
.Refresh() # without this wxMac has troubles showing the just added page
576 #---------------------------------------------
578 def GetDemoFile(self
, filename
):
581 self
.txt
.SetValue(open(filename
).read())
583 self
.txt
.SetValue("Cannot open %s file." % filename
)
585 self
.txt
.SetInsertionPoint(0)
586 self
.txt
.ShowPosition(0)
588 #---------------------------------------------
589 def SetOverview(self
, name
, text
):
590 self
.curOverview
= text
592 if lead
!= '<html>' and lead
!= '<HTML>':
593 text
= '<br>'.join(text
.split('\n'))
594 self
.ovr
.SetPage(text
)
595 self
.nb
.SetPageText(0, name
)
597 #---------------------------------------------
599 def OnFileExit(self
, *event
):
602 def OnHelpAbout(self
, event
):
603 from About
import MyAboutBox
604 about
= MyAboutBox(self
)
608 def OnHelpFind(self
, event
):
609 self
.nb
.SetSelection(1)
610 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
614 self
.finddlg
.Show(True)
616 def OnFind(self
, event
):
617 self
.nb
.SetSelection(1)
618 end
= self
.txt
.GetLastPosition()
619 textstring
= self
.txt
.GetRange(0, end
).lower()
620 start
= self
.txt
.GetSelection()[1]
621 findstring
= self
.finddata
.GetFindString().lower()
622 loc
= textstring
.find(findstring
, start
)
623 if loc
== -1 and start
!= 0:
624 # string not found, start at beginning
626 loc
= textstring
.find(findstring
, start
)
628 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
629 'Find String Not Found in Demo File',
630 wx
.OK | wx
.ICON_INFORMATION
)
635 self
.finddlg
.SetFocus()
638 self
.finddlg
.Destroy()
639 self
.txt
.ShowPosition(loc
)
640 self
.txt
.SetSelection(loc
, loc
+ len(findstring
))
644 def OnFindNext(self
, event
):
645 if self
.finddata
.GetFindString():
648 self
.OnHelpFind(event
)
650 def OnFindClose(self
, event
):
651 event
.GetDialog().Destroy()
654 #---------------------------------------------
655 def OnCloseWindow(self
, event
):
659 if hasattr(self
, "tbicon"):
664 #---------------------------------------------
665 def OnIdle(self
, event
):
667 self
.otherWin
.Raise()
668 self
.window
= self
.otherWin
672 #---------------------------------------------
675 showTipText
= open(opj("data/showTips")).read()
676 showTip
, index
= eval(showTipText
)
678 showTip
, index
= (1, 0)
680 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
682 showTip
= wx
.ShowTip(self
, tp
)
683 index
= tp
.GetCurrentTip()
684 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
687 #---------------------------------------------
688 def OnDemoMenu(self
, event
):
690 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
694 self
.tree
.SelectItem(selectedDemo
)
695 self
.tree
.EnsureVisible(selectedDemo
)
698 #---------------------------------------------
699 def OnTaskBarActivate(self
, evt
):
700 if self
.IsIconized():
702 if not self
.IsShown():
706 #---------------------------------------------
708 TBMENU_RESTORE
= 1000
711 def OnTaskBarMenu(self
, evt
):
713 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
714 menu
.Append(self
.TBMENU_CLOSE
, "Close")
715 self
.tbicon
.PopupMenu(menu
)
718 #---------------------------------------------
719 def OnTaskBarClose(self
, evt
):
722 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
723 # prod the main idle handler a bit to get the window to actually close
724 wx
.GetApp().ProcessIdle()
727 #---------------------------------------------
728 def OnIconfiy(self
, evt
):
729 wx
.LogMessage("OnIconfiy")
732 #---------------------------------------------
733 def OnMaximize(self
, evt
):
734 wx
.LogMessage("OnMaximize")
740 #---------------------------------------------------------------------------
741 #---------------------------------------------------------------------------
743 class MySplashScreen(wx
.SplashScreen
):
745 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
746 wx
.SplashScreen
.__init
__(self
, bmp
,
747 wx
.SPLASH_CENTRE_ON_SCREEN|wx
.SPLASH_TIMEOUT
,
749 style
= wx
.SIMPLE_BORDER|wx
.FRAME_NO_TASKBAR|wx
.STAY_ON_TOP
)
750 wx
.EVT_CLOSE(self
, self
.OnClose
)
752 def OnClose(self
, evt
):
753 frame
= wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
755 evt
.Skip() # Make sure the default handler runs too...
761 Create and show the splash screen. It will then create and show
762 the main frame when it is time to do so.
766 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
767 #locale.setlocale(locale.LC_ALL, 'fr')
769 wx
.InitAllImageHandlers()
770 splash
= MySplashScreen()
776 #---------------------------------------------------------------------------
780 demoPath
= os
.path
.dirname(__file__
)
784 app
= MyApp(wx
.Platform
== "__WXMAC__")
788 #---------------------------------------------------------------------------
792 overview
= """<html><body>
795 <p> wxPython is a <b>GUI toolkit</b> for the <a
796 href="http://www.python.org/">Python</a> programming language. It
797 allows Python programmers to create programs with a robust, highly
798 functional graphical user interface, simply and easily. It is
799 implemented as a Python extension module (native code) that wraps the
800 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
801 platform GUI library, which is written in C++.
803 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
804 means that it is free for anyone to use and the source code is
805 available for anyone to look at and modify. Or anyone can contribute
806 fixes or enhnacments to the project.
808 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
809 same program will run on multiple platforms without modification.
810 Currently supported platforms are 32-bit Microsoft Windows, most Unix
811 or unix-like systems, and Macintosh OS X. Since the language is
812 Python, wxPython programs are <b>simple, easy</b> to write and easy to
815 <p> <b>This demo</b> is not only a collection of test cases for
816 wxPython, but is also designed to help you learn about and how to use
817 wxPython. Each sample is listed in the tree control on the left.
818 When a sample is selected in the tree then a module is loaded and run
819 (usually in a tab of this notebook,) and the source code of the module
820 is loaded in another tab for you to browse and learn from.
825 #----------------------------------------------------------------------------
826 #----------------------------------------------------------------------------
828 if __name__
== '__main__':
831 #----------------------------------------------------------------------------