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',
75 # managed windows == things with a (optional) caption you can close
76 ('Frames and Dialogs', [
77 'AUI_DockingWindowMgr',
102 # dialogs from libraries
105 'ScrolledMessageDialog',
109 ('Core Windows/Controls', [
146 ('"Book" Controls', [
155 ('Custom Controls', [
172 # controls coming from other libraries
173 ('More Windows/Controls', [
174 'ActiveX_FlashWindow',
175 'ActiveX_IEHtmlWindow',
177 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
180 'CheckListCtrlMixin',
196 'MaskedEditControls',
199 'MultiSplitterWindow',
216 # How to lay out the controls in a frame/dialog
226 'XmlResourceHandler',
227 'XmlResourceSubclass',
231 ('Process and Events', [
239 ##'infoframe', # needs better explanation and some fixing
243 ('Clipboard and DnD', [
269 ##'DialogUnits', # needs more explanations
289 ('Check out the samples dir too', [
296 #---------------------------------------------------------------------------
297 # Show how to derive a custom wxLog class
299 class MyLog(wx
.PyLog
):
300 def __init__(self
, textCtrl
, logTime
=0):
301 wx
.PyLog
.__init
__(self
)
303 self
.logTime
= logTime
305 def DoLogString(self
, message
, timeStamp
):
306 #print message, timeStamp
308 # message = time.strftime("%X", time.localtime(timeStamp)) + \
311 self
.tc
.AppendText(message
+ '\n')
314 class MyTP(wx
.PyTipProvider
):
316 return "This is my tip"
318 #---------------------------------------------------------------------------
319 # A class to be used to simply display a message in the demo pane
320 # rather than running the sample itself.
322 class MessagePanel(wx
.Panel
):
323 def __init__(self
, parent
, message
, caption
='', flags
=0):
324 wx
.Panel
.__init
__(self
, parent
)
329 if flags
& wx
.ICON_EXCLAMATION
:
330 artid
= wx
.ART_WARNING
331 elif flags
& wx
.ICON_ERROR
:
333 elif flags
& wx
.ICON_QUESTION
:
334 artid
= wx
.ART_QUESTION
335 elif flags
& wx
.ICON_INFORMATION
:
336 artid
= wx
.ART_INFORMATION
338 if artid
is not None:
339 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
340 icon
= wx
.StaticBitmap(self
, -1, bmp
)
342 icon
= (32,32) # make a spacer instead
345 caption
= wx
.StaticText(self
, -1, caption
)
346 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
348 message
= wx
.StaticText(self
, -1, message
)
350 # add to sizers for layout
351 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
357 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
364 box
= wx
.BoxSizer(wx
.VERTICAL
)
366 box
.Add(hbox
, 0, wx
.EXPAND
)
373 #---------------------------------------------------------------------------
374 # A class to be used to display source code in the demo. Try using the
375 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
376 # if there is an error, such as the stc module not being present.
380 ##raise ImportError # for testing the alternate implementation
382 from StyledTextCtrl_2
import PythonSTC
384 class DemoCodeEditor(PythonSTC
):
385 def __init__(self
, parent
):
386 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
389 # Some methods to make it compatible with how the wxTextCtrl is used
390 def SetValue(self
, value
):
392 value
= value
.decode('iso8859_1')
394 self
.EmptyUndoBuffer()
397 def IsModified(self
):
398 return self
.GetModify()
403 def SetInsertionPoint(self
, pos
):
404 self
.SetCurrentPos(pos
)
407 def ShowPosition(self
, pos
):
408 line
= self
.LineFromPosition(pos
)
409 #self.EnsureVisible(line)
412 def GetLastPosition(self
):
413 return self
.GetLength()
415 def GetPositionFromLine(self
, line
):
416 return self
.PositionFromLine(line
)
418 def GetRange(self
, start
, end
):
419 return self
.GetTextRange(start
, end
)
421 def GetSelection(self
):
422 return self
.GetAnchor(), self
.GetCurrentPos()
424 def SetSelection(self
, start
, end
):
425 self
.SetSelectionStart(start
)
426 self
.SetSelectionEnd(end
)
428 def SelectLine(self
, line
):
429 start
= self
.PositionFromLine(line
)
430 end
= self
.GetLineEndPosition(line
)
431 self
.SetSelection(start
, end
)
433 def SetUpEditor(self
):
435 This method carries out the work of setting up the demo editor.
436 It's seperate so as not to clutter up the init code.
440 self
.SetLexer(stc
.STC_LEX_PYTHON
)
441 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
444 self
.SetProperty("fold", "1" )
446 # Highlight tab/space mixing (shouldn't be any)
447 self
.SetProperty("tab.timmy.whinge.level", "1")
449 # Set left and right margins
452 # Set up the numbers in the margin for margin #1
453 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
454 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
455 self
.SetMarginWidth(1, 40)
457 # Indentation and tab stuff
458 self
.SetIndent(4) # Proscribed indent size for wx
459 self
.SetIndentationGuides(True) # Show indent guides
460 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
461 self
.SetTabIndents(True) # Tab key indents
462 self
.SetTabWidth(4) # Proscribed tab size for wx
463 self
.SetUseTabs(False) # Use spaces rather than tabs, or
464 # TabTimmy will complain!
466 self
.SetViewWhiteSpace(False) # Don't view white space
468 # EOL: Since we are loading/saving ourselves, and the
469 # strings will always have \n's in them, set the STC to
470 # edit them that way.
471 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
472 self
.SetViewEOL(False)
474 # No right-edge mode indicator
475 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
477 # Setup a margin to hold fold markers
478 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
479 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
480 self
.SetMarginSensitive(2, True)
481 self
.SetMarginWidth(2, 12)
483 # and now set up the fold markers
484 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
485 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
486 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
487 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
488 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
489 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
490 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
492 # Global default style
493 if wx
.Platform
== '__WXMSW__':
494 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
495 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
496 elif wx
.Platform
== '__WXMAC__':
497 # TODO: if this looks fine on Linux too, remove the Mac-specific case
498 # and use this whenever OS != MSW.
499 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
500 'fore:#000000,back:#FFFFFF,face:Courier')
502 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
503 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
505 # Clear styles and revert to default.
508 # Following style specs only indicate differences from default.
509 # The rest remains unchanged.
511 # Line numbers in margin
512 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
514 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
516 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
518 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
521 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
523 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
524 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
526 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
527 # Strings and characters
528 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
529 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
531 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
533 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
534 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
536 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
538 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
540 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
541 # Identifiers. I leave this as not bold because everything seems
542 # to be an identifier if it doesn't match the above criterae
543 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
546 self
.SetCaretForeground("BLUE")
547 # Selection background
548 self
.SetSelBackground(1, '#66CCFF')
550 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
551 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
553 def RegisterModifiedEvent(self
, eventHandler
):
554 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
558 class DemoCodeEditor(wx
.TextCtrl
):
559 def __init__(self
, parent
):
560 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
561 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
563 def RegisterModifiedEvent(self
, eventHandler
):
564 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
566 def SetReadOnly(self
, flag
):
567 self
.SetEditable(not flag
)
568 # NOTE: STC already has this method
571 return self
.GetValue()
573 def GetPositionFromLine(self
, line
):
574 return self
.XYToPosition(0,line
)
576 def GotoLine(self
, line
):
577 pos
= self
.GetPositionFromLine(line
)
578 self
.SetInsertionPoint(pos
)
579 self
.ShowPosition(pos
)
581 def SelectLine(self
, line
):
582 start
= self
.GetPositionFromLine(line
)
583 end
= start
+ self
.GetLineLength(line
)
584 self
.SetSelection(start
, end
)
587 #---------------------------------------------------------------------------
588 # Constants for module versions
592 modDefault
= modOriginal
594 #---------------------------------------------------------------------------
596 class DemoCodePanel(wx
.Panel
):
597 """Panel for the 'Demo Code' tab"""
598 def __init__(self
, parent
, mainFrame
):
599 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
600 if 'wxMSW' in wx
.PlatformInfo
:
602 self
.mainFrame
= mainFrame
603 self
.editor
= DemoCodeEditor(self
)
604 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
606 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
607 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
608 self
.btnSave
.Enable(False)
609 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
610 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
612 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
613 modModified
: wx
.RadioButton(self
, -1, "Modified") }
615 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
616 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
617 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
618 for modID
, radioButton
in self
.radioButtons
.items():
619 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
620 radioButton
.modID
= modID
# makes it easier for the event handler
621 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
623 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
624 self
.controlBox
.Add(self
.btnRestore
, 0)
626 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
627 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
628 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
629 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
632 self
.SetSizer(self
.box
)
635 # Loads a demo from a DemoModules object
636 def LoadDemo(self
, demoModules
):
637 self
.demoModules
= demoModules
638 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
639 demoModules
.SetActive(modModified
)
641 demoModules
.SetActive(modOriginal
)
642 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
643 self
.ActiveModuleChanged()
646 def ActiveModuleChanged(self
):
647 self
.LoadDemoSource(self
.demoModules
.GetSource())
648 self
.UpdateControlState()
652 def LoadDemoSource(self
, source
):
654 self
.editor
.SetValue(source
)
656 self
.btnSave
.Enable(False)
659 def JumpToLine(self
, line
, highlight
=False):
660 self
.editor
.GotoLine(line
)
661 self
.editor
.SetFocus()
663 self
.editor
.SelectLine(line
)
666 def UpdateControlState(self
):
667 active
= self
.demoModules
.GetActiveID()
668 # Update the radio/restore buttons
669 for moduleID
in self
.radioButtons
:
670 btn
= self
.radioButtons
[moduleID
]
671 if moduleID
== active
:
676 if self
.demoModules
.Exists(moduleID
):
678 if moduleID
== modModified
:
679 self
.btnRestore
.Enable(True)
682 if moduleID
== modModified
:
683 self
.btnRestore
.Enable(False)
686 def OnRadioButton(self
, event
):
687 radioSelected
= event
.GetEventObject()
688 modSelected
= radioSelected
.modID
689 if modSelected
!= self
.demoModules
.GetActiveID():
690 busy
= wx
.BusyInfo("Reloading demo module...")
691 self
.demoModules
.SetActive(modSelected
)
692 self
.ActiveModuleChanged()
695 def ReloadDemo(self
):
696 if self
.demoModules
.name
!= __name__
:
697 self
.mainFrame
.RunModule()
700 def OnCodeModified(self
, event
):
701 self
.btnSave
.Enable(self
.editor
.IsModified())
704 def OnSave(self
, event
):
705 if self
.demoModules
.Exists(modModified
):
706 if self
.demoModules
.GetActiveID() == modOriginal
:
707 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
708 "Do you want to continue?"
709 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
710 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
711 result
= dlg
.ShowModal()
712 if result
== wx
.ID_NO
:
716 self
.demoModules
.SetActive(modModified
)
717 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
719 # Create the demo directory if one doesn't already exist
720 if not os
.path
.exists(GetModifiedDirectory()):
722 os
.makedirs(GetModifiedDirectory())
723 if not os
.path
.exists(GetModifiedDirectory()):
724 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
727 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
730 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
733 f
= open(modifiedFilename
, "wt")
734 source
= self
.editor
.GetText()
740 busy
= wx
.BusyInfo("Reloading demo module...")
741 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
742 self
.ActiveModuleChanged()
745 def OnRestore(self
, event
): # Handles the "Delete Modified" button
746 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
747 self
.demoModules
.Delete(modModified
)
748 os
.unlink(modifiedFilename
) # Delete the modified copy
749 busy
= wx
.BusyInfo("Reloading demo module...")
750 self
.ActiveModuleChanged()
753 #---------------------------------------------------------------------------
756 """Convert paths to the platform-specific separator"""
757 str = apply(os
.path
.join
, tuple(path
.split('/')))
758 # HACK: on Linux, a leading / gets lost...
759 if path
.startswith('/'):
764 def GetModifiedDirectory():
766 Returns the directory where modified versions of the demo files
769 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
772 def GetModifiedFilename(name
):
774 Returns the filename of the modified version of the specified demo
776 if not name
.endswith(".py"):
778 return GetModifiedDirectory() + name
781 def GetOriginalFilename(name
):
783 Returns the filename of the original version of the specified demo
785 if not name
.endswith(".py"):
790 def DoesModifiedExist(name
):
791 """Returns whether the specified demo has a modified copy"""
792 if os
.path
.exists(GetModifiedFilename(name
)):
798 #---------------------------------------------------------------------------
800 class ModuleDictWrapper
:
801 """Emulates a module with a dynamically compiled __dict__"""
802 def __init__(self
, dict):
805 def __getattr__(self
, name
):
806 if name
in self
.dict:
807 return self
.dict[name
]
813 Dynamically manages the original/modified versions of a demo
816 def __init__(self
, name
):
820 # (dict , source , filename , description , error information )
821 # ( 0 , 1 , 2 , 3 , 4 )
822 self
.modules
= [[None, "" , "" , "<original>" , None],
823 [None, "" , "" , "<modified>" , None]]
825 # load original module
826 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
827 self
.SetActive(modOriginal
)
829 # load modified module (if one exists)
830 if DoesModifiedExist(name
):
831 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
834 def LoadFromFile(self
, modID
, filename
):
835 self
.modules
[modID
][2] = filename
836 file = open(filename
, "rt")
837 self
.LoadFromSource(modID
, file.read())
841 def LoadFromSource(self
, modID
, source
):
842 self
.modules
[modID
][1] = source
846 def LoadDict(self
, modID
):
847 if self
.name
!= __name__
:
848 source
= self
.modules
[modID
][1]
849 #description = self.modules[modID][3]
850 description
= self
.modules
[modID
][2]
853 self
.modules
[modID
][0] = {}
854 code
= compile(source
, description
, "exec")
855 exec code
in self
.modules
[modID
][0]
857 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
858 self
.modules
[modID
][0] = None
860 self
.modules
[modID
][4] = None
863 def SetActive(self
, modID
):
864 if modID
!= modOriginal
and modID
!= modModified
:
867 self
.modActive
= modID
871 dict = self
.modules
[self
.modActive
][0]
875 return ModuleDictWrapper(dict)
878 def GetActiveID(self
):
879 return self
.modActive
882 def GetSource(self
, modID
= None):
884 modID
= self
.modActive
885 return self
.modules
[modID
][1]
888 def GetFilename(self
, modID
= None):
890 modID
= self
.modActive
891 return self
.modules
[self
.modActive
][2]
894 def GetErrorInfo(self
, modID
= None):
896 modID
= self
.modActive
897 return self
.modules
[self
.modActive
][4]
900 def Exists(self
, modID
):
901 return self
.modules
[modID
][1] != ""
904 def UpdateFile(self
, modID
= None):
905 """Updates the file from which a module was loaded
906 with (possibly updated) source"""
908 modID
= self
.modActive
910 source
= self
.modules
[modID
][1]
911 filename
= self
.modules
[modID
][2]
914 file = open(filename
, "wt")
920 def Delete(self
, modID
):
921 if self
.modActive
== modID
:
924 self
.modules
[modID
][0] = None
925 self
.modules
[modID
][1] = ""
926 self
.modules
[modID
][2] = ""
929 #---------------------------------------------------------------------------
932 """Wraps and stores information about the current exception"""
933 def __init__(self
, exc_info
):
936 excType
, excValue
= exc_info
[:2]
937 # traceback list entries: (filename, line number, function name, text)
938 self
.traceback
= traceback
.extract_tb(exc_info
[2])
940 # --Based on traceback.py::format_exception_only()--
941 if type(excType
) == types
.ClassType
:
942 self
.exception_type
= excType
.__name
__
944 self
.exception_type
= excType
946 # If it's a syntax error, extra information needs
947 # to be added to the traceback
948 if excType
is SyntaxError:
950 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
955 filename
= "<string>"
957 self
.traceback
.append( (filename
, lineno
, "", line
) )
960 self
.exception_details
= str(excValue
)
962 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
969 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
972 #---------------------------------------------------------------------------
974 class DemoErrorPanel(wx
.Panel
):
975 """Panel put into the demo tab when the demo fails to run due to errors"""
977 def __init__(self
, parent
, codePanel
, demoError
, log
):
978 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
979 self
.codePanel
= codePanel
983 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
986 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
987 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
989 # Exception Information
990 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
991 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
992 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
993 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
994 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
995 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
996 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
997 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
998 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
999 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
1001 # Set up the traceback list
1002 # This one automatically resizes last column to take up remaining space
1003 from ListCtrl
import TestListCtrl
1004 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
1005 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
1006 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
1007 self
.list.InsertColumn(0, "Filename")
1008 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
1009 self
.list.InsertColumn(2, "Function")
1010 self
.list.InsertColumn(3, "Code")
1011 self
.InsertTraceback(self
.list, demoError
.traceback
)
1012 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
1013 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
1014 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
1015 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
1016 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
1017 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
1018 + "Double-click on them to go to the offending line")
1019 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
1022 self
.SetSizer(self
.box
)
1025 def InsertTraceback(self
, list, traceback
):
1026 #Add the traceback data
1027 for x
in range(len(traceback
)):
1029 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1030 list.SetStringItem(x
, 1, str(data
[1])) # Line
1031 list.SetStringItem(x
, 2, str(data
[2])) # Function
1032 list.SetStringItem(x
, 3, str(data
[3])) # Code
1034 # Check whether this entry is from the demo module
1035 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1036 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1037 # Give it a blue colour
1038 item
= self
.list.GetItem(x
)
1039 item
.SetTextColour(wx
.BLUE
)
1040 self
.list.SetItem(item
)
1042 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1045 def OnItemSelected(self
, event
):
1046 # This occurs before OnDoubleClick and can be used to set the
1047 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1048 self
.currentItem
= event
.m_itemIndex
1052 def OnDoubleClick(self
, event
):
1053 # If double-clicking on a demo's entry, jump to the line number
1054 line
= self
.list.GetItemData(self
.currentItem
)
1056 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1057 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1061 #---------------------------------------------------------------------------
1063 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1064 TBMENU_RESTORE
= wx
.NewId()
1065 TBMENU_CLOSE
= wx
.NewId()
1066 TBMENU_CHANGE
= wx
.NewId()
1067 TBMENU_REMOVE
= wx
.NewId()
1069 def __init__(self
, frame
):
1070 wx
.TaskBarIcon
.__init
__(self
)
1074 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1075 self
.SetIcon(icon
, "wxPython Demo")
1079 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1080 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1081 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1082 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1083 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1086 def CreatePopupMenu(self
):
1088 This method is called by the base class when it needs to popup
1089 the menu for the default EVT_RIGHT_DOWN event. Just create
1090 the menu how you want it and return it from this function,
1091 the base class takes care of the rest.
1094 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1095 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1096 menu
.AppendSeparator()
1097 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1098 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1102 def MakeIcon(self
, img
):
1104 The various platforms have different requirements for the
1107 if "wxMSW" in wx
.PlatformInfo
:
1108 img
= img
.Scale(16, 16)
1109 elif "wxGTK" in wx
.PlatformInfo
:
1110 img
= img
.Scale(22, 22)
1111 # wxMac can be any size upto 128x128, so leave the source img alone....
1112 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1116 def OnTaskBarActivate(self
, evt
):
1117 if self
.frame
.IsIconized():
1118 self
.frame
.Iconize(False)
1119 if not self
.frame
.IsShown():
1120 self
.frame
.Show(True)
1124 def OnTaskBarClose(self
, evt
):
1128 def OnTaskBarChange(self
, evt
):
1129 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1130 name
= names
[self
.imgidx
]
1132 getFunc
= getattr(images
, "get%sImage" % name
)
1134 if self
.imgidx
>= len(names
):
1137 icon
= self
.MakeIcon(getFunc())
1138 self
.SetIcon(icon
, "This is a new icon: " + name
)
1141 def OnTaskBarRemove(self
, evt
):
1145 #---------------------------------------------------------------------------
1146 class wxPythonDemo(wx
.Frame
):
1147 overviewText
= "wxPython Overview"
1149 def __init__(self
, parent
, title
):
1150 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1151 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1153 self
.SetMinSize((640,480))
1156 self
.cwd
= os
.getcwd()
1157 self
.curOverview
= ""
1158 self
.demoPage
= None
1159 self
.codePage
= None
1161 self
.firstTime
= True
1164 icon
= images
.getWXPdemoIcon()
1168 self
.tbicon
= DemoTaskBarIcon(self
)
1172 wx
.CallAfter(self
.ShowTip
)
1174 self
.otherWin
= None
1175 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1176 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1177 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1178 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1180 self
.Centre(wx
.BOTH
)
1181 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1183 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1184 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1186 def EmptyHandler(evt
): pass
1187 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1188 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1190 # Prevent TreeCtrl from displaying all items after destruction when True
1194 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1197 self
.mainmenu
= wx
.MenuBar()
1199 item
= menu
.Append(-1, '&Redirect Output',
1200 'Redirect print statements to a window',
1202 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1204 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1205 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1206 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1207 self
.mainmenu
.Append(menu
, '&File')
1211 for item
in _treeList
:
1213 for childItem
in item
[1]:
1214 mi
= submenu
.Append(-1, childItem
)
1215 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1216 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1217 self
.mainmenu
.Append(menu
, '&Demo')
1222 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1223 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1224 menu
.AppendSeparator()
1226 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1227 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1228 menu
.AppendSeparator()
1229 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1230 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1232 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1233 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1234 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1235 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1236 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1237 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1238 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1239 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1240 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1241 self
.mainmenu
.Append(menu
, '&Help')
1242 self
.SetMenuBar(self
.mainmenu
)
1244 self
.finddata
= wx
.FindReplaceData()
1245 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1248 # This is another way to set Accelerators, in addition to
1249 # using the '\t<key>' syntax in the menu items.
1250 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1251 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1252 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1253 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1255 self
.SetAcceleratorTable(aTable
)
1260 leftPanel
= wx
.Panel(splitter
)
1262 self
.filter = wx
.TextCtrl(leftPanel
)
1263 self
.filter.Bind(wx
.EVT_TEXT
, self
.RecreateTree
)
1266 self
.tree
= wx
.TreeCtrl(leftPanel
, tID
, style
=
1267 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1270 self
.root
= self
.tree
.AddRoot("wxPython Overview")
1272 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1273 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1274 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1275 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1277 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1278 # we put it in a panel first because there seems to be a
1279 # refresh bug of some sort (wxGTK) when it is directly in
1282 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1283 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1285 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1286 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1287 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1288 self
.nb
.AddPage(panel
, self
.overviewText
)
1290 def OnOvrSize(evt
, ovr
=self
.ovr
):
1291 ovr
.SetSize(evt
.GetSize())
1292 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1293 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1295 if "gtk2" in wx
.PlatformInfo
:
1296 self
.ovr
.SetStandardFonts()
1297 self
.SetOverview(self
.overviewText
, mainOverview
)
1300 # Set up a log window
1301 self
.log
= wx
.TextCtrl(splitter2
, -1,
1302 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1304 # Set the wxWindows log target to be this textctrl
1305 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1307 # But instead of the above we want to show how to use our own wx.Log class
1308 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1310 # for serious debugging
1311 #wx.Log_SetActiveTarget(wx.LogStderr())
1312 #wx.Log_SetTraceMask(wx.TraceMessages)
1315 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1316 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1318 # add the windows to the splitter and split it.
1319 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1320 leftBox
= wx
.BoxSizer(wx
.VERTICAL
)
1321 leftBox
.Add(self
.tree
, 1, wx
.EXPAND
)
1322 leftBox
.Add(wx
.StaticText(leftPanel
, label
= "Filter Demos:"), 0, wx
.TOP|wx
.LEFT
, 5)
1323 leftBox
.Add(self
.filter, 0, wx
.EXPAND|wx
.ALL
, 5)
1324 leftPanel
.SetSizer(leftBox
)
1325 splitter
.SplitVertically(leftPanel
, splitter2
, 220)
1327 splitter
.SetMinimumPaneSize(120)
1328 splitter2
.SetMinimumPaneSize(60)
1330 # Make the splitter on the right expand the top window when resized
1331 def SplitterOnSize(evt
):
1332 splitter
= evt
.GetEventObject()
1333 sz
= splitter
.GetSize()
1334 splitter
.SetSashPosition(sz
.height
- 160, False)
1337 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1339 # select initial items
1340 self
.nb
.SetSelection(0)
1341 self
.tree
.SelectItem(self
.root
)
1343 # Load 'Main' module
1344 self
.LoadDemo(self
.overviewText
)
1347 # select some other initial module?
1348 if len(sys
.argv
) > 1:
1350 if arg
.endswith('.py'):
1352 selectedDemo
= self
.treeMap
.get(arg
, None)
1354 self
.tree
.SelectItem(selectedDemo
)
1355 self
.tree
.EnsureVisible(selectedDemo
)
1358 #---------------------------------------------
1360 def RecreateTree(self
, evt
=None):
1361 self
.tree
.DeleteAllItems()
1362 self
.root
= self
.tree
.AddRoot("wxPython Overview")
1364 filter = self
.filter.GetValue()
1365 for category
, items
in _treeList
:
1367 items
= [item
for item
in items
if filter in item
.lower()]
1369 child
= self
.tree
.AppendItem(self
.root
, category
)
1370 if not firstChild
: firstChild
= child
1371 for childItem
in items
:
1372 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1373 self
.treeMap
[childItem
] = theDemo
1375 self
.tree
.Expand(self
.root
)
1377 self
.tree
.Expand(firstChild
)
1380 def WriteText(self
, text
):
1381 if text
[-1:] == '\n':
1385 def write(self
, txt
):
1388 #---------------------------------------------
1389 def OnItemExpanded(self
, event
):
1390 item
= event
.GetItem()
1391 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1394 #---------------------------------------------
1395 def OnItemCollapsed(self
, event
):
1396 item
= event
.GetItem()
1397 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1400 #---------------------------------------------
1401 def OnTreeLeftDown(self
, event
):
1402 # reset the overview text if the tree item is clicked on again
1403 pt
= event
.GetPosition();
1404 item
, flags
= self
.tree
.HitTest(pt
)
1405 if item
== self
.tree
.GetSelection():
1406 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1409 #---------------------------------------------
1410 def OnSelChanged(self
, event
):
1411 if self
.dying
or not self
.loaded
:
1414 item
= event
.GetItem()
1415 itemText
= self
.tree
.GetItemText(item
)
1416 self
.LoadDemo(itemText
)
1418 #---------------------------------------------
1419 def LoadDemo(self
, demoName
):
1421 wx
.BeginBusyCursor()
1424 self
.ShutdownDemoModule()
1426 if demoName
== self
.overviewText
:
1427 # User selected the "wxPython Overview" node
1429 # Changing the main window at runtime not yet supported...
1430 self
.demoModules
= DemoModules(__name__
)
1431 self
.SetOverview(self
.overviewText
, mainOverview
)
1432 self
.LoadDemoSource()
1433 self
.UpdateNotebook(0)
1435 if os
.path
.exists(GetOriginalFilename(demoName
)):
1436 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1437 self
.demoModules
= DemoModules(demoName
)
1438 self
.LoadDemoSource()
1441 self
.SetOverview("wxPython", mainOverview
)
1442 self
.codePage
= None
1443 self
.UpdateNotebook(0)
1447 #---------------------------------------------
1448 def LoadDemoSource(self
):
1449 self
.codePage
= None
1450 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1451 self
.codePage
.LoadDemo(self
.demoModules
)
1453 #---------------------------------------------
1454 def RunModule(self
):
1455 """Runs the active module"""
1457 module
= self
.demoModules
.GetActive()
1458 self
.ShutdownDemoModule()
1461 # o The RunTest() for all samples must now return a window that can
1462 # be palced in a tab in the main notebook.
1463 # o If an error occurs (or has occurred before) an error tab is created.
1465 if module
is not None:
1466 wx
.LogMessage("Running demo module...")
1467 if hasattr(module
, "overview"):
1468 overviewText
= module
.overview
1471 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1473 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1474 DemoError(sys
.exc_info()), self
)
1476 assert self
.demoPage
is not None, "runTest must return a window!"
1479 # There was a previous error in compiling or exec-ing
1480 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1481 self
.demoModules
.GetErrorInfo(), self
)
1483 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1486 # cahnge to the demo page the first time a module is run
1487 self
.UpdateNotebook(2)
1488 self
.firstTime
= False
1490 # otherwise just stay on the same tab in case the user has changed to another one
1491 self
.UpdateNotebook()
1493 #---------------------------------------------
1494 def ShutdownDemoModule(self
):
1496 # inform the window that it's time to quit if it cares
1497 if hasattr(self
.demoPage
, "ShutdownDemo"):
1498 self
.demoPage
.ShutdownDemo()
1499 wx
.YieldIfNeeded() # in case the page has pending events
1500 self
.demoPage
= None
1502 #---------------------------------------------
1503 def UpdateNotebook(self
, select
= -1):
1507 def UpdatePage(page
, pageText
):
1510 for i
in range(nb
.GetPageCount()):
1511 if nb
.GetPageText(i
) == pageText
:
1519 nb
.AddPage(page
, pageText
)
1520 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1522 if nb
.GetPage(pagePos
) != page
:
1523 # Reload an existing page
1525 nb
.DeletePage(pagePos
)
1526 nb
.InsertPage(pagePos
, page
, pageText
)
1528 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1530 # Excellent! No redraw/flicker
1531 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1534 nb
.DeletePage(pagePos
)
1535 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1537 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1540 select
= nb
.GetSelection()
1542 UpdatePage(self
.codePage
, "Demo Code")
1543 UpdatePage(self
.demoPage
, "Demo")
1545 if select
>= 0 and select
< nb
.GetPageCount():
1546 nb
.SetSelection(select
)
1548 #---------------------------------------------
1549 def SetOverview(self
, name
, text
):
1550 self
.curOverview
= text
1552 if lead
!= '<html>' and lead
!= '<HTML>':
1553 text
= '<br>'.join(text
.split('\n'))
1555 text
= text
.decode('iso8859_1')
1556 self
.ovr
.SetPage(text
)
1557 self
.nb
.SetPageText(0, name
)
1559 #---------------------------------------------
1561 def OnFileExit(self
, *event
):
1564 def OnToggleRedirect(self
, event
):
1568 print "Print statements and other standard output will now be directed to this window."
1571 print "Print statements and other standard output will now be sent to the usual location."
1573 def OnHelpAbout(self
, event
):
1574 from About
import MyAboutBox
1575 about
= MyAboutBox(self
)
1579 def OnHelpFind(self
, event
):
1580 if self
.finddlg
!= None:
1583 self
.nb
.SetSelection(1)
1584 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1585 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1586 self
.finddlg
.Show(True)
1589 def OnUpdateFindItems(self
, evt
):
1590 evt
.Enable(self
.finddlg
== None)
1593 def OnFind(self
, event
):
1594 editor
= self
.codePage
.editor
1595 self
.nb
.SetSelection(1)
1596 end
= editor
.GetLastPosition()
1597 textstring
= editor
.GetRange(0, end
).lower()
1598 findstring
= self
.finddata
.GetFindString().lower()
1599 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1601 start
= editor
.GetSelection()[0]
1602 loc
= textstring
.rfind(findstring
, 0, start
)
1604 start
= editor
.GetSelection()[1]
1605 loc
= textstring
.find(findstring
, start
)
1606 if loc
== -1 and start
!= 0:
1607 # string not found, start at beginning
1610 loc
= textstring
.rfind(findstring
, 0, start
)
1613 loc
= textstring
.find(findstring
, start
)
1615 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1616 'Find String Not Found in Demo File',
1617 wx
.OK | wx
.ICON_INFORMATION
)
1622 self
.finddlg
.SetFocus()
1625 self
.finddlg
.Destroy()
1627 editor
.ShowPosition(loc
)
1628 editor
.SetSelection(loc
, loc
+ len(findstring
))
1632 def OnFindNext(self
, event
):
1633 if self
.finddata
.GetFindString():
1636 self
.OnHelpFind(event
)
1638 def OnFindClose(self
, event
):
1639 event
.GetDialog().Destroy()
1643 def OnOpenShellWindow(self
, evt
):
1645 # if it already exists then just make sure it's visible
1651 # Make a PyShell window
1653 namespace
= { 'wx' : wx
,
1654 'app' : wx
.GetApp(),
1657 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1658 self
.shell
.SetSize((640,480))
1661 # Hook the close event of the main frame window so that we
1662 # close the shell at the same time if it still exists
1663 def CloseShell(evt
):
1667 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1670 #---------------------------------------------
1671 def OnCloseWindow(self
, event
):
1673 self
.demoPage
= None
1674 self
.codePage
= None
1675 self
.mainmenu
= None
1676 if self
.tbicon
is not None:
1677 self
.tbicon
.Destroy()
1681 #---------------------------------------------
1682 def OnIdle(self
, event
):
1684 self
.otherWin
.Raise()
1685 self
.demoPage
= self
.otherWin
1686 self
.otherWin
= None
1689 #---------------------------------------------
1692 showTipText
= open(opj("data/showTips")).read()
1693 showTip
, index
= eval(showTipText
)
1695 showTip
, index
= (1, 0)
1697 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1699 showTip
= wx
.ShowTip(self
, tp
)
1700 index
= tp
.GetCurrentTip()
1701 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1704 #---------------------------------------------
1705 def OnDemoMenu(self
, event
):
1707 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1711 self
.tree
.SelectItem(selectedDemo
)
1712 self
.tree
.EnsureVisible(selectedDemo
)
1716 #---------------------------------------------
1717 def OnIconfiy(self
, evt
):
1718 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1721 #---------------------------------------------
1722 def OnMaximize(self
, evt
):
1723 wx
.LogMessage("OnMaximize")
1726 #---------------------------------------------
1727 def OnActivate(self
, evt
):
1728 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1731 #---------------------------------------------
1732 def OnAppActivate(self
, evt
):
1733 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1736 #---------------------------------------------------------------------------
1737 #---------------------------------------------------------------------------
1739 class MySplashScreen(wx
.SplashScreen
):
1741 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1742 wx
.SplashScreen
.__init
__(self
, bmp
,
1743 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1745 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1746 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1749 def OnClose(self
, evt
):
1750 # Make sure the default handler runs too so this window gets
1755 # if the timer is still running then go ahead and show the
1757 if self
.fc
.IsRunning():
1763 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1765 if self
.fc
.IsRunning():
1769 class MyApp(wx
.App
):
1772 Create and show the splash screen. It will then create and show
1773 the main frame when it is time to do so.
1776 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1779 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1781 # Normally when using a SplashScreen you would create it, show
1782 # it and then continue on with the applicaiton's
1783 # initialization, finally creating and showing the main
1784 # application window(s). In this case we have nothing else to
1785 # do so we'll delay showing the main frame until later (see
1786 # ShowMain above) so the users can see the SplashScreen effect.
1787 splash
= MySplashScreen()
1794 #---------------------------------------------------------------------------
1798 demoPath
= os
.path
.dirname(__file__
)
1805 #---------------------------------------------------------------------------
1808 mainOverview
= """<html><body>
1811 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1812 language. It allows Python programmers to create programs with a
1813 robust, highly functional graphical user interface, simply and easily.
1814 It is implemented as a Python extension module (native code) that
1815 wraps the popular wxWindows cross platform GUI library, which is
1818 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1819 means that it is free for anyone to use and the source code is
1820 available for anyone to look at and modify. Or anyone can contribute
1821 fixes or enhancements to the project.
1823 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1824 same program will run on multiple platforms without modification.
1825 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1826 or unix-like systems, and Macintosh OS X. Since the language is
1827 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1830 <p> <b>This demo</b> is not only a collection of test cases for
1831 wxPython, but is also designed to help you learn about and how to use
1832 wxPython. Each sample is listed in the tree control on the left.
1833 When a sample is selected in the tree then a module is loaded and run
1834 (usually in a tab of this notebook,) and the source code of the module
1835 is loaded in another tab for you to browse and learn from.
1840 #----------------------------------------------------------------------------
1841 #----------------------------------------------------------------------------
1843 if __name__
== '__main__':
1847 #----------------------------------------------------------------------------