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',
68 # managed windows == things with a (optional) caption you can close
69 ('Frames and Dialogs', [
70 'AUI_DockingWindowMgr',
94 # dialogs from libraries
97 'ScrolledMessageDialog',
101 ('Core Windows/Controls', [
138 ('"Book" Controls', [
147 ('Custom Controls', [
161 # controls coming from other libraries
162 ('More Windows/Controls', [
163 'ActiveX_FlashWindow',
164 'ActiveX_IEHtmlWindow',
166 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
169 'CheckListCtrlMixin',
185 'MaskedEditControls',
188 'MultiSplitterWindow',
205 # How to lay out the controls in a frame/dialog
215 'XmlResourceHandler',
216 'XmlResourceSubclass',
220 ('Process and Events', [
228 ##'infoframe', # needs better explanation and some fixing
232 ('Clipboard and DnD', [
258 ##'DialogUnits', # needs more explanations
277 ('Check out the samples dir too', [
284 #---------------------------------------------------------------------------
285 # Show how to derive a custom wxLog class
287 class MyLog(wx
.PyLog
):
288 def __init__(self
, textCtrl
, logTime
=0):
289 wx
.PyLog
.__init
__(self
)
291 self
.logTime
= logTime
293 def DoLogString(self
, message
, timeStamp
):
294 #print message, timeStamp
296 # message = time.strftime("%X", time.localtime(timeStamp)) + \
299 self
.tc
.AppendText(message
+ '\n')
302 class MyTP(wx
.PyTipProvider
):
304 return "This is my tip"
306 #---------------------------------------------------------------------------
307 # A class to be used to simply display a message in the demo pane
308 # rather than running the sample itself.
310 class MessagePanel(wx
.Panel
):
311 def __init__(self
, parent
, message
, caption
='', flags
=0):
312 wx
.Panel
.__init
__(self
, parent
)
317 if flags
& wx
.ICON_EXCLAMATION
:
318 artid
= wx
.ART_WARNING
319 elif flags
& wx
.ICON_ERROR
:
321 elif flags
& wx
.ICON_QUESTION
:
322 artid
= wx
.ART_QUESTION
323 elif flags
& wx
.ICON_INFORMATION
:
324 artid
= wx
.ART_INFORMATION
326 if artid
is not None:
327 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
328 icon
= wx
.StaticBitmap(self
, -1, bmp
)
330 icon
= (32,32) # make a spacer instead
333 caption
= wx
.StaticText(self
, -1, caption
)
334 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
336 message
= wx
.StaticText(self
, -1, message
)
338 # add to sizers for layout
339 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
345 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
352 box
= wx
.BoxSizer(wx
.VERTICAL
)
354 box
.Add(hbox
, 0, wx
.EXPAND
)
361 #---------------------------------------------------------------------------
362 # A class to be used to display source code in the demo. Try using the
363 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
364 # if there is an error, such as the stc module not being present.
368 ##raise ImportError # for testing the alternate implementation
370 from StyledTextCtrl_2
import PythonSTC
372 class DemoCodeEditor(PythonSTC
):
373 def __init__(self
, parent
):
374 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
377 # Some methods to make it compatible with how the wxTextCtrl is used
378 def SetValue(self
, value
):
380 value
= value
.decode('iso8859_1')
382 self
.EmptyUndoBuffer()
385 def IsModified(self
):
386 return self
.GetModify()
391 def SetInsertionPoint(self
, pos
):
392 self
.SetCurrentPos(pos
)
395 def ShowPosition(self
, pos
):
396 line
= self
.LineFromPosition(pos
)
397 #self.EnsureVisible(line)
400 def GetLastPosition(self
):
401 return self
.GetLength()
403 def GetPositionFromLine(self
, line
):
404 return self
.PositionFromLine(line
)
406 def GetRange(self
, start
, end
):
407 return self
.GetTextRange(start
, end
)
409 def GetSelection(self
):
410 return self
.GetAnchor(), self
.GetCurrentPos()
412 def SetSelection(self
, start
, end
):
413 self
.SetSelectionStart(start
)
414 self
.SetSelectionEnd(end
)
416 def SelectLine(self
, line
):
417 start
= self
.PositionFromLine(line
)
418 end
= self
.GetLineEndPosition(line
)
419 self
.SetSelection(start
, end
)
421 def SetUpEditor(self
):
423 This method carries out the work of setting up the demo editor.
424 It's seperate so as not to clutter up the init code.
428 self
.SetLexer(stc
.STC_LEX_PYTHON
)
429 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
432 self
.SetProperty("fold", "1" )
434 # Highlight tab/space mixing (shouldn't be any)
435 self
.SetProperty("tab.timmy.whinge.level", "1")
437 # Set left and right margins
440 # Set up the numbers in the margin for margin #1
441 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
442 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
443 self
.SetMarginWidth(1, 40)
445 # Indentation and tab stuff
446 self
.SetIndent(4) # Proscribed indent size for wx
447 self
.SetIndentationGuides(True) # Show indent guides
448 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
449 self
.SetTabIndents(True) # Tab key indents
450 self
.SetTabWidth(4) # Proscribed tab size for wx
451 self
.SetUseTabs(False) # Use spaces rather than tabs, or
452 # TabTimmy will complain!
454 self
.SetViewWhiteSpace(False) # Don't view white space
456 # EOL: Since we are loading/saving ourselves, and the
457 # strings will always have \n's in them, set the STC to
458 # edit them that way.
459 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
460 self
.SetViewEOL(False)
462 # No right-edge mode indicator
463 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
465 # Setup a margin to hold fold markers
466 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
467 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
468 self
.SetMarginSensitive(2, True)
469 self
.SetMarginWidth(2, 12)
471 # and now set up the fold markers
472 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
473 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
474 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
475 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
476 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
477 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
478 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
480 # Global default style
481 if wx
.Platform
== '__WXMSW__':
482 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
483 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
485 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
486 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
488 # Clear styles and revert to default.
491 # Following style specs only indicate differences from default.
492 # The rest remains unchanged.
494 # Line numbers in margin
495 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
497 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
499 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
501 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
504 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
506 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
507 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
509 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
510 # Strings and characters
511 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
512 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
514 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
516 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
517 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
519 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
521 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
523 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
524 # Identifiers. I leave this as not bold because everything seems
525 # to be an identifier if it doesn't match the above criterae
526 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
529 self
.SetCaretForeground("BLUE")
530 # Selection background
531 self
.SetSelBackground(1, '#66CCFF')
533 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
534 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
536 def RegisterModifiedEvent(self
, eventHandler
):
537 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
541 class DemoCodeEditor(wx
.TextCtrl
):
542 def __init__(self
, parent
):
543 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
544 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
546 def RegisterModifiedEvent(self
, eventHandler
):
547 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
549 def SetReadOnly(self
, flag
):
550 self
.SetEditable(not flag
)
551 # NOTE: STC already has this method
554 return self
.GetValue()
556 def GetPositionFromLine(self
, line
):
557 return self
.XYToPosition(0,line
)
559 def GotoLine(self
, line
):
560 pos
= self
.GetPositionFromLine(line
)
561 self
.SetInsertionPoint(pos
)
562 self
.ShowPosition(pos
)
564 def SelectLine(self
, line
):
565 start
= self
.GetPositionFromLine(line
)
566 end
= start
+ self
.GetLineLength(line
)
567 self
.SetSelection(start
, end
)
570 #---------------------------------------------------------------------------
571 # Constants for module versions
575 modDefault
= modOriginal
577 #---------------------------------------------------------------------------
579 class DemoCodePanel(wx
.Panel
):
580 """Panel for the 'Demo Code' tab"""
581 def __init__(self
, parent
, mainFrame
):
582 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
583 if 'wxMSW' in wx
.PlatformInfo
:
585 self
.mainFrame
= mainFrame
586 self
.editor
= DemoCodeEditor(self
)
587 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
589 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
590 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
591 self
.btnSave
.Enable(False)
592 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
593 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
595 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
596 modModified
: wx
.RadioButton(self
, -1, "Modified") }
598 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
599 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
600 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
601 for modID
, radioButton
in self
.radioButtons
.items():
602 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
603 radioButton
.modID
= modID
# makes it easier for the event handler
604 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
606 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
607 self
.controlBox
.Add(self
.btnRestore
, 0)
609 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
610 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
611 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
612 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
615 self
.SetSizer(self
.box
)
618 # Loads a demo from a DemoModules object
619 def LoadDemo(self
, demoModules
):
620 self
.demoModules
= demoModules
621 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
622 demoModules
.SetActive(modModified
)
624 demoModules
.SetActive(modOriginal
)
625 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
626 self
.ActiveModuleChanged()
629 def ActiveModuleChanged(self
):
630 self
.LoadDemoSource(self
.demoModules
.GetSource())
631 self
.UpdateControlState()
635 def LoadDemoSource(self
, source
):
637 self
.editor
.SetValue(source
)
639 self
.btnSave
.Enable(False)
642 def JumpToLine(self
, line
, highlight
=False):
643 self
.editor
.GotoLine(line
)
644 self
.editor
.SetFocus()
646 self
.editor
.SelectLine(line
)
649 def UpdateControlState(self
):
650 active
= self
.demoModules
.GetActiveID()
651 # Update the radio/restore buttons
652 for moduleID
in self
.radioButtons
:
653 btn
= self
.radioButtons
[moduleID
]
654 if moduleID
== active
:
659 if self
.demoModules
.Exists(moduleID
):
661 if moduleID
== modModified
:
662 self
.btnRestore
.Enable(True)
665 if moduleID
== modModified
:
666 self
.btnRestore
.Enable(False)
669 def OnRadioButton(self
, event
):
670 radioSelected
= event
.GetEventObject()
671 modSelected
= radioSelected
.modID
672 if modSelected
!= self
.demoModules
.GetActiveID():
673 busy
= wx
.BusyInfo("Reloading demo module...")
674 self
.demoModules
.SetActive(modSelected
)
675 self
.ActiveModuleChanged()
678 def ReloadDemo(self
):
679 if self
.demoModules
.name
!= __name__
:
680 self
.mainFrame
.RunModule()
683 def OnCodeModified(self
, event
):
684 self
.btnSave
.Enable(self
.editor
.IsModified())
687 def OnSave(self
, event
):
688 if self
.demoModules
.Exists(modModified
):
689 if self
.demoModules
.GetActiveID() == modOriginal
:
690 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
691 "Do you want to continue?"
692 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
693 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
694 result
= dlg
.ShowModal()
695 if result
== wx
.ID_NO
:
699 self
.demoModules
.SetActive(modModified
)
700 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
702 # Create the demo directory if one doesn't already exist
703 if not os
.path
.exists(GetModifiedDirectory()):
705 os
.makedirs(GetModifiedDirectory())
706 if not os
.path
.exists(GetModifiedDirectory()):
707 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
710 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
713 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
716 f
= open(modifiedFilename
, "wt")
717 source
= self
.editor
.GetText()
723 busy
= wx
.BusyInfo("Reloading demo module...")
724 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
725 self
.ActiveModuleChanged()
728 def OnRestore(self
, event
): # Handles the "Delete Modified" button
729 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
730 self
.demoModules
.Delete(modModified
)
731 os
.unlink(modifiedFilename
) # Delete the modified copy
732 busy
= wx
.BusyInfo("Reloading demo module...")
733 self
.ActiveModuleChanged()
736 #---------------------------------------------------------------------------
739 """Convert paths to the platform-specific separator"""
740 str = apply(os
.path
.join
, tuple(path
.split('/')))
741 # HACK: on Linux, a leading / gets lost...
742 if path
.startswith('/'):
747 def GetModifiedDirectory():
749 Returns the directory where modified versions of the demo files
752 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
755 def GetModifiedFilename(name
):
757 Returns the filename of the modified version of the specified demo
759 if not name
.endswith(".py"):
761 return GetModifiedDirectory() + name
764 def GetOriginalFilename(name
):
766 Returns the filename of the original version of the specified demo
768 if not name
.endswith(".py"):
773 def DoesModifiedExist(name
):
774 """Returns whether the specified demo has a modified copy"""
775 if os
.path
.exists(GetModifiedFilename(name
)):
781 #---------------------------------------------------------------------------
783 class ModuleDictWrapper
:
784 """Emulates a module with a dynamically compiled __dict__"""
785 def __init__(self
, dict):
788 def __getattr__(self
, name
):
789 if name
in self
.dict:
790 return self
.dict[name
]
796 Dynamically manages the original/modified versions of a demo
799 def __init__(self
, name
):
803 # (dict , source , filename , description , error information )
804 # ( 0 , 1 , 2 , 3 , 4 )
805 self
.modules
= [[None, "" , "" , "<original>" , None],
806 [None, "" , "" , "<modified>" , None]]
808 # load original module
809 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
810 self
.SetActive(modOriginal
)
812 # load modified module (if one exists)
813 if DoesModifiedExist(name
):
814 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
817 def LoadFromFile(self
, modID
, filename
):
818 self
.modules
[modID
][2] = filename
819 file = open(filename
, "rt")
820 self
.LoadFromSource(modID
, file.read())
824 def LoadFromSource(self
, modID
, source
):
825 self
.modules
[modID
][1] = source
829 def LoadDict(self
, modID
):
830 if self
.name
!= __name__
:
831 source
= self
.modules
[modID
][1]
832 #description = self.modules[modID][3]
833 description
= self
.modules
[modID
][2]
836 self
.modules
[modID
][0] = {}
837 code
= compile(source
, description
, "exec")
838 exec code
in self
.modules
[modID
][0]
840 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
841 self
.modules
[modID
][0] = None
843 self
.modules
[modID
][4] = None
846 def SetActive(self
, modID
):
847 if modID
!= modOriginal
and modID
!= modModified
:
850 self
.modActive
= modID
854 dict = self
.modules
[self
.modActive
][0]
858 return ModuleDictWrapper(dict)
861 def GetActiveID(self
):
862 return self
.modActive
865 def GetSource(self
, modID
= None):
867 modID
= self
.modActive
868 return self
.modules
[modID
][1]
871 def GetFilename(self
, modID
= None):
873 modID
= self
.modActive
874 return self
.modules
[self
.modActive
][2]
877 def GetErrorInfo(self
, modID
= None):
879 modID
= self
.modActive
880 return self
.modules
[self
.modActive
][4]
883 def Exists(self
, modID
):
884 return self
.modules
[modID
][1] != ""
887 def UpdateFile(self
, modID
= None):
888 """Updates the file from which a module was loaded
889 with (possibly updated) source"""
891 modID
= self
.modActive
893 source
= self
.modules
[modID
][1]
894 filename
= self
.modules
[modID
][2]
897 file = open(filename
, "wt")
903 def Delete(self
, modID
):
904 if self
.modActive
== modID
:
907 self
.modules
[modID
][0] = None
908 self
.modules
[modID
][1] = ""
909 self
.modules
[modID
][2] = ""
912 #---------------------------------------------------------------------------
915 """Wraps and stores information about the current exception"""
916 def __init__(self
, exc_info
):
919 excType
, excValue
= exc_info
[:2]
920 # traceback list entries: (filename, line number, function name, text)
921 self
.traceback
= traceback
.extract_tb(exc_info
[2])
923 # --Based on traceback.py::format_exception_only()--
924 if type(excType
) == types
.ClassType
:
925 self
.exception_type
= excType
.__name
__
927 self
.exception_type
= excType
929 # If it's a syntax error, extra information needs
930 # to be added to the traceback
931 if excType
is SyntaxError:
933 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
938 filename
= "<string>"
940 self
.traceback
.append( (filename
, lineno
, "", line
) )
943 self
.exception_details
= str(excValue
)
945 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
952 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
955 #---------------------------------------------------------------------------
957 class DemoErrorPanel(wx
.Panel
):
958 """Panel put into the demo tab when the demo fails to run due to errors"""
960 def __init__(self
, parent
, codePanel
, demoError
, log
):
961 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
962 self
.codePanel
= codePanel
966 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
969 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
970 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
972 # Exception Information
973 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
974 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
975 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
976 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
977 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
978 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
979 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
980 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
981 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
982 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
984 # Set up the traceback list
985 # This one automatically resizes last column to take up remaining space
986 from ListCtrl
import TestListCtrl
987 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
988 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
989 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
990 self
.list.InsertColumn(0, "Filename")
991 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
992 self
.list.InsertColumn(2, "Function")
993 self
.list.InsertColumn(3, "Code")
994 self
.InsertTraceback(self
.list, demoError
.traceback
)
995 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
996 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
997 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
998 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
999 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
1000 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
1001 + "Double-click on them to go to the offending line")
1002 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
1005 self
.SetSizer(self
.box
)
1008 def InsertTraceback(self
, list, traceback
):
1009 #Add the traceback data
1010 for x
in range(len(traceback
)):
1012 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1013 list.SetStringItem(x
, 1, str(data
[1])) # Line
1014 list.SetStringItem(x
, 2, str(data
[2])) # Function
1015 list.SetStringItem(x
, 3, str(data
[3])) # Code
1017 # Check whether this entry is from the demo module
1018 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1019 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1020 # Give it a blue colour
1021 item
= self
.list.GetItem(x
)
1022 item
.SetTextColour(wx
.BLUE
)
1023 self
.list.SetItem(item
)
1025 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1028 def OnItemSelected(self
, event
):
1029 # This occurs before OnDoubleClick and can be used to set the
1030 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1031 self
.currentItem
= event
.m_itemIndex
1035 def OnDoubleClick(self
, event
):
1036 # If double-clicking on a demo's entry, jump to the line number
1037 line
= self
.list.GetItemData(self
.currentItem
)
1039 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1040 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1044 #---------------------------------------------------------------------------
1046 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1047 TBMENU_RESTORE
= wx
.NewId()
1048 TBMENU_CLOSE
= wx
.NewId()
1049 TBMENU_CHANGE
= wx
.NewId()
1050 TBMENU_REMOVE
= wx
.NewId()
1052 def __init__(self
, frame
):
1053 wx
.TaskBarIcon
.__init
__(self
)
1057 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1058 self
.SetIcon(icon
, "wxPython Demo")
1062 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1063 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1064 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1065 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1066 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1069 def CreatePopupMenu(self
):
1071 This method is called by the base class when it needs to popup
1072 the menu for the default EVT_RIGHT_DOWN event. Just create
1073 the menu how you want it and return it from this function,
1074 the base class takes care of the rest.
1077 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1078 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1079 menu
.AppendSeparator()
1080 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1081 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1085 def MakeIcon(self
, img
):
1087 The various platforms have different requirements for the
1090 if "wxMSW" in wx
.PlatformInfo
:
1091 img
= img
.Scale(16, 16)
1092 elif "wxGTK" in wx
.PlatformInfo
:
1093 img
= img
.Scale(22, 22)
1094 # wxMac can be any size upto 128x128, so leave the source img alone....
1095 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1099 def OnTaskBarActivate(self
, evt
):
1100 if self
.frame
.IsIconized():
1101 self
.frame
.Iconize(False)
1102 if not self
.frame
.IsShown():
1103 self
.frame
.Show(True)
1107 def OnTaskBarClose(self
, evt
):
1111 def OnTaskBarChange(self
, evt
):
1112 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1113 name
= names
[self
.imgidx
]
1115 getFunc
= getattr(images
, "get%sImage" % name
)
1117 if self
.imgidx
>= len(names
):
1120 icon
= self
.MakeIcon(getFunc())
1121 self
.SetIcon(icon
, "This is a new icon: " + name
)
1124 def OnTaskBarRemove(self
, evt
):
1128 #---------------------------------------------------------------------------
1129 class wxPythonDemo(wx
.Frame
):
1130 overviewText
= "wxPython Overview"
1132 def __init__(self
, parent
, title
):
1133 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1134 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1136 self
.SetMinSize((640,480))
1139 self
.cwd
= os
.getcwd()
1140 self
.curOverview
= ""
1141 self
.demoPage
= None
1142 self
.codePage
= None
1144 self
.firstTime
= True
1147 icon
= images
.getWXPdemoIcon()
1151 self
.tbicon
= DemoTaskBarIcon(self
)
1155 wx
.CallAfter(self
.ShowTip
)
1157 self
.otherWin
= None
1158 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1159 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1160 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1161 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1163 self
.Centre(wx
.BOTH
)
1164 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1166 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1167 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1169 def EmptyHandler(evt
): pass
1170 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1171 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1173 # Prevent TreeCtrl from displaying all items after destruction when True
1177 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1180 self
.mainmenu
= wx
.MenuBar()
1182 item
= menu
.Append(-1, '&Redirect Output',
1183 'Redirect print statements to a window',
1185 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1187 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1188 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1189 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1190 self
.mainmenu
.Append(menu
, '&File')
1194 for item
in _treeList
:
1196 for childItem
in item
[1]:
1197 mi
= submenu
.Append(-1, childItem
)
1198 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1199 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1200 self
.mainmenu
.Append(menu
, '&Demo')
1205 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1206 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1207 menu
.AppendSeparator()
1209 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1210 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1211 menu
.AppendSeparator()
1212 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1213 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1215 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1216 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1217 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1218 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1219 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1220 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1221 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1222 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1223 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1224 self
.mainmenu
.Append(menu
, '&Help')
1225 self
.SetMenuBar(self
.mainmenu
)
1227 self
.finddata
= wx
.FindReplaceData()
1228 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1231 # This is another way to set Accelerators, in addition to
1232 # using the '\t<key>' syntax in the menu items.
1233 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1234 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1235 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1236 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1238 self
.SetAcceleratorTable(aTable
)
1244 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1245 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1248 root
= self
.tree
.AddRoot("wxPython Overview")
1250 for item
in _treeList
:
1251 child
= self
.tree
.AppendItem(root
, item
[0])
1252 if not firstChild
: firstChild
= child
1253 for childItem
in item
[1]:
1254 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1255 self
.treeMap
[childItem
] = theDemo
1257 self
.tree
.Expand(root
)
1258 self
.tree
.Expand(firstChild
)
1259 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1260 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1261 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1262 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1264 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1265 # we put it in a panel first because there seems to be a
1266 # refresh bug of some sort (wxGTK) when it is directly in
1269 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1270 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1272 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1273 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1274 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1275 self
.nb
.AddPage(panel
, self
.overviewText
)
1277 def OnOvrSize(evt
, ovr
=self
.ovr
):
1278 ovr
.SetSize(evt
.GetSize())
1279 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1280 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1282 if "gtk2" in wx
.PlatformInfo
:
1283 self
.ovr
.SetStandardFonts()
1284 self
.SetOverview(self
.overviewText
, mainOverview
)
1287 # Set up a log window
1288 self
.log
= wx
.TextCtrl(splitter2
, -1,
1289 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1291 # Set the wxWindows log target to be this textctrl
1292 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1294 # But instead of the above we want to show how to use our own wx.Log class
1295 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1297 # for serious debugging
1298 #wx.Log_SetActiveTarget(wx.LogStderr())
1299 #wx.Log_SetTraceMask(wx.TraceMessages)
1302 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1303 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1305 # add the windows to the splitter and split it.
1306 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1307 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1309 splitter
.SetMinimumPaneSize(120)
1310 splitter2
.SetMinimumPaneSize(60)
1312 # Make the splitter on the right expand the top window when resized
1313 def SplitterOnSize(evt
):
1314 splitter
= evt
.GetEventObject()
1315 sz
= splitter
.GetSize()
1316 splitter
.SetSashPosition(sz
.height
- 160, False)
1319 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1321 # select initial items
1322 self
.nb
.SetSelection(0)
1323 self
.tree
.SelectItem(root
)
1325 # Load 'Main' module
1326 self
.LoadDemo(self
.overviewText
)
1329 # select some other initial module?
1330 if len(sys
.argv
) > 1:
1332 if arg
.endswith('.py'):
1334 selectedDemo
= self
.treeMap
.get(arg
, None)
1336 self
.tree
.SelectItem(selectedDemo
)
1337 self
.tree
.EnsureVisible(selectedDemo
)
1340 #---------------------------------------------
1341 def WriteText(self
, text
):
1342 if text
[-1:] == '\n':
1346 def write(self
, txt
):
1349 #---------------------------------------------
1350 def OnItemExpanded(self
, event
):
1351 item
= event
.GetItem()
1352 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1355 #---------------------------------------------
1356 def OnItemCollapsed(self
, event
):
1357 item
= event
.GetItem()
1358 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1361 #---------------------------------------------
1362 def OnTreeLeftDown(self
, event
):
1363 # reset the overview text if the tree item is clicked on again
1364 pt
= event
.GetPosition();
1365 item
, flags
= self
.tree
.HitTest(pt
)
1366 if item
== self
.tree
.GetSelection():
1367 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1370 #---------------------------------------------
1371 def OnSelChanged(self
, event
):
1372 if self
.dying
or not self
.loaded
:
1375 item
= event
.GetItem()
1376 itemText
= self
.tree
.GetItemText(item
)
1377 self
.LoadDemo(itemText
)
1379 #---------------------------------------------
1380 def LoadDemo(self
, demoName
):
1382 wx
.BeginBusyCursor()
1385 self
.ShutdownDemoModule()
1387 if demoName
== self
.overviewText
:
1388 # User selected the "wxPython Overview" node
1390 # Changing the main window at runtime not yet supported...
1391 self
.demoModules
= DemoModules(__name__
)
1392 self
.SetOverview(self
.overviewText
, mainOverview
)
1393 self
.LoadDemoSource()
1394 self
.UpdateNotebook(0)
1396 if os
.path
.exists(GetOriginalFilename(demoName
)):
1397 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1398 self
.demoModules
= DemoModules(demoName
)
1399 self
.LoadDemoSource()
1402 self
.SetOverview("wxPython", mainOverview
)
1403 self
.codePage
= None
1404 self
.UpdateNotebook(0)
1408 #---------------------------------------------
1409 def LoadDemoSource(self
):
1410 self
.codePage
= None
1411 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1412 self
.codePage
.LoadDemo(self
.demoModules
)
1414 #---------------------------------------------
1415 def RunModule(self
):
1416 """Runs the active module"""
1418 module
= self
.demoModules
.GetActive()
1419 self
.ShutdownDemoModule()
1422 # o The RunTest() for all samples must now return a window that can
1423 # be palced in a tab in the main notebook.
1424 # o If an error occurs (or has occurred before) an error tab is created.
1426 if module
is not None:
1427 wx
.LogMessage("Running demo module...")
1428 if hasattr(module
, "overview"):
1429 overviewText
= module
.overview
1432 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1434 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1435 DemoError(sys
.exc_info()), self
)
1437 assert self
.demoPage
is not None, "runTest must return a window!"
1440 # There was a previous error in compiling or exec-ing
1441 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1442 self
.demoModules
.GetErrorInfo(), self
)
1444 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1447 # cahnge to the demo page the first time a module is run
1448 self
.UpdateNotebook(2)
1449 self
.firstTime
= False
1451 # otherwise just stay on the same tab in case the user has changed to another one
1452 self
.UpdateNotebook()
1454 #---------------------------------------------
1455 def ShutdownDemoModule(self
):
1457 # inform the window that it's time to quit if it cares
1458 if hasattr(self
.demoPage
, "ShutdownDemo"):
1459 self
.demoPage
.ShutdownDemo()
1460 wx
.YieldIfNeeded() # in case the page has pending events
1461 self
.demoPage
= None
1463 #---------------------------------------------
1464 def UpdateNotebook(self
, select
= -1):
1468 def UpdatePage(page
, pageText
):
1471 for i
in range(nb
.GetPageCount()):
1472 if nb
.GetPageText(i
) == pageText
:
1480 nb
.AddPage(page
, pageText
)
1481 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1483 if nb
.GetPage(pagePos
) != page
:
1484 # Reload an existing page
1486 nb
.DeletePage(pagePos
)
1487 nb
.InsertPage(pagePos
, page
, pageText
)
1489 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1491 # Excellent! No redraw/flicker
1492 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1495 nb
.DeletePage(pagePos
)
1496 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1498 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1501 select
= nb
.GetSelection()
1503 UpdatePage(self
.codePage
, "Demo Code")
1504 UpdatePage(self
.demoPage
, "Demo")
1506 if select
>= 0 and select
< nb
.GetPageCount():
1507 nb
.SetSelection(select
)
1509 #---------------------------------------------
1510 def SetOverview(self
, name
, text
):
1511 self
.curOverview
= text
1513 if lead
!= '<html>' and lead
!= '<HTML>':
1514 text
= '<br>'.join(text
.split('\n'))
1516 text
= text
.decode('iso8859_1')
1517 self
.ovr
.SetPage(text
)
1518 self
.nb
.SetPageText(0, name
)
1520 #---------------------------------------------
1522 def OnFileExit(self
, *event
):
1525 def OnToggleRedirect(self
, event
):
1529 print "Print statements and other standard output will now be directed to this window."
1532 print "Print statements and other standard output will now be sent to the usual location."
1534 def OnHelpAbout(self
, event
):
1535 from About
import MyAboutBox
1536 about
= MyAboutBox(self
)
1540 def OnHelpFind(self
, event
):
1541 if self
.finddlg
!= None:
1544 self
.nb
.SetSelection(1)
1545 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1546 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1547 self
.finddlg
.Show(True)
1550 def OnUpdateFindItems(self
, evt
):
1551 evt
.Enable(self
.finddlg
== None)
1554 def OnFind(self
, event
):
1555 editor
= self
.codePage
.editor
1556 self
.nb
.SetSelection(1)
1557 end
= editor
.GetLastPosition()
1558 textstring
= editor
.GetRange(0, end
).lower()
1559 findstring
= self
.finddata
.GetFindString().lower()
1560 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1562 start
= editor
.GetSelection()[0]
1563 loc
= textstring
.rfind(findstring
, 0, start
)
1565 start
= editor
.GetSelection()[1]
1566 loc
= textstring
.find(findstring
, start
)
1567 if loc
== -1 and start
!= 0:
1568 # string not found, start at beginning
1571 loc
= textstring
.rfind(findstring
, 0, start
)
1574 loc
= textstring
.find(findstring
, start
)
1576 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1577 'Find String Not Found in Demo File',
1578 wx
.OK | wx
.ICON_INFORMATION
)
1583 self
.finddlg
.SetFocus()
1586 self
.finddlg
.Destroy()
1588 editor
.ShowPosition(loc
)
1589 editor
.SetSelection(loc
, loc
+ len(findstring
))
1593 def OnFindNext(self
, event
):
1594 if self
.finddata
.GetFindString():
1597 self
.OnHelpFind(event
)
1599 def OnFindClose(self
, event
):
1600 event
.GetDialog().Destroy()
1604 def OnOpenShellWindow(self
, evt
):
1606 # if it already exists then just make sure it's visible
1612 # Make a PyShell window
1614 namespace
= { 'wx' : wx
,
1615 'app' : wx
.GetApp(),
1618 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1619 self
.shell
.SetSize((640,480))
1622 # Hook the close event of the main frame window so that we
1623 # close the shell at the same time if it still exists
1624 def CloseShell(evt
):
1628 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1631 #---------------------------------------------
1632 def OnCloseWindow(self
, event
):
1634 self
.demoPage
= None
1635 self
.codePage
= None
1636 self
.mainmenu
= None
1637 if self
.tbicon
is not None:
1638 self
.tbicon
.Destroy()
1642 #---------------------------------------------
1643 def OnIdle(self
, event
):
1645 self
.otherWin
.Raise()
1646 self
.demoPage
= self
.otherWin
1647 self
.otherWin
= None
1650 #---------------------------------------------
1653 showTipText
= open(opj("data/showTips")).read()
1654 showTip
, index
= eval(showTipText
)
1656 showTip
, index
= (1, 0)
1658 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1660 showTip
= wx
.ShowTip(self
, tp
)
1661 index
= tp
.GetCurrentTip()
1662 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1665 #---------------------------------------------
1666 def OnDemoMenu(self
, event
):
1668 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1672 self
.tree
.SelectItem(selectedDemo
)
1673 self
.tree
.EnsureVisible(selectedDemo
)
1677 #---------------------------------------------
1678 def OnIconfiy(self
, evt
):
1679 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1682 #---------------------------------------------
1683 def OnMaximize(self
, evt
):
1684 wx
.LogMessage("OnMaximize")
1687 #---------------------------------------------
1688 def OnActivate(self
, evt
):
1689 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1692 #---------------------------------------------
1693 def OnAppActivate(self
, evt
):
1694 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1697 #---------------------------------------------------------------------------
1698 #---------------------------------------------------------------------------
1700 class MySplashScreen(wx
.SplashScreen
):
1702 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1703 wx
.SplashScreen
.__init
__(self
, bmp
,
1704 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1706 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1707 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1710 def OnClose(self
, evt
):
1711 # Make sure the default handler runs too so this window gets
1716 # if the timer is still running then go ahead and show the
1718 if self
.fc
.IsRunning():
1724 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1726 if self
.fc
.IsRunning():
1730 class MyApp(wx
.App
):
1733 Create and show the splash screen. It will then create and show
1734 the main frame when it is time to do so.
1737 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1740 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1742 # Normally when using a SplashScreen you would create it, show
1743 # it and then continue on with the applicaiton's
1744 # initialization, finally creating and showing the main
1745 # application window(s). In this case we have nothing else to
1746 # do so we'll delay showing the main frame until later (see
1747 # ShowMain above) so the users can see the SplashScreen effect.
1748 splash
= MySplashScreen()
1755 #---------------------------------------------------------------------------
1759 demoPath
= os
.path
.dirname(__file__
)
1766 #---------------------------------------------------------------------------
1769 mainOverview
= """<html><body>
1772 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1773 language. It allows Python programmers to create programs with a
1774 robust, highly functional graphical user interface, simply and easily.
1775 It is implemented as a Python extension module (native code) that
1776 wraps the popular wxWindows cross platform GUI library, which is
1779 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1780 means that it is free for anyone to use and the source code is
1781 available for anyone to look at and modify. Or anyone can contribute
1782 fixes or enhancements to the project.
1784 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1785 same program will run on multiple platforms without modification.
1786 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1787 or unix-like systems, and Macintosh OS X. Since the language is
1788 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1791 <p> <b>This demo</b> is not only a collection of test cases for
1792 wxPython, but is also designed to help you learn about and how to use
1793 wxPython. Each sample is listed in the tree control on the left.
1794 When a sample is selected in the tree then a module is loaded and run
1795 (usually in a tab of this notebook,) and the source code of the module
1796 is loaded in another tab for you to browse and learn from.
1801 #----------------------------------------------------------------------------
1802 #----------------------------------------------------------------------------
1804 if __name__
== '__main__':
1808 #----------------------------------------------------------------------------