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',
77 # managed windows == things with a (optional) caption you can close
78 ('Frames and Dialogs', [
79 'AUI_DockingWindowMgr',
100 'SingleChoiceDialog',
104 # dialogs from libraries
107 'ScrolledMessageDialog',
111 ('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',
203 'OwnerDrawnComboBox',
220 # How to lay out the controls in a frame/dialog
230 'XmlResourceHandler',
231 'XmlResourceSubclass',
235 ('Process and Events', [
243 ##'infoframe', # needs better explanation and some fixing
247 ('Clipboard and DnD', [
273 ##'DialogUnits', # needs more explanations
293 ('Check out the samples dir too', [
300 #---------------------------------------------------------------------------
301 # Show how to derive a custom wxLog class
303 class MyLog(wx
.PyLog
):
304 def __init__(self
, textCtrl
, logTime
=0):
305 wx
.PyLog
.__init
__(self
)
307 self
.logTime
= logTime
309 def DoLogString(self
, message
, timeStamp
):
310 #print message, timeStamp
312 # message = time.strftime("%X", time.localtime(timeStamp)) + \
315 self
.tc
.AppendText(message
+ '\n')
318 class MyTP(wx
.PyTipProvider
):
320 return "This is my tip"
322 #---------------------------------------------------------------------------
323 # A class to be used to simply display a message in the demo pane
324 # rather than running the sample itself.
326 class MessagePanel(wx
.Panel
):
327 def __init__(self
, parent
, message
, caption
='', flags
=0):
328 wx
.Panel
.__init
__(self
, parent
)
333 if flags
& wx
.ICON_EXCLAMATION
:
334 artid
= wx
.ART_WARNING
335 elif flags
& wx
.ICON_ERROR
:
337 elif flags
& wx
.ICON_QUESTION
:
338 artid
= wx
.ART_QUESTION
339 elif flags
& wx
.ICON_INFORMATION
:
340 artid
= wx
.ART_INFORMATION
342 if artid
is not None:
343 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
344 icon
= wx
.StaticBitmap(self
, -1, bmp
)
346 icon
= (32,32) # make a spacer instead
349 caption
= wx
.StaticText(self
, -1, caption
)
350 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
352 message
= wx
.StaticText(self
, -1, message
)
354 # add to sizers for layout
355 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
361 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
368 box
= wx
.BoxSizer(wx
.VERTICAL
)
370 box
.Add(hbox
, 0, wx
.EXPAND
)
377 #---------------------------------------------------------------------------
378 # A class to be used to display source code in the demo. Try using the
379 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
380 # if there is an error, such as the stc module not being present.
384 ##raise ImportError # for testing the alternate implementation
386 from StyledTextCtrl_2
import PythonSTC
388 class DemoCodeEditor(PythonSTC
):
389 def __init__(self
, parent
):
390 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
393 # Some methods to make it compatible with how the wxTextCtrl is used
394 def SetValue(self
, value
):
396 value
= value
.decode('iso8859_1')
398 self
.EmptyUndoBuffer()
401 def IsModified(self
):
402 return self
.GetModify()
407 def SetInsertionPoint(self
, pos
):
408 self
.SetCurrentPos(pos
)
411 def ShowPosition(self
, pos
):
412 line
= self
.LineFromPosition(pos
)
413 #self.EnsureVisible(line)
416 def GetLastPosition(self
):
417 return self
.GetLength()
419 def GetPositionFromLine(self
, line
):
420 return self
.PositionFromLine(line
)
422 def GetRange(self
, start
, end
):
423 return self
.GetTextRange(start
, end
)
425 def GetSelection(self
):
426 return self
.GetAnchor(), self
.GetCurrentPos()
428 def SetSelection(self
, start
, end
):
429 self
.SetSelectionStart(start
)
430 self
.SetSelectionEnd(end
)
432 def SelectLine(self
, line
):
433 start
= self
.PositionFromLine(line
)
434 end
= self
.GetLineEndPosition(line
)
435 self
.SetSelection(start
, end
)
437 def SetUpEditor(self
):
439 This method carries out the work of setting up the demo editor.
440 It's seperate so as not to clutter up the init code.
444 self
.SetLexer(stc
.STC_LEX_PYTHON
)
445 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
448 self
.SetProperty("fold", "1" )
450 # Highlight tab/space mixing (shouldn't be any)
451 self
.SetProperty("tab.timmy.whinge.level", "1")
453 # Set left and right margins
456 # Set up the numbers in the margin for margin #1
457 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
458 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
459 self
.SetMarginWidth(1, 40)
461 # Indentation and tab stuff
462 self
.SetIndent(4) # Proscribed indent size for wx
463 self
.SetIndentationGuides(True) # Show indent guides
464 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
465 self
.SetTabIndents(True) # Tab key indents
466 self
.SetTabWidth(4) # Proscribed tab size for wx
467 self
.SetUseTabs(False) # Use spaces rather than tabs, or
468 # TabTimmy will complain!
470 self
.SetViewWhiteSpace(False) # Don't view white space
472 # EOL: Since we are loading/saving ourselves, and the
473 # strings will always have \n's in them, set the STC to
474 # edit them that way.
475 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
476 self
.SetViewEOL(False)
478 # No right-edge mode indicator
479 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
481 # Setup a margin to hold fold markers
482 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
483 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
484 self
.SetMarginSensitive(2, True)
485 self
.SetMarginWidth(2, 12)
487 # and now set up the fold markers
488 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
489 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
490 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
491 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
492 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
493 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
494 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
496 # Global default style
497 if wx
.Platform
== '__WXMSW__':
498 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
499 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
500 elif wx
.Platform
== '__WXMAC__':
501 # TODO: if this looks fine on Linux too, remove the Mac-specific case
502 # and use this whenever OS != MSW.
503 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
504 'fore:#000000,back:#FFFFFF,face:Courier')
506 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
507 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
509 # Clear styles and revert to default.
512 # Following style specs only indicate differences from default.
513 # The rest remains unchanged.
515 # Line numbers in margin
516 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
518 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
520 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
522 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
525 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
527 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
528 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
530 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
531 # Strings and characters
532 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
533 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
535 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
537 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
538 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
540 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
542 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
544 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
545 # Identifiers. I leave this as not bold because everything seems
546 # to be an identifier if it doesn't match the above criterae
547 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
550 self
.SetCaretForeground("BLUE")
551 # Selection background
552 self
.SetSelBackground(1, '#66CCFF')
554 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
555 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
557 def RegisterModifiedEvent(self
, eventHandler
):
558 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
562 class DemoCodeEditor(wx
.TextCtrl
):
563 def __init__(self
, parent
):
564 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
565 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
567 def RegisterModifiedEvent(self
, eventHandler
):
568 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
570 def SetReadOnly(self
, flag
):
571 self
.SetEditable(not flag
)
572 # NOTE: STC already has this method
575 return self
.GetValue()
577 def GetPositionFromLine(self
, line
):
578 return self
.XYToPosition(0,line
)
580 def GotoLine(self
, line
):
581 pos
= self
.GetPositionFromLine(line
)
582 self
.SetInsertionPoint(pos
)
583 self
.ShowPosition(pos
)
585 def SelectLine(self
, line
):
586 start
= self
.GetPositionFromLine(line
)
587 end
= start
+ self
.GetLineLength(line
)
588 self
.SetSelection(start
, end
)
591 #---------------------------------------------------------------------------
592 # Constants for module versions
596 modDefault
= modOriginal
598 #---------------------------------------------------------------------------
600 class DemoCodePanel(wx
.Panel
):
601 """Panel for the 'Demo Code' tab"""
602 def __init__(self
, parent
, mainFrame
):
603 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
604 if 'wxMSW' in wx
.PlatformInfo
:
606 self
.mainFrame
= mainFrame
607 self
.editor
= DemoCodeEditor(self
)
608 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
610 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
611 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
612 self
.btnSave
.Enable(False)
613 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
614 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
616 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
617 modModified
: wx
.RadioButton(self
, -1, "Modified") }
619 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
620 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
621 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
622 for modID
, radioButton
in self
.radioButtons
.items():
623 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
624 radioButton
.modID
= modID
# makes it easier for the event handler
625 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
627 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
628 self
.controlBox
.Add(self
.btnRestore
, 0)
630 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
631 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
632 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
633 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
636 self
.SetSizer(self
.box
)
639 # Loads a demo from a DemoModules object
640 def LoadDemo(self
, demoModules
):
641 self
.demoModules
= demoModules
642 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
643 demoModules
.SetActive(modModified
)
645 demoModules
.SetActive(modOriginal
)
646 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
647 self
.ActiveModuleChanged()
650 def ActiveModuleChanged(self
):
651 self
.LoadDemoSource(self
.demoModules
.GetSource())
652 self
.UpdateControlState()
656 def LoadDemoSource(self
, source
):
658 self
.editor
.SetValue(source
)
660 self
.btnSave
.Enable(False)
663 def JumpToLine(self
, line
, highlight
=False):
664 self
.editor
.GotoLine(line
)
665 self
.editor
.SetFocus()
667 self
.editor
.SelectLine(line
)
670 def UpdateControlState(self
):
671 active
= self
.demoModules
.GetActiveID()
672 # Update the radio/restore buttons
673 for moduleID
in self
.radioButtons
:
674 btn
= self
.radioButtons
[moduleID
]
675 if moduleID
== active
:
680 if self
.demoModules
.Exists(moduleID
):
682 if moduleID
== modModified
:
683 self
.btnRestore
.Enable(True)
686 if moduleID
== modModified
:
687 self
.btnRestore
.Enable(False)
690 def OnRadioButton(self
, event
):
691 radioSelected
= event
.GetEventObject()
692 modSelected
= radioSelected
.modID
693 if modSelected
!= self
.demoModules
.GetActiveID():
694 busy
= wx
.BusyInfo("Reloading demo module...")
695 self
.demoModules
.SetActive(modSelected
)
696 self
.ActiveModuleChanged()
699 def ReloadDemo(self
):
700 if self
.demoModules
.name
!= __name__
:
701 self
.mainFrame
.RunModule()
704 def OnCodeModified(self
, event
):
705 self
.btnSave
.Enable(self
.editor
.IsModified())
708 def OnSave(self
, event
):
709 if self
.demoModules
.Exists(modModified
):
710 if self
.demoModules
.GetActiveID() == modOriginal
:
711 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
712 "Do you want to continue?"
713 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
714 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
715 result
= dlg
.ShowModal()
716 if result
== wx
.ID_NO
:
720 self
.demoModules
.SetActive(modModified
)
721 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
723 # Create the demo directory if one doesn't already exist
724 if not os
.path
.exists(GetModifiedDirectory()):
726 os
.makedirs(GetModifiedDirectory())
727 if not os
.path
.exists(GetModifiedDirectory()):
728 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
731 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
734 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
737 f
= open(modifiedFilename
, "wt")
738 source
= self
.editor
.GetText()
744 busy
= wx
.BusyInfo("Reloading demo module...")
745 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
746 self
.ActiveModuleChanged()
749 def OnRestore(self
, event
): # Handles the "Delete Modified" button
750 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
751 self
.demoModules
.Delete(modModified
)
752 os
.unlink(modifiedFilename
) # Delete the modified copy
753 busy
= wx
.BusyInfo("Reloading demo module...")
754 self
.ActiveModuleChanged()
757 #---------------------------------------------------------------------------
760 """Convert paths to the platform-specific separator"""
761 str = apply(os
.path
.join
, tuple(path
.split('/')))
762 # HACK: on Linux, a leading / gets lost...
763 if path
.startswith('/'):
768 def GetModifiedDirectory():
770 Returns the directory where modified versions of the demo files
773 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
776 def GetModifiedFilename(name
):
778 Returns the filename of the modified version of the specified demo
780 if not name
.endswith(".py"):
782 return GetModifiedDirectory() + name
785 def GetOriginalFilename(name
):
787 Returns the filename of the original version of the specified demo
789 if not name
.endswith(".py"):
794 def DoesModifiedExist(name
):
795 """Returns whether the specified demo has a modified copy"""
796 if os
.path
.exists(GetModifiedFilename(name
)):
802 #---------------------------------------------------------------------------
804 class ModuleDictWrapper
:
805 """Emulates a module with a dynamically compiled __dict__"""
806 def __init__(self
, dict):
809 def __getattr__(self
, name
):
810 if name
in self
.dict:
811 return self
.dict[name
]
817 Dynamically manages the original/modified versions of a demo
820 def __init__(self
, name
):
824 # (dict , source , filename , description , error information )
825 # ( 0 , 1 , 2 , 3 , 4 )
826 self
.modules
= [[None, "" , "" , "<original>" , None],
827 [None, "" , "" , "<modified>" , None]]
829 # load original module
830 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
831 self
.SetActive(modOriginal
)
833 # load modified module (if one exists)
834 if DoesModifiedExist(name
):
835 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
838 def LoadFromFile(self
, modID
, filename
):
839 self
.modules
[modID
][2] = filename
840 file = open(filename
, "rt")
841 self
.LoadFromSource(modID
, file.read())
845 def LoadFromSource(self
, modID
, source
):
846 self
.modules
[modID
][1] = source
850 def LoadDict(self
, modID
):
851 if self
.name
!= __name__
:
852 source
= self
.modules
[modID
][1]
853 #description = self.modules[modID][3]
854 description
= self
.modules
[modID
][2]
857 self
.modules
[modID
][0] = {}
858 code
= compile(source
, description
, "exec")
859 exec code
in self
.modules
[modID
][0]
861 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
862 self
.modules
[modID
][0] = None
864 self
.modules
[modID
][4] = None
867 def SetActive(self
, modID
):
868 if modID
!= modOriginal
and modID
!= modModified
:
871 self
.modActive
= modID
875 dict = self
.modules
[self
.modActive
][0]
879 return ModuleDictWrapper(dict)
882 def GetActiveID(self
):
883 return self
.modActive
886 def GetSource(self
, modID
= None):
888 modID
= self
.modActive
889 return self
.modules
[modID
][1]
892 def GetFilename(self
, modID
= None):
894 modID
= self
.modActive
895 return self
.modules
[self
.modActive
][2]
898 def GetErrorInfo(self
, modID
= None):
900 modID
= self
.modActive
901 return self
.modules
[self
.modActive
][4]
904 def Exists(self
, modID
):
905 return self
.modules
[modID
][1] != ""
908 def UpdateFile(self
, modID
= None):
909 """Updates the file from which a module was loaded
910 with (possibly updated) source"""
912 modID
= self
.modActive
914 source
= self
.modules
[modID
][1]
915 filename
= self
.modules
[modID
][2]
918 file = open(filename
, "wt")
924 def Delete(self
, modID
):
925 if self
.modActive
== modID
:
928 self
.modules
[modID
][0] = None
929 self
.modules
[modID
][1] = ""
930 self
.modules
[modID
][2] = ""
933 #---------------------------------------------------------------------------
936 """Wraps and stores information about the current exception"""
937 def __init__(self
, exc_info
):
940 excType
, excValue
= exc_info
[:2]
941 # traceback list entries: (filename, line number, function name, text)
942 self
.traceback
= traceback
.extract_tb(exc_info
[2])
944 # --Based on traceback.py::format_exception_only()--
945 if type(excType
) == types
.ClassType
:
946 self
.exception_type
= excType
.__name
__
948 self
.exception_type
= excType
950 # If it's a syntax error, extra information needs
951 # to be added to the traceback
952 if excType
is SyntaxError:
954 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
959 filename
= "<string>"
961 self
.traceback
.append( (filename
, lineno
, "", line
) )
964 self
.exception_details
= str(excValue
)
966 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
973 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
976 #---------------------------------------------------------------------------
978 class DemoErrorPanel(wx
.Panel
):
979 """Panel put into the demo tab when the demo fails to run due to errors"""
981 def __init__(self
, parent
, codePanel
, demoError
, log
):
982 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
983 self
.codePanel
= codePanel
987 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
990 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
991 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
993 # Exception Information
994 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
995 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
996 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
997 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
998 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
999 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
1000 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
1001 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
1002 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
1003 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
1005 # Set up the traceback list
1006 # This one automatically resizes last column to take up remaining space
1007 from ListCtrl
import TestListCtrl
1008 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
1009 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
1010 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
1011 self
.list.InsertColumn(0, "Filename")
1012 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
1013 self
.list.InsertColumn(2, "Function")
1014 self
.list.InsertColumn(3, "Code")
1015 self
.InsertTraceback(self
.list, demoError
.traceback
)
1016 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
1017 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
1018 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
1019 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
1020 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
1021 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
1022 + "Double-click on them to go to the offending line")
1023 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
1026 self
.SetSizer(self
.box
)
1029 def InsertTraceback(self
, list, traceback
):
1030 #Add the traceback data
1031 for x
in range(len(traceback
)):
1033 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1034 list.SetStringItem(x
, 1, str(data
[1])) # Line
1035 list.SetStringItem(x
, 2, str(data
[2])) # Function
1036 list.SetStringItem(x
, 3, str(data
[3])) # Code
1038 # Check whether this entry is from the demo module
1039 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1040 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1041 # Give it a blue colour
1042 item
= self
.list.GetItem(x
)
1043 item
.SetTextColour(wx
.BLUE
)
1044 self
.list.SetItem(item
)
1046 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1049 def OnItemSelected(self
, event
):
1050 # This occurs before OnDoubleClick and can be used to set the
1051 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1052 self
.currentItem
= event
.m_itemIndex
1056 def OnDoubleClick(self
, event
):
1057 # If double-clicking on a demo's entry, jump to the line number
1058 line
= self
.list.GetItemData(self
.currentItem
)
1060 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1061 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1065 #---------------------------------------------------------------------------
1067 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1068 TBMENU_RESTORE
= wx
.NewId()
1069 TBMENU_CLOSE
= wx
.NewId()
1070 TBMENU_CHANGE
= wx
.NewId()
1071 TBMENU_REMOVE
= wx
.NewId()
1073 def __init__(self
, frame
):
1074 wx
.TaskBarIcon
.__init
__(self
)
1078 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1079 self
.SetIcon(icon
, "wxPython Demo")
1083 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1084 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1085 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1086 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1087 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1090 def CreatePopupMenu(self
):
1092 This method is called by the base class when it needs to popup
1093 the menu for the default EVT_RIGHT_DOWN event. Just create
1094 the menu how you want it and return it from this function,
1095 the base class takes care of the rest.
1098 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1099 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1100 menu
.AppendSeparator()
1101 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1102 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1106 def MakeIcon(self
, img
):
1108 The various platforms have different requirements for the
1111 if "wxMSW" in wx
.PlatformInfo
:
1112 img
= img
.Scale(16, 16)
1113 elif "wxGTK" in wx
.PlatformInfo
:
1114 img
= img
.Scale(22, 22)
1115 # wxMac can be any size upto 128x128, so leave the source img alone....
1116 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1120 def OnTaskBarActivate(self
, evt
):
1121 if self
.frame
.IsIconized():
1122 self
.frame
.Iconize(False)
1123 if not self
.frame
.IsShown():
1124 self
.frame
.Show(True)
1128 def OnTaskBarClose(self
, evt
):
1132 def OnTaskBarChange(self
, evt
):
1133 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1134 name
= names
[self
.imgidx
]
1136 getFunc
= getattr(images
, "get%sImage" % name
)
1138 if self
.imgidx
>= len(names
):
1141 icon
= self
.MakeIcon(getFunc())
1142 self
.SetIcon(icon
, "This is a new icon: " + name
)
1145 def OnTaskBarRemove(self
, evt
):
1149 #---------------------------------------------------------------------------
1150 class wxPythonDemo(wx
.Frame
):
1151 overviewText
= "wxPython Overview"
1153 def __init__(self
, parent
, title
):
1154 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1155 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1157 self
.SetMinSize((640,480))
1160 self
.cwd
= os
.getcwd()
1161 self
.curOverview
= ""
1162 self
.demoPage
= None
1163 self
.codePage
= None
1165 self
.firstTime
= True
1168 icon
= images
.getWXPdemoIcon()
1172 self
.tbicon
= DemoTaskBarIcon(self
)
1176 wx
.CallAfter(self
.ShowTip
)
1178 self
.otherWin
= None
1179 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1180 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1181 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1182 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1184 self
.Centre(wx
.BOTH
)
1185 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1187 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1188 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1190 def EmptyHandler(evt
): pass
1191 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1192 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1194 # Prevent TreeCtrl from displaying all items after destruction when True
1198 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1201 self
.mainmenu
= wx
.MenuBar()
1203 item
= menu
.Append(-1, '&Redirect Output',
1204 'Redirect print statements to a window',
1206 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1208 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1209 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1210 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1211 self
.mainmenu
.Append(menu
, '&File')
1215 for item
in _treeList
:
1217 for childItem
in item
[1]:
1218 mi
= submenu
.Append(-1, childItem
)
1219 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1220 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1221 self
.mainmenu
.Append(menu
, '&Demo')
1226 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1227 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1228 menu
.AppendSeparator()
1230 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1231 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1232 menu
.AppendSeparator()
1233 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1234 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1236 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1237 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1238 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1239 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1240 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1241 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1242 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1243 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1244 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1245 self
.mainmenu
.Append(menu
, '&Help')
1246 self
.SetMenuBar(self
.mainmenu
)
1248 self
.finddata
= wx
.FindReplaceData()
1249 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1252 # This is another way to set Accelerators, in addition to
1253 # using the '\t<key>' syntax in the menu items.
1254 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1255 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1256 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1257 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1259 self
.SetAcceleratorTable(aTable
)
1264 leftPanel
= wx
.Panel(splitter
)
1266 self
.filter = wx
.TextCtrl(leftPanel
)
1267 self
.filter.Bind(wx
.EVT_TEXT
, self
.RecreateTree
)
1270 self
.tree
= wx
.TreeCtrl(leftPanel
, tID
, style
=
1271 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1274 self
.root
= self
.tree
.AddRoot("wxPython Overview")
1276 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1277 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1278 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1279 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1281 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1282 # we put it in a panel first because there seems to be a
1283 # refresh bug of some sort (wxGTK) when it is directly in
1286 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1287 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1289 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1290 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1291 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1292 self
.nb
.AddPage(panel
, self
.overviewText
)
1294 def OnOvrSize(evt
, ovr
=self
.ovr
):
1295 ovr
.SetSize(evt
.GetSize())
1296 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1297 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1299 if "gtk2" in wx
.PlatformInfo
:
1300 self
.ovr
.SetStandardFonts()
1301 self
.SetOverview(self
.overviewText
, mainOverview
)
1304 # Set up a log window
1305 self
.log
= wx
.TextCtrl(splitter2
, -1,
1306 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1308 # Set the wxWindows log target to be this textctrl
1309 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1311 # But instead of the above we want to show how to use our own wx.Log class
1312 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1314 # for serious debugging
1315 #wx.Log_SetActiveTarget(wx.LogStderr())
1316 #wx.Log_SetTraceMask(wx.TraceMessages)
1319 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1320 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1322 # add the windows to the splitter and split it.
1323 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1324 leftBox
= wx
.BoxSizer(wx
.VERTICAL
)
1325 leftBox
.Add(self
.tree
, 1, wx
.EXPAND
)
1326 leftBox
.Add(wx
.StaticText(leftPanel
, label
= "Filter Demos:"), 0, wx
.TOP|wx
.LEFT
, 5)
1327 leftBox
.Add(self
.filter, 0, wx
.EXPAND|wx
.ALL
, 5)
1328 leftPanel
.SetSizer(leftBox
)
1329 splitter
.SplitVertically(leftPanel
, splitter2
, 220)
1331 splitter
.SetMinimumPaneSize(120)
1332 splitter2
.SetMinimumPaneSize(60)
1334 # Make the splitter on the right expand the top window when resized
1335 def SplitterOnSize(evt
):
1336 splitter
= evt
.GetEventObject()
1337 sz
= splitter
.GetSize()
1338 splitter
.SetSashPosition(sz
.height
- 160, False)
1341 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1343 # select initial items
1344 self
.nb
.SetSelection(0)
1345 self
.tree
.SelectItem(self
.root
)
1347 # Load 'Main' module
1348 self
.LoadDemo(self
.overviewText
)
1351 # select some other initial module?
1352 if len(sys
.argv
) > 1:
1354 if arg
.endswith('.py'):
1356 selectedDemo
= self
.treeMap
.get(arg
, None)
1358 self
.tree
.SelectItem(selectedDemo
)
1359 self
.tree
.EnsureVisible(selectedDemo
)
1362 #---------------------------------------------
1364 def RecreateTree(self
, evt
=None):
1365 self
.tree
.DeleteAllItems()
1366 self
.root
= self
.tree
.AddRoot("wxPython Overview")
1368 filter = self
.filter.GetValue()
1369 for category
, items
in _treeList
:
1371 items
= [item
for item
in items
if filter in item
.lower()]
1373 child
= self
.tree
.AppendItem(self
.root
, category
)
1374 if not firstChild
: firstChild
= child
1375 for childItem
in items
:
1376 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1377 self
.treeMap
[childItem
] = theDemo
1379 self
.tree
.Expand(self
.root
)
1381 self
.tree
.Expand(firstChild
)
1384 def WriteText(self
, text
):
1385 if text
[-1:] == '\n':
1389 def write(self
, txt
):
1392 #---------------------------------------------
1393 def OnItemExpanded(self
, event
):
1394 item
= event
.GetItem()
1395 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1398 #---------------------------------------------
1399 def OnItemCollapsed(self
, event
):
1400 item
= event
.GetItem()
1401 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1404 #---------------------------------------------
1405 def OnTreeLeftDown(self
, event
):
1406 # reset the overview text if the tree item is clicked on again
1407 pt
= event
.GetPosition();
1408 item
, flags
= self
.tree
.HitTest(pt
)
1409 if item
== self
.tree
.GetSelection():
1410 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1413 #---------------------------------------------
1414 def OnSelChanged(self
, event
):
1415 if self
.dying
or not self
.loaded
:
1418 item
= event
.GetItem()
1419 itemText
= self
.tree
.GetItemText(item
)
1420 self
.LoadDemo(itemText
)
1422 #---------------------------------------------
1423 def LoadDemo(self
, demoName
):
1425 wx
.BeginBusyCursor()
1428 self
.ShutdownDemoModule()
1430 if demoName
== self
.overviewText
:
1431 # User selected the "wxPython Overview" node
1433 # Changing the main window at runtime not yet supported...
1434 self
.demoModules
= DemoModules(__name__
)
1435 self
.SetOverview(self
.overviewText
, mainOverview
)
1436 self
.LoadDemoSource()
1437 self
.UpdateNotebook(0)
1439 if os
.path
.exists(GetOriginalFilename(demoName
)):
1440 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1441 self
.demoModules
= DemoModules(demoName
)
1442 self
.LoadDemoSource()
1445 self
.SetOverview("wxPython", mainOverview
)
1446 self
.codePage
= None
1447 self
.UpdateNotebook(0)
1451 #---------------------------------------------
1452 def LoadDemoSource(self
):
1453 self
.codePage
= None
1454 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1455 self
.codePage
.LoadDemo(self
.demoModules
)
1457 #---------------------------------------------
1458 def RunModule(self
):
1459 """Runs the active module"""
1461 module
= self
.demoModules
.GetActive()
1462 self
.ShutdownDemoModule()
1465 # o The RunTest() for all samples must now return a window that can
1466 # be palced in a tab in the main notebook.
1467 # o If an error occurs (or has occurred before) an error tab is created.
1469 if module
is not None:
1470 wx
.LogMessage("Running demo module...")
1471 if hasattr(module
, "overview"):
1472 overviewText
= module
.overview
1475 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1477 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1478 DemoError(sys
.exc_info()), self
)
1480 assert self
.demoPage
is not None, "runTest must return a window!"
1483 # There was a previous error in compiling or exec-ing
1484 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1485 self
.demoModules
.GetErrorInfo(), self
)
1487 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1490 # cahnge to the demo page the first time a module is run
1491 self
.UpdateNotebook(2)
1492 self
.firstTime
= False
1494 # otherwise just stay on the same tab in case the user has changed to another one
1495 self
.UpdateNotebook()
1497 #---------------------------------------------
1498 def ShutdownDemoModule(self
):
1500 # inform the window that it's time to quit if it cares
1501 if hasattr(self
.demoPage
, "ShutdownDemo"):
1502 self
.demoPage
.ShutdownDemo()
1503 wx
.YieldIfNeeded() # in case the page has pending events
1504 self
.demoPage
= None
1506 #---------------------------------------------
1507 def UpdateNotebook(self
, select
= -1):
1511 def UpdatePage(page
, pageText
):
1514 for i
in range(nb
.GetPageCount()):
1515 if nb
.GetPageText(i
) == pageText
:
1523 nb
.AddPage(page
, pageText
)
1524 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1526 if nb
.GetPage(pagePos
) != page
:
1527 # Reload an existing page
1529 nb
.DeletePage(pagePos
)
1530 nb
.InsertPage(pagePos
, page
, pageText
)
1532 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1534 # Excellent! No redraw/flicker
1535 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1538 nb
.DeletePage(pagePos
)
1539 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1541 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1544 select
= nb
.GetSelection()
1546 UpdatePage(self
.codePage
, "Demo Code")
1547 UpdatePage(self
.demoPage
, "Demo")
1549 if select
>= 0 and select
< nb
.GetPageCount():
1550 nb
.SetSelection(select
)
1552 #---------------------------------------------
1553 def SetOverview(self
, name
, text
):
1554 self
.curOverview
= text
1556 if lead
!= '<html>' and lead
!= '<HTML>':
1557 text
= '<br>'.join(text
.split('\n'))
1559 text
= text
.decode('iso8859_1')
1560 self
.ovr
.SetPage(text
)
1561 self
.nb
.SetPageText(0, name
)
1563 #---------------------------------------------
1565 def OnFileExit(self
, *event
):
1568 def OnToggleRedirect(self
, event
):
1572 print "Print statements and other standard output will now be directed to this window."
1575 print "Print statements and other standard output will now be sent to the usual location."
1577 def OnHelpAbout(self
, event
):
1578 from About
import MyAboutBox
1579 about
= MyAboutBox(self
)
1583 def OnHelpFind(self
, event
):
1584 if self
.finddlg
!= None:
1587 self
.nb
.SetSelection(1)
1588 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1589 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1590 self
.finddlg
.Show(True)
1593 def OnUpdateFindItems(self
, evt
):
1594 evt
.Enable(self
.finddlg
== None)
1597 def OnFind(self
, event
):
1598 editor
= self
.codePage
.editor
1599 self
.nb
.SetSelection(1)
1600 end
= editor
.GetLastPosition()
1601 textstring
= editor
.GetRange(0, end
).lower()
1602 findstring
= self
.finddata
.GetFindString().lower()
1603 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1605 start
= editor
.GetSelection()[0]
1606 loc
= textstring
.rfind(findstring
, 0, start
)
1608 start
= editor
.GetSelection()[1]
1609 loc
= textstring
.find(findstring
, start
)
1610 if loc
== -1 and start
!= 0:
1611 # string not found, start at beginning
1614 loc
= textstring
.rfind(findstring
, 0, start
)
1617 loc
= textstring
.find(findstring
, start
)
1619 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1620 'Find String Not Found in Demo File',
1621 wx
.OK | wx
.ICON_INFORMATION
)
1626 self
.finddlg
.SetFocus()
1629 self
.finddlg
.Destroy()
1631 editor
.ShowPosition(loc
)
1632 editor
.SetSelection(loc
, loc
+ len(findstring
))
1636 def OnFindNext(self
, event
):
1637 if self
.finddata
.GetFindString():
1640 self
.OnHelpFind(event
)
1642 def OnFindClose(self
, event
):
1643 event
.GetDialog().Destroy()
1647 def OnOpenShellWindow(self
, evt
):
1649 # if it already exists then just make sure it's visible
1655 # Make a PyShell window
1657 namespace
= { 'wx' : wx
,
1658 'app' : wx
.GetApp(),
1661 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1662 self
.shell
.SetSize((640,480))
1665 # Hook the close event of the main frame window so that we
1666 # close the shell at the same time if it still exists
1667 def CloseShell(evt
):
1671 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1674 #---------------------------------------------
1675 def OnCloseWindow(self
, event
):
1677 self
.demoPage
= None
1678 self
.codePage
= None
1679 self
.mainmenu
= None
1680 if self
.tbicon
is not None:
1681 self
.tbicon
.Destroy()
1685 #---------------------------------------------
1686 def OnIdle(self
, event
):
1688 self
.otherWin
.Raise()
1689 self
.demoPage
= self
.otherWin
1690 self
.otherWin
= None
1693 #---------------------------------------------
1696 showTipText
= open(opj("data/showTips")).read()
1697 showTip
, index
= eval(showTipText
)
1699 showTip
, index
= (1, 0)
1701 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1703 showTip
= wx
.ShowTip(self
, tp
)
1704 index
= tp
.GetCurrentTip()
1705 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1708 #---------------------------------------------
1709 def OnDemoMenu(self
, event
):
1711 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1715 self
.tree
.SelectItem(selectedDemo
)
1716 self
.tree
.EnsureVisible(selectedDemo
)
1720 #---------------------------------------------
1721 def OnIconfiy(self
, evt
):
1722 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1725 #---------------------------------------------
1726 def OnMaximize(self
, evt
):
1727 wx
.LogMessage("OnMaximize")
1730 #---------------------------------------------
1731 def OnActivate(self
, evt
):
1732 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1735 #---------------------------------------------
1736 def OnAppActivate(self
, evt
):
1737 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1740 #---------------------------------------------------------------------------
1741 #---------------------------------------------------------------------------
1743 class MySplashScreen(wx
.SplashScreen
):
1745 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1746 wx
.SplashScreen
.__init
__(self
, bmp
,
1747 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1749 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1750 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1753 def OnClose(self
, evt
):
1754 # Make sure the default handler runs too so this window gets
1759 # if the timer is still running then go ahead and show the
1761 if self
.fc
.IsRunning():
1767 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1769 if self
.fc
.IsRunning():
1773 class MyApp(wx
.App
):
1776 Create and show the splash screen. It will then create and show
1777 the main frame when it is time to do so.
1780 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1783 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1785 # Normally when using a SplashScreen you would create it, show
1786 # it and then continue on with the applicaiton's
1787 # initialization, finally creating and showing the main
1788 # application window(s). In this case we have nothing else to
1789 # do so we'll delay showing the main frame until later (see
1790 # ShowMain above) so the users can see the SplashScreen effect.
1791 splash
= MySplashScreen()
1798 #---------------------------------------------------------------------------
1802 demoPath
= os
.path
.dirname(__file__
)
1809 #---------------------------------------------------------------------------
1812 mainOverview
= """<html><body>
1815 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1816 language. It allows Python programmers to create programs with a
1817 robust, highly functional graphical user interface, simply and easily.
1818 It is implemented as a Python extension module (native code) that
1819 wraps the popular wxWindows cross platform GUI library, which is
1822 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1823 means that it is free for anyone to use and the source code is
1824 available for anyone to look at and modify. Or anyone can contribute
1825 fixes or enhancements to the project.
1827 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1828 same program will run on multiple platforms without modification.
1829 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1830 or unix-like systems, and Macintosh OS X. Since the language is
1831 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1834 <p> <b>This demo</b> is not only a collection of test cases for
1835 wxPython, but is also designed to help you learn about and how to use
1836 wxPython. Each sample is listed in the tree control on the left.
1837 When a sample is selected in the tree then a module is loaded and run
1838 (usually in a tab of this notebook,) and the source code of the module
1839 is loaded in another tab for you to browse and learn from.
1844 #----------------------------------------------------------------------------
1845 #----------------------------------------------------------------------------
1847 if __name__
== '__main__':
1851 #----------------------------------------------------------------------------