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 #----------------------------------------------------------------------------
15 # * Problems with flickering related to ERASE_BACKGROUND
16 # and the splitters. Might be a problem with this 2.5 beta...?
17 # UPDATE: can't see on 2.5.2 GTK - maybe just a faster machine :)
19 # * Annoying switching between tabs and resulting flicker
20 # how to replace a page in the notebook without deleting/adding?
21 # Where is SetPage!? tried freeze...tried reparent of dummy panel....
24 # * UI design more prefessional
25 # * save file positions (new field in demoModules) (@ LoadDemoSource)
26 # * Update main overview
28 # * Why don't we move _treeList into a separate module
30 import sys
, os
, time
, traceback
, types
32 import wx
# This module uses the new wx namespace
39 ##print "wx.VERSION_STRING = %s (%s)" % (wx.VERSION_STRING, wx.USE_UNICODE and 'unicode' or 'ansi')
40 ##print "pid:", os.getpid()
41 ##raw_input("Press Enter...")
44 #---------------------------------------------------------------------------
49 ('Recent Additions/Updates', [
51 'AUI_DockingWindowMgr',
76 # managed windows == things with a (optional) caption you can close
77 ('Frames and Dialogs', [
78 'AUI_DockingWindowMgr',
103 # dialogs from libraries
106 'ScrolledMessageDialog',
110 ('Core Windows/Controls', [
148 ('"Book" Controls', [
157 ('Custom Controls', [
174 # controls coming from other libraries
175 ('More Windows/Controls', [
176 'ActiveX_FlashWindow',
177 'ActiveX_IEHtmlWindow',
179 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
182 'CheckListCtrlMixin',
199 'MaskedEditControls',
202 'MultiSplitterWindow',
219 # How to lay out the controls in a frame/dialog
229 'XmlResourceHandler',
230 'XmlResourceSubclass',
234 ('Process and Events', [
242 ##'infoframe', # needs better explanation and some fixing
246 ('Clipboard and DnD', [
272 ##'DialogUnits', # needs more explanations
292 ('Check out the samples dir too', [
299 #---------------------------------------------------------------------------
300 # Show how to derive a custom wxLog class
302 class MyLog(wx
.PyLog
):
303 def __init__(self
, textCtrl
, logTime
=0):
304 wx
.PyLog
.__init
__(self
)
306 self
.logTime
= logTime
308 def DoLogString(self
, message
, timeStamp
):
309 #print message, timeStamp
311 # message = time.strftime("%X", time.localtime(timeStamp)) + \
314 self
.tc
.AppendText(message
+ '\n')
317 class MyTP(wx
.PyTipProvider
):
319 return "This is my tip"
321 #---------------------------------------------------------------------------
322 # A class to be used to simply display a message in the demo pane
323 # rather than running the sample itself.
325 class MessagePanel(wx
.Panel
):
326 def __init__(self
, parent
, message
, caption
='', flags
=0):
327 wx
.Panel
.__init
__(self
, parent
)
332 if flags
& wx
.ICON_EXCLAMATION
:
333 artid
= wx
.ART_WARNING
334 elif flags
& wx
.ICON_ERROR
:
336 elif flags
& wx
.ICON_QUESTION
:
337 artid
= wx
.ART_QUESTION
338 elif flags
& wx
.ICON_INFORMATION
:
339 artid
= wx
.ART_INFORMATION
341 if artid
is not None:
342 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
343 icon
= wx
.StaticBitmap(self
, -1, bmp
)
345 icon
= (32,32) # make a spacer instead
348 caption
= wx
.StaticText(self
, -1, caption
)
349 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
351 message
= wx
.StaticText(self
, -1, message
)
353 # add to sizers for layout
354 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
360 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
367 box
= wx
.BoxSizer(wx
.VERTICAL
)
369 box
.Add(hbox
, 0, wx
.EXPAND
)
376 #---------------------------------------------------------------------------
377 # A class to be used to display source code in the demo. Try using the
378 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
379 # if there is an error, such as the stc module not being present.
383 ##raise ImportError # for testing the alternate implementation
385 from StyledTextCtrl_2
import PythonSTC
387 class DemoCodeEditor(PythonSTC
):
388 def __init__(self
, parent
):
389 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
392 # Some methods to make it compatible with how the wxTextCtrl is used
393 def SetValue(self
, value
):
395 value
= value
.decode('iso8859_1')
397 self
.EmptyUndoBuffer()
400 def IsModified(self
):
401 return self
.GetModify()
406 def SetInsertionPoint(self
, pos
):
407 self
.SetCurrentPos(pos
)
410 def ShowPosition(self
, pos
):
411 line
= self
.LineFromPosition(pos
)
412 #self.EnsureVisible(line)
415 def GetLastPosition(self
):
416 return self
.GetLength()
418 def GetPositionFromLine(self
, line
):
419 return self
.PositionFromLine(line
)
421 def GetRange(self
, start
, end
):
422 return self
.GetTextRange(start
, end
)
424 def GetSelection(self
):
425 return self
.GetAnchor(), self
.GetCurrentPos()
427 def SetSelection(self
, start
, end
):
428 self
.SetSelectionStart(start
)
429 self
.SetSelectionEnd(end
)
431 def SelectLine(self
, line
):
432 start
= self
.PositionFromLine(line
)
433 end
= self
.GetLineEndPosition(line
)
434 self
.SetSelection(start
, end
)
436 def SetUpEditor(self
):
438 This method carries out the work of setting up the demo editor.
439 It's seperate so as not to clutter up the init code.
443 self
.SetLexer(stc
.STC_LEX_PYTHON
)
444 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
447 self
.SetProperty("fold", "1" )
449 # Highlight tab/space mixing (shouldn't be any)
450 self
.SetProperty("tab.timmy.whinge.level", "1")
452 # Set left and right margins
455 # Set up the numbers in the margin for margin #1
456 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
457 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
458 self
.SetMarginWidth(1, 40)
460 # Indentation and tab stuff
461 self
.SetIndent(4) # Proscribed indent size for wx
462 self
.SetIndentationGuides(True) # Show indent guides
463 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
464 self
.SetTabIndents(True) # Tab key indents
465 self
.SetTabWidth(4) # Proscribed tab size for wx
466 self
.SetUseTabs(False) # Use spaces rather than tabs, or
467 # TabTimmy will complain!
469 self
.SetViewWhiteSpace(False) # Don't view white space
471 # EOL: Since we are loading/saving ourselves, and the
472 # strings will always have \n's in them, set the STC to
473 # edit them that way.
474 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
475 self
.SetViewEOL(False)
477 # No right-edge mode indicator
478 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
480 # Setup a margin to hold fold markers
481 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
482 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
483 self
.SetMarginSensitive(2, True)
484 self
.SetMarginWidth(2, 12)
486 # and now set up the fold markers
487 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
488 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
489 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
490 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
491 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
492 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
493 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
495 # Global default style
496 if wx
.Platform
== '__WXMSW__':
497 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
498 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
499 elif wx
.Platform
== '__WXMAC__':
500 # TODO: if this looks fine on Linux too, remove the Mac-specific case
501 # and use this whenever OS != MSW.
502 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
503 'fore:#000000,back:#FFFFFF,face:Courier')
505 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
506 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
508 # Clear styles and revert to default.
511 # Following style specs only indicate differences from default.
512 # The rest remains unchanged.
514 # Line numbers in margin
515 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
517 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
519 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
521 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
524 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
526 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
527 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
529 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
530 # Strings and characters
531 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
532 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
534 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
536 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
537 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
539 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
541 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
543 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
544 # Identifiers. I leave this as not bold because everything seems
545 # to be an identifier if it doesn't match the above criterae
546 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
549 self
.SetCaretForeground("BLUE")
550 # Selection background
551 self
.SetSelBackground(1, '#66CCFF')
553 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
554 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
556 def RegisterModifiedEvent(self
, eventHandler
):
557 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
561 class DemoCodeEditor(wx
.TextCtrl
):
562 def __init__(self
, parent
):
563 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
564 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
566 def RegisterModifiedEvent(self
, eventHandler
):
567 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
569 def SetReadOnly(self
, flag
):
570 self
.SetEditable(not flag
)
571 # NOTE: STC already has this method
574 return self
.GetValue()
576 def GetPositionFromLine(self
, line
):
577 return self
.XYToPosition(0,line
)
579 def GotoLine(self
, line
):
580 pos
= self
.GetPositionFromLine(line
)
581 self
.SetInsertionPoint(pos
)
582 self
.ShowPosition(pos
)
584 def SelectLine(self
, line
):
585 start
= self
.GetPositionFromLine(line
)
586 end
= start
+ self
.GetLineLength(line
)
587 self
.SetSelection(start
, end
)
590 #---------------------------------------------------------------------------
591 # Constants for module versions
595 modDefault
= modOriginal
597 #---------------------------------------------------------------------------
599 class DemoCodePanel(wx
.Panel
):
600 """Panel for the 'Demo Code' tab"""
601 def __init__(self
, parent
, mainFrame
):
602 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
603 if 'wxMSW' in wx
.PlatformInfo
:
605 self
.mainFrame
= mainFrame
606 self
.editor
= DemoCodeEditor(self
)
607 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
609 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
610 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
611 self
.btnSave
.Enable(False)
612 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
613 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
615 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
616 modModified
: wx
.RadioButton(self
, -1, "Modified") }
618 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
619 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
620 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
621 for modID
, radioButton
in self
.radioButtons
.items():
622 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
623 radioButton
.modID
= modID
# makes it easier for the event handler
624 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
626 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
627 self
.controlBox
.Add(self
.btnRestore
, 0)
629 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
630 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
631 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
632 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
635 self
.SetSizer(self
.box
)
638 # Loads a demo from a DemoModules object
639 def LoadDemo(self
, demoModules
):
640 self
.demoModules
= demoModules
641 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
642 demoModules
.SetActive(modModified
)
644 demoModules
.SetActive(modOriginal
)
645 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
646 self
.ActiveModuleChanged()
649 def ActiveModuleChanged(self
):
650 self
.LoadDemoSource(self
.demoModules
.GetSource())
651 self
.UpdateControlState()
655 def LoadDemoSource(self
, source
):
657 self
.editor
.SetValue(source
)
659 self
.btnSave
.Enable(False)
662 def JumpToLine(self
, line
, highlight
=False):
663 self
.editor
.GotoLine(line
)
664 self
.editor
.SetFocus()
666 self
.editor
.SelectLine(line
)
669 def UpdateControlState(self
):
670 active
= self
.demoModules
.GetActiveID()
671 # Update the radio/restore buttons
672 for moduleID
in self
.radioButtons
:
673 btn
= self
.radioButtons
[moduleID
]
674 if moduleID
== active
:
679 if self
.demoModules
.Exists(moduleID
):
681 if moduleID
== modModified
:
682 self
.btnRestore
.Enable(True)
685 if moduleID
== modModified
:
686 self
.btnRestore
.Enable(False)
689 def OnRadioButton(self
, event
):
690 radioSelected
= event
.GetEventObject()
691 modSelected
= radioSelected
.modID
692 if modSelected
!= self
.demoModules
.GetActiveID():
693 busy
= wx
.BusyInfo("Reloading demo module...")
694 self
.demoModules
.SetActive(modSelected
)
695 self
.ActiveModuleChanged()
698 def ReloadDemo(self
):
699 if self
.demoModules
.name
!= __name__
:
700 self
.mainFrame
.RunModule()
703 def OnCodeModified(self
, event
):
704 self
.btnSave
.Enable(self
.editor
.IsModified())
707 def OnSave(self
, event
):
708 if self
.demoModules
.Exists(modModified
):
709 if self
.demoModules
.GetActiveID() == modOriginal
:
710 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
711 "Do you want to continue?"
712 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
713 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
714 result
= dlg
.ShowModal()
715 if result
== wx
.ID_NO
:
719 self
.demoModules
.SetActive(modModified
)
720 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
722 # Create the demo directory if one doesn't already exist
723 if not os
.path
.exists(GetModifiedDirectory()):
725 os
.makedirs(GetModifiedDirectory())
726 if not os
.path
.exists(GetModifiedDirectory()):
727 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
730 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
733 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
736 f
= open(modifiedFilename
, "wt")
737 source
= self
.editor
.GetText()
743 busy
= wx
.BusyInfo("Reloading demo module...")
744 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
745 self
.ActiveModuleChanged()
748 def OnRestore(self
, event
): # Handles the "Delete Modified" button
749 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
750 self
.demoModules
.Delete(modModified
)
751 os
.unlink(modifiedFilename
) # Delete the modified copy
752 busy
= wx
.BusyInfo("Reloading demo module...")
753 self
.ActiveModuleChanged()
756 #---------------------------------------------------------------------------
759 """Convert paths to the platform-specific separator"""
760 str = apply(os
.path
.join
, tuple(path
.split('/')))
761 # HACK: on Linux, a leading / gets lost...
762 if path
.startswith('/'):
767 def GetModifiedDirectory():
769 Returns the directory where modified versions of the demo files
772 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
775 def GetModifiedFilename(name
):
777 Returns the filename of the modified version of the specified demo
779 if not name
.endswith(".py"):
781 return GetModifiedDirectory() + name
784 def GetOriginalFilename(name
):
786 Returns the filename of the original version of the specified demo
788 if not name
.endswith(".py"):
793 def DoesModifiedExist(name
):
794 """Returns whether the specified demo has a modified copy"""
795 if os
.path
.exists(GetModifiedFilename(name
)):
801 #---------------------------------------------------------------------------
803 class ModuleDictWrapper
:
804 """Emulates a module with a dynamically compiled __dict__"""
805 def __init__(self
, dict):
808 def __getattr__(self
, name
):
809 if name
in self
.dict:
810 return self
.dict[name
]
816 Dynamically manages the original/modified versions of a demo
819 def __init__(self
, name
):
823 # (dict , source , filename , description , error information )
824 # ( 0 , 1 , 2 , 3 , 4 )
825 self
.modules
= [[None, "" , "" , "<original>" , None],
826 [None, "" , "" , "<modified>" , None]]
828 # load original module
829 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
830 self
.SetActive(modOriginal
)
832 # load modified module (if one exists)
833 if DoesModifiedExist(name
):
834 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
837 def LoadFromFile(self
, modID
, filename
):
838 self
.modules
[modID
][2] = filename
839 file = open(filename
, "rt")
840 self
.LoadFromSource(modID
, file.read())
844 def LoadFromSource(self
, modID
, source
):
845 self
.modules
[modID
][1] = source
849 def LoadDict(self
, modID
):
850 if self
.name
!= __name__
:
851 source
= self
.modules
[modID
][1]
852 #description = self.modules[modID][3]
853 description
= self
.modules
[modID
][2]
856 self
.modules
[modID
][0] = {}
857 code
= compile(source
, description
, "exec")
858 exec code
in self
.modules
[modID
][0]
860 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
861 self
.modules
[modID
][0] = None
863 self
.modules
[modID
][4] = None
866 def SetActive(self
, modID
):
867 if modID
!= modOriginal
and modID
!= modModified
:
870 self
.modActive
= modID
874 dict = self
.modules
[self
.modActive
][0]
878 return ModuleDictWrapper(dict)
881 def GetActiveID(self
):
882 return self
.modActive
885 def GetSource(self
, modID
= None):
887 modID
= self
.modActive
888 return self
.modules
[modID
][1]
891 def GetFilename(self
, modID
= None):
893 modID
= self
.modActive
894 return self
.modules
[self
.modActive
][2]
897 def GetErrorInfo(self
, modID
= None):
899 modID
= self
.modActive
900 return self
.modules
[self
.modActive
][4]
903 def Exists(self
, modID
):
904 return self
.modules
[modID
][1] != ""
907 def UpdateFile(self
, modID
= None):
908 """Updates the file from which a module was loaded
909 with (possibly updated) source"""
911 modID
= self
.modActive
913 source
= self
.modules
[modID
][1]
914 filename
= self
.modules
[modID
][2]
917 file = open(filename
, "wt")
923 def Delete(self
, modID
):
924 if self
.modActive
== modID
:
927 self
.modules
[modID
][0] = None
928 self
.modules
[modID
][1] = ""
929 self
.modules
[modID
][2] = ""
932 #---------------------------------------------------------------------------
935 """Wraps and stores information about the current exception"""
936 def __init__(self
, exc_info
):
939 excType
, excValue
= exc_info
[:2]
940 # traceback list entries: (filename, line number, function name, text)
941 self
.traceback
= traceback
.extract_tb(exc_info
[2])
943 # --Based on traceback.py::format_exception_only()--
944 if type(excType
) == types
.ClassType
:
945 self
.exception_type
= excType
.__name
__
947 self
.exception_type
= excType
949 # If it's a syntax error, extra information needs
950 # to be added to the traceback
951 if excType
is SyntaxError:
953 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
958 filename
= "<string>"
960 self
.traceback
.append( (filename
, lineno
, "", line
) )
963 self
.exception_details
= str(excValue
)
965 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
972 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
975 #---------------------------------------------------------------------------
977 class DemoErrorPanel(wx
.Panel
):
978 """Panel put into the demo tab when the demo fails to run due to errors"""
980 def __init__(self
, parent
, codePanel
, demoError
, log
):
981 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
982 self
.codePanel
= codePanel
986 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
989 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
990 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
992 # Exception Information
993 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
994 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
995 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
996 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
997 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
998 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
999 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
1000 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
1001 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
1002 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
1004 # Set up the traceback list
1005 # This one automatically resizes last column to take up remaining space
1006 from ListCtrl
import TestListCtrl
1007 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
1008 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
1009 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
1010 self
.list.InsertColumn(0, "Filename")
1011 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
1012 self
.list.InsertColumn(2, "Function")
1013 self
.list.InsertColumn(3, "Code")
1014 self
.InsertTraceback(self
.list, demoError
.traceback
)
1015 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
1016 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
1017 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
1018 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
1019 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
1020 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
1021 + "Double-click on them to go to the offending line")
1022 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
1025 self
.SetSizer(self
.box
)
1028 def InsertTraceback(self
, list, traceback
):
1029 #Add the traceback data
1030 for x
in range(len(traceback
)):
1032 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1033 list.SetStringItem(x
, 1, str(data
[1])) # Line
1034 list.SetStringItem(x
, 2, str(data
[2])) # Function
1035 list.SetStringItem(x
, 3, str(data
[3])) # Code
1037 # Check whether this entry is from the demo module
1038 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1039 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1040 # Give it a blue colour
1041 item
= self
.list.GetItem(x
)
1042 item
.SetTextColour(wx
.BLUE
)
1043 self
.list.SetItem(item
)
1045 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1048 def OnItemSelected(self
, event
):
1049 # This occurs before OnDoubleClick and can be used to set the
1050 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1051 self
.currentItem
= event
.m_itemIndex
1055 def OnDoubleClick(self
, event
):
1056 # If double-clicking on a demo's entry, jump to the line number
1057 line
= self
.list.GetItemData(self
.currentItem
)
1059 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1060 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1064 #---------------------------------------------------------------------------
1066 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1067 TBMENU_RESTORE
= wx
.NewId()
1068 TBMENU_CLOSE
= wx
.NewId()
1069 TBMENU_CHANGE
= wx
.NewId()
1070 TBMENU_REMOVE
= wx
.NewId()
1072 def __init__(self
, frame
):
1073 wx
.TaskBarIcon
.__init
__(self
)
1077 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1078 self
.SetIcon(icon
, "wxPython Demo")
1082 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1083 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1084 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1085 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1086 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1089 def CreatePopupMenu(self
):
1091 This method is called by the base class when it needs to popup
1092 the menu for the default EVT_RIGHT_DOWN event. Just create
1093 the menu how you want it and return it from this function,
1094 the base class takes care of the rest.
1097 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1098 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1099 menu
.AppendSeparator()
1100 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1101 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1105 def MakeIcon(self
, img
):
1107 The various platforms have different requirements for the
1110 if "wxMSW" in wx
.PlatformInfo
:
1111 img
= img
.Scale(16, 16)
1112 elif "wxGTK" in wx
.PlatformInfo
:
1113 img
= img
.Scale(22, 22)
1114 # wxMac can be any size upto 128x128, so leave the source img alone....
1115 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1119 def OnTaskBarActivate(self
, evt
):
1120 if self
.frame
.IsIconized():
1121 self
.frame
.Iconize(False)
1122 if not self
.frame
.IsShown():
1123 self
.frame
.Show(True)
1127 def OnTaskBarClose(self
, evt
):
1131 def OnTaskBarChange(self
, evt
):
1132 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1133 name
= names
[self
.imgidx
]
1135 getFunc
= getattr(images
, "get%sImage" % name
)
1137 if self
.imgidx
>= len(names
):
1140 icon
= self
.MakeIcon(getFunc())
1141 self
.SetIcon(icon
, "This is a new icon: " + name
)
1144 def OnTaskBarRemove(self
, evt
):
1148 #---------------------------------------------------------------------------
1149 class wxPythonDemo(wx
.Frame
):
1150 overviewText
= "wxPython Overview"
1152 def __init__(self
, parent
, title
):
1153 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1154 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1156 self
.SetMinSize((640,480))
1159 self
.cwd
= os
.getcwd()
1160 self
.curOverview
= ""
1161 self
.demoPage
= None
1162 self
.codePage
= None
1164 self
.firstTime
= True
1167 icon
= images
.getWXPdemoIcon()
1171 self
.tbicon
= DemoTaskBarIcon(self
)
1175 wx
.CallAfter(self
.ShowTip
)
1177 self
.otherWin
= None
1178 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1179 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1180 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1181 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1183 self
.Centre(wx
.BOTH
)
1184 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1186 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1187 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1189 def EmptyHandler(evt
): pass
1190 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1191 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1193 # Prevent TreeCtrl from displaying all items after destruction when True
1197 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1200 self
.mainmenu
= wx
.MenuBar()
1202 item
= menu
.Append(-1, '&Redirect Output',
1203 'Redirect print statements to a window',
1205 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1207 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1208 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1209 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1210 self
.mainmenu
.Append(menu
, '&File')
1214 for item
in _treeList
:
1216 for childItem
in item
[1]:
1217 mi
= submenu
.Append(-1, childItem
)
1218 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1219 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1220 self
.mainmenu
.Append(menu
, '&Demo')
1225 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1226 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1227 menu
.AppendSeparator()
1229 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1230 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1231 menu
.AppendSeparator()
1232 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1233 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1235 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1236 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1237 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1238 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1239 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1240 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1241 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1242 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1243 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1244 self
.mainmenu
.Append(menu
, '&Help')
1245 self
.SetMenuBar(self
.mainmenu
)
1247 self
.finddata
= wx
.FindReplaceData()
1248 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1251 # This is another way to set Accelerators, in addition to
1252 # using the '\t<key>' syntax in the menu items.
1253 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1254 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1255 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1256 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1258 self
.SetAcceleratorTable(aTable
)
1263 leftPanel
= wx
.Panel(splitter
)
1265 self
.filter = wx
.TextCtrl(leftPanel
)
1266 self
.filter.Bind(wx
.EVT_TEXT
, self
.RecreateTree
)
1269 self
.tree
= wx
.TreeCtrl(leftPanel
, tID
, style
=
1270 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1273 self
.root
= self
.tree
.AddRoot("wxPython Overview")
1275 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1276 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1277 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1278 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1280 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1281 # we put it in a panel first because there seems to be a
1282 # refresh bug of some sort (wxGTK) when it is directly in
1285 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1286 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1288 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1289 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1290 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1291 self
.nb
.AddPage(panel
, self
.overviewText
)
1293 def OnOvrSize(evt
, ovr
=self
.ovr
):
1294 ovr
.SetSize(evt
.GetSize())
1295 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1296 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1298 if "gtk2" in wx
.PlatformInfo
:
1299 self
.ovr
.SetStandardFonts()
1300 self
.SetOverview(self
.overviewText
, mainOverview
)
1303 # Set up a log window
1304 self
.log
= wx
.TextCtrl(splitter2
, -1,
1305 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1307 # Set the wxWindows log target to be this textctrl
1308 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1310 # But instead of the above we want to show how to use our own wx.Log class
1311 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1313 # for serious debugging
1314 #wx.Log_SetActiveTarget(wx.LogStderr())
1315 #wx.Log_SetTraceMask(wx.TraceMessages)
1318 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1319 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1321 # add the windows to the splitter and split it.
1322 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1323 leftBox
= wx
.BoxSizer(wx
.VERTICAL
)
1324 leftBox
.Add(self
.tree
, 1, wx
.EXPAND
)
1325 leftBox
.Add(wx
.StaticText(leftPanel
, label
= "Filter Demos:"), 0, wx
.TOP|wx
.LEFT
, 5)
1326 leftBox
.Add(self
.filter, 0, wx
.EXPAND|wx
.ALL
, 5)
1327 leftPanel
.SetSizer(leftBox
)
1328 splitter
.SplitVertically(leftPanel
, splitter2
, 220)
1330 splitter
.SetMinimumPaneSize(120)
1331 splitter2
.SetMinimumPaneSize(60)
1333 # Make the splitter on the right expand the top window when resized
1334 def SplitterOnSize(evt
):
1335 splitter
= evt
.GetEventObject()
1336 sz
= splitter
.GetSize()
1337 splitter
.SetSashPosition(sz
.height
- 160, False)
1340 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1342 # select initial items
1343 self
.nb
.SetSelection(0)
1344 self
.tree
.SelectItem(self
.root
)
1346 # Load 'Main' module
1347 self
.LoadDemo(self
.overviewText
)
1350 # select some other initial module?
1351 if len(sys
.argv
) > 1:
1353 if arg
.endswith('.py'):
1355 selectedDemo
= self
.treeMap
.get(arg
, None)
1357 self
.tree
.SelectItem(selectedDemo
)
1358 self
.tree
.EnsureVisible(selectedDemo
)
1361 #---------------------------------------------
1363 def RecreateTree(self
, evt
=None):
1364 self
.tree
.DeleteAllItems()
1365 self
.root
= self
.tree
.AddRoot("wxPython Overview")
1367 filter = self
.filter.GetValue()
1368 for category
, items
in _treeList
:
1370 items
= [item
for item
in items
if filter in item
.lower()]
1372 child
= self
.tree
.AppendItem(self
.root
, category
)
1373 if not firstChild
: firstChild
= child
1374 for childItem
in items
:
1375 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1376 self
.treeMap
[childItem
] = theDemo
1378 self
.tree
.Expand(self
.root
)
1380 self
.tree
.Expand(firstChild
)
1383 def WriteText(self
, text
):
1384 if text
[-1:] == '\n':
1388 def write(self
, txt
):
1391 #---------------------------------------------
1392 def OnItemExpanded(self
, event
):
1393 item
= event
.GetItem()
1394 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1397 #---------------------------------------------
1398 def OnItemCollapsed(self
, event
):
1399 item
= event
.GetItem()
1400 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1403 #---------------------------------------------
1404 def OnTreeLeftDown(self
, event
):
1405 # reset the overview text if the tree item is clicked on again
1406 pt
= event
.GetPosition();
1407 item
, flags
= self
.tree
.HitTest(pt
)
1408 if item
== self
.tree
.GetSelection():
1409 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1412 #---------------------------------------------
1413 def OnSelChanged(self
, event
):
1414 if self
.dying
or not self
.loaded
:
1417 item
= event
.GetItem()
1418 itemText
= self
.tree
.GetItemText(item
)
1419 self
.LoadDemo(itemText
)
1421 #---------------------------------------------
1422 def LoadDemo(self
, demoName
):
1424 wx
.BeginBusyCursor()
1427 self
.ShutdownDemoModule()
1429 if demoName
== self
.overviewText
:
1430 # User selected the "wxPython Overview" node
1432 # Changing the main window at runtime not yet supported...
1433 self
.demoModules
= DemoModules(__name__
)
1434 self
.SetOverview(self
.overviewText
, mainOverview
)
1435 self
.LoadDemoSource()
1436 self
.UpdateNotebook(0)
1438 if os
.path
.exists(GetOriginalFilename(demoName
)):
1439 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1440 self
.demoModules
= DemoModules(demoName
)
1441 self
.LoadDemoSource()
1444 self
.SetOverview("wxPython", mainOverview
)
1445 self
.codePage
= None
1446 self
.UpdateNotebook(0)
1450 #---------------------------------------------
1451 def LoadDemoSource(self
):
1452 self
.codePage
= None
1453 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1454 self
.codePage
.LoadDemo(self
.demoModules
)
1456 #---------------------------------------------
1457 def RunModule(self
):
1458 """Runs the active module"""
1460 module
= self
.demoModules
.GetActive()
1461 self
.ShutdownDemoModule()
1464 # o The RunTest() for all samples must now return a window that can
1465 # be palced in a tab in the main notebook.
1466 # o If an error occurs (or has occurred before) an error tab is created.
1468 if module
is not None:
1469 wx
.LogMessage("Running demo module...")
1470 if hasattr(module
, "overview"):
1471 overviewText
= module
.overview
1474 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1476 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1477 DemoError(sys
.exc_info()), self
)
1479 assert self
.demoPage
is not None, "runTest must return a window!"
1482 # There was a previous error in compiling or exec-ing
1483 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1484 self
.demoModules
.GetErrorInfo(), self
)
1486 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1489 # cahnge to the demo page the first time a module is run
1490 self
.UpdateNotebook(2)
1491 self
.firstTime
= False
1493 # otherwise just stay on the same tab in case the user has changed to another one
1494 self
.UpdateNotebook()
1496 #---------------------------------------------
1497 def ShutdownDemoModule(self
):
1499 # inform the window that it's time to quit if it cares
1500 if hasattr(self
.demoPage
, "ShutdownDemo"):
1501 self
.demoPage
.ShutdownDemo()
1502 wx
.YieldIfNeeded() # in case the page has pending events
1503 self
.demoPage
= None
1505 #---------------------------------------------
1506 def UpdateNotebook(self
, select
= -1):
1510 def UpdatePage(page
, pageText
):
1513 for i
in range(nb
.GetPageCount()):
1514 if nb
.GetPageText(i
) == pageText
:
1522 nb
.AddPage(page
, pageText
)
1523 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1525 if nb
.GetPage(pagePos
) != page
:
1526 # Reload an existing page
1528 nb
.DeletePage(pagePos
)
1529 nb
.InsertPage(pagePos
, page
, pageText
)
1531 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1533 # Excellent! No redraw/flicker
1534 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1537 nb
.DeletePage(pagePos
)
1538 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1540 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1543 select
= nb
.GetSelection()
1545 UpdatePage(self
.codePage
, "Demo Code")
1546 UpdatePage(self
.demoPage
, "Demo")
1548 if select
>= 0 and select
< nb
.GetPageCount():
1549 nb
.SetSelection(select
)
1551 #---------------------------------------------
1552 def SetOverview(self
, name
, text
):
1553 self
.curOverview
= text
1555 if lead
!= '<html>' and lead
!= '<HTML>':
1556 text
= '<br>'.join(text
.split('\n'))
1558 text
= text
.decode('iso8859_1')
1559 self
.ovr
.SetPage(text
)
1560 self
.nb
.SetPageText(0, name
)
1562 #---------------------------------------------
1564 def OnFileExit(self
, *event
):
1567 def OnToggleRedirect(self
, event
):
1571 print "Print statements and other standard output will now be directed to this window."
1574 print "Print statements and other standard output will now be sent to the usual location."
1576 def OnHelpAbout(self
, event
):
1577 from About
import MyAboutBox
1578 about
= MyAboutBox(self
)
1582 def OnHelpFind(self
, event
):
1583 if self
.finddlg
!= None:
1586 self
.nb
.SetSelection(1)
1587 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1588 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1589 self
.finddlg
.Show(True)
1592 def OnUpdateFindItems(self
, evt
):
1593 evt
.Enable(self
.finddlg
== None)
1596 def OnFind(self
, event
):
1597 editor
= self
.codePage
.editor
1598 self
.nb
.SetSelection(1)
1599 end
= editor
.GetLastPosition()
1600 textstring
= editor
.GetRange(0, end
).lower()
1601 findstring
= self
.finddata
.GetFindString().lower()
1602 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1604 start
= editor
.GetSelection()[0]
1605 loc
= textstring
.rfind(findstring
, 0, start
)
1607 start
= editor
.GetSelection()[1]
1608 loc
= textstring
.find(findstring
, start
)
1609 if loc
== -1 and start
!= 0:
1610 # string not found, start at beginning
1613 loc
= textstring
.rfind(findstring
, 0, start
)
1616 loc
= textstring
.find(findstring
, start
)
1618 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1619 'Find String Not Found in Demo File',
1620 wx
.OK | wx
.ICON_INFORMATION
)
1625 self
.finddlg
.SetFocus()
1628 self
.finddlg
.Destroy()
1630 editor
.ShowPosition(loc
)
1631 editor
.SetSelection(loc
, loc
+ len(findstring
))
1635 def OnFindNext(self
, event
):
1636 if self
.finddata
.GetFindString():
1639 self
.OnHelpFind(event
)
1641 def OnFindClose(self
, event
):
1642 event
.GetDialog().Destroy()
1646 def OnOpenShellWindow(self
, evt
):
1648 # if it already exists then just make sure it's visible
1654 # Make a PyShell window
1656 namespace
= { 'wx' : wx
,
1657 'app' : wx
.GetApp(),
1660 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1661 self
.shell
.SetSize((640,480))
1664 # Hook the close event of the main frame window so that we
1665 # close the shell at the same time if it still exists
1666 def CloseShell(evt
):
1670 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1673 #---------------------------------------------
1674 def OnCloseWindow(self
, event
):
1676 self
.demoPage
= None
1677 self
.codePage
= None
1678 self
.mainmenu
= None
1679 if self
.tbicon
is not None:
1680 self
.tbicon
.Destroy()
1684 #---------------------------------------------
1685 def OnIdle(self
, event
):
1687 self
.otherWin
.Raise()
1688 self
.demoPage
= self
.otherWin
1689 self
.otherWin
= None
1692 #---------------------------------------------
1695 showTipText
= open(opj("data/showTips")).read()
1696 showTip
, index
= eval(showTipText
)
1698 showTip
, index
= (1, 0)
1700 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1702 showTip
= wx
.ShowTip(self
, tp
)
1703 index
= tp
.GetCurrentTip()
1704 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1707 #---------------------------------------------
1708 def OnDemoMenu(self
, event
):
1710 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1714 self
.tree
.SelectItem(selectedDemo
)
1715 self
.tree
.EnsureVisible(selectedDemo
)
1719 #---------------------------------------------
1720 def OnIconfiy(self
, evt
):
1721 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1724 #---------------------------------------------
1725 def OnMaximize(self
, evt
):
1726 wx
.LogMessage("OnMaximize")
1729 #---------------------------------------------
1730 def OnActivate(self
, evt
):
1731 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1734 #---------------------------------------------
1735 def OnAppActivate(self
, evt
):
1736 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1739 #---------------------------------------------------------------------------
1740 #---------------------------------------------------------------------------
1742 class MySplashScreen(wx
.SplashScreen
):
1744 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1745 wx
.SplashScreen
.__init
__(self
, bmp
,
1746 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1748 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1749 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1752 def OnClose(self
, evt
):
1753 # Make sure the default handler runs too so this window gets
1758 # if the timer is still running then go ahead and show the
1760 if self
.fc
.IsRunning():
1766 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1768 if self
.fc
.IsRunning():
1772 class MyApp(wx
.App
):
1775 Create and show the splash screen. It will then create and show
1776 the main frame when it is time to do so.
1779 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1782 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1784 # Normally when using a SplashScreen you would create it, show
1785 # it and then continue on with the applicaiton's
1786 # initialization, finally creating and showing the main
1787 # application window(s). In this case we have nothing else to
1788 # do so we'll delay showing the main frame until later (see
1789 # ShowMain above) so the users can see the SplashScreen effect.
1790 splash
= MySplashScreen()
1797 #---------------------------------------------------------------------------
1801 demoPath
= os
.path
.dirname(__file__
)
1808 #---------------------------------------------------------------------------
1811 mainOverview
= """<html><body>
1814 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1815 language. It allows Python programmers to create programs with a
1816 robust, highly functional graphical user interface, simply and easily.
1817 It is implemented as a Python extension module (native code) that
1818 wraps the popular wxWindows cross platform GUI library, which is
1821 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1822 means that it is free for anyone to use and the source code is
1823 available for anyone to look at and modify. Or anyone can contribute
1824 fixes or enhancements to the project.
1826 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1827 same program will run on multiple platforms without modification.
1828 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1829 or unix-like systems, and Macintosh OS X. Since the language is
1830 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1833 <p> <b>This demo</b> is not only a collection of test cases for
1834 wxPython, but is also designed to help you learn about and how to use
1835 wxPython. Each sample is listed in the tree control on the left.
1836 When a sample is selected in the tree then a module is loaded and run
1837 (usually in a tab of this notebook,) and the source code of the module
1838 is loaded in another tab for you to browse and learn from.
1843 #----------------------------------------------------------------------------
1844 #----------------------------------------------------------------------------
1846 if __name__
== '__main__':
1850 #----------------------------------------------------------------------------