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',
74 # managed windows == things with a (optional) caption you can close
75 ('Frames and Dialogs', [
76 'AUI_DockingWindowMgr',
101 # dialogs from libraries
104 'ScrolledMessageDialog',
108 ('Core Windows/Controls', [
145 ('"Book" Controls', [
154 ('Custom Controls', [
171 # controls coming from other libraries
172 ('More Windows/Controls', [
173 'ActiveX_FlashWindow',
174 'ActiveX_IEHtmlWindow',
176 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
179 'CheckListCtrlMixin',
194 'MaskedEditControls',
197 'MultiSplitterWindow',
214 # How to lay out the controls in a frame/dialog
224 'XmlResourceHandler',
225 'XmlResourceSubclass',
229 ('Process and Events', [
237 ##'infoframe', # needs better explanation and some fixing
241 ('Clipboard and DnD', [
267 ##'DialogUnits', # needs more explanations
287 ('Check out the samples dir too', [
294 #---------------------------------------------------------------------------
295 # Show how to derive a custom wxLog class
297 class MyLog(wx
.PyLog
):
298 def __init__(self
, textCtrl
, logTime
=0):
299 wx
.PyLog
.__init
__(self
)
301 self
.logTime
= logTime
303 def DoLogString(self
, message
, timeStamp
):
304 #print message, timeStamp
306 # message = time.strftime("%X", time.localtime(timeStamp)) + \
309 self
.tc
.AppendText(message
+ '\n')
312 class MyTP(wx
.PyTipProvider
):
314 return "This is my tip"
316 #---------------------------------------------------------------------------
317 # A class to be used to simply display a message in the demo pane
318 # rather than running the sample itself.
320 class MessagePanel(wx
.Panel
):
321 def __init__(self
, parent
, message
, caption
='', flags
=0):
322 wx
.Panel
.__init
__(self
, parent
)
327 if flags
& wx
.ICON_EXCLAMATION
:
328 artid
= wx
.ART_WARNING
329 elif flags
& wx
.ICON_ERROR
:
331 elif flags
& wx
.ICON_QUESTION
:
332 artid
= wx
.ART_QUESTION
333 elif flags
& wx
.ICON_INFORMATION
:
334 artid
= wx
.ART_INFORMATION
336 if artid
is not None:
337 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
338 icon
= wx
.StaticBitmap(self
, -1, bmp
)
340 icon
= (32,32) # make a spacer instead
343 caption
= wx
.StaticText(self
, -1, caption
)
344 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
346 message
= wx
.StaticText(self
, -1, message
)
348 # add to sizers for layout
349 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
355 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
362 box
= wx
.BoxSizer(wx
.VERTICAL
)
364 box
.Add(hbox
, 0, wx
.EXPAND
)
371 #---------------------------------------------------------------------------
372 # A class to be used to display source code in the demo. Try using the
373 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
374 # if there is an error, such as the stc module not being present.
378 ##raise ImportError # for testing the alternate implementation
380 from StyledTextCtrl_2
import PythonSTC
382 class DemoCodeEditor(PythonSTC
):
383 def __init__(self
, parent
):
384 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
387 # Some methods to make it compatible with how the wxTextCtrl is used
388 def SetValue(self
, value
):
390 value
= value
.decode('iso8859_1')
392 self
.EmptyUndoBuffer()
395 def IsModified(self
):
396 return self
.GetModify()
401 def SetInsertionPoint(self
, pos
):
402 self
.SetCurrentPos(pos
)
405 def ShowPosition(self
, pos
):
406 line
= self
.LineFromPosition(pos
)
407 #self.EnsureVisible(line)
410 def GetLastPosition(self
):
411 return self
.GetLength()
413 def GetPositionFromLine(self
, line
):
414 return self
.PositionFromLine(line
)
416 def GetRange(self
, start
, end
):
417 return self
.GetTextRange(start
, end
)
419 def GetSelection(self
):
420 return self
.GetAnchor(), self
.GetCurrentPos()
422 def SetSelection(self
, start
, end
):
423 self
.SetSelectionStart(start
)
424 self
.SetSelectionEnd(end
)
426 def SelectLine(self
, line
):
427 start
= self
.PositionFromLine(line
)
428 end
= self
.GetLineEndPosition(line
)
429 self
.SetSelection(start
, end
)
431 def SetUpEditor(self
):
433 This method carries out the work of setting up the demo editor.
434 It's seperate so as not to clutter up the init code.
438 self
.SetLexer(stc
.STC_LEX_PYTHON
)
439 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
442 self
.SetProperty("fold", "1" )
444 # Highlight tab/space mixing (shouldn't be any)
445 self
.SetProperty("tab.timmy.whinge.level", "1")
447 # Set left and right margins
450 # Set up the numbers in the margin for margin #1
451 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
452 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
453 self
.SetMarginWidth(1, 40)
455 # Indentation and tab stuff
456 self
.SetIndent(4) # Proscribed indent size for wx
457 self
.SetIndentationGuides(True) # Show indent guides
458 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
459 self
.SetTabIndents(True) # Tab key indents
460 self
.SetTabWidth(4) # Proscribed tab size for wx
461 self
.SetUseTabs(False) # Use spaces rather than tabs, or
462 # TabTimmy will complain!
464 self
.SetViewWhiteSpace(False) # Don't view white space
466 # EOL: Since we are loading/saving ourselves, and the
467 # strings will always have \n's in them, set the STC to
468 # edit them that way.
469 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
470 self
.SetViewEOL(False)
472 # No right-edge mode indicator
473 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
475 # Setup a margin to hold fold markers
476 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
477 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
478 self
.SetMarginSensitive(2, True)
479 self
.SetMarginWidth(2, 12)
481 # and now set up the fold markers
482 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
483 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
484 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
485 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
486 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
487 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
488 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
490 # Global default style
491 if wx
.Platform
== '__WXMSW__':
492 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
493 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
494 elif wx
.Platform
== '__WXMAC__':
495 # TODO: if this looks fine on Linux too, remove the Mac-specific case
496 # and use this whenever OS != MSW.
497 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
498 'fore:#000000,back:#FFFFFF,face:Courier')
500 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
501 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
503 # Clear styles and revert to default.
506 # Following style specs only indicate differences from default.
507 # The rest remains unchanged.
509 # Line numbers in margin
510 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
512 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
514 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
516 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
519 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
521 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
522 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
524 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
525 # Strings and characters
526 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
527 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
529 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
531 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
532 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
534 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
536 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
538 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
539 # Identifiers. I leave this as not bold because everything seems
540 # to be an identifier if it doesn't match the above criterae
541 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
544 self
.SetCaretForeground("BLUE")
545 # Selection background
546 self
.SetSelBackground(1, '#66CCFF')
548 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
549 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
551 def RegisterModifiedEvent(self
, eventHandler
):
552 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
556 class DemoCodeEditor(wx
.TextCtrl
):
557 def __init__(self
, parent
):
558 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
559 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
561 def RegisterModifiedEvent(self
, eventHandler
):
562 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
564 def SetReadOnly(self
, flag
):
565 self
.SetEditable(not flag
)
566 # NOTE: STC already has this method
569 return self
.GetValue()
571 def GetPositionFromLine(self
, line
):
572 return self
.XYToPosition(0,line
)
574 def GotoLine(self
, line
):
575 pos
= self
.GetPositionFromLine(line
)
576 self
.SetInsertionPoint(pos
)
577 self
.ShowPosition(pos
)
579 def SelectLine(self
, line
):
580 start
= self
.GetPositionFromLine(line
)
581 end
= start
+ self
.GetLineLength(line
)
582 self
.SetSelection(start
, end
)
585 #---------------------------------------------------------------------------
586 # Constants for module versions
590 modDefault
= modOriginal
592 #---------------------------------------------------------------------------
594 class DemoCodePanel(wx
.Panel
):
595 """Panel for the 'Demo Code' tab"""
596 def __init__(self
, parent
, mainFrame
):
597 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
598 if 'wxMSW' in wx
.PlatformInfo
:
600 self
.mainFrame
= mainFrame
601 self
.editor
= DemoCodeEditor(self
)
602 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
604 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
605 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
606 self
.btnSave
.Enable(False)
607 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
608 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
610 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
611 modModified
: wx
.RadioButton(self
, -1, "Modified") }
613 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
614 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
615 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
616 for modID
, radioButton
in self
.radioButtons
.items():
617 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
618 radioButton
.modID
= modID
# makes it easier for the event handler
619 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
621 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
622 self
.controlBox
.Add(self
.btnRestore
, 0)
624 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
625 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
626 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
627 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
630 self
.SetSizer(self
.box
)
633 # Loads a demo from a DemoModules object
634 def LoadDemo(self
, demoModules
):
635 self
.demoModules
= demoModules
636 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
637 demoModules
.SetActive(modModified
)
639 demoModules
.SetActive(modOriginal
)
640 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
641 self
.ActiveModuleChanged()
644 def ActiveModuleChanged(self
):
645 self
.LoadDemoSource(self
.demoModules
.GetSource())
646 self
.UpdateControlState()
650 def LoadDemoSource(self
, source
):
652 self
.editor
.SetValue(source
)
654 self
.btnSave
.Enable(False)
657 def JumpToLine(self
, line
, highlight
=False):
658 self
.editor
.GotoLine(line
)
659 self
.editor
.SetFocus()
661 self
.editor
.SelectLine(line
)
664 def UpdateControlState(self
):
665 active
= self
.demoModules
.GetActiveID()
666 # Update the radio/restore buttons
667 for moduleID
in self
.radioButtons
:
668 btn
= self
.radioButtons
[moduleID
]
669 if moduleID
== active
:
674 if self
.demoModules
.Exists(moduleID
):
676 if moduleID
== modModified
:
677 self
.btnRestore
.Enable(True)
680 if moduleID
== modModified
:
681 self
.btnRestore
.Enable(False)
684 def OnRadioButton(self
, event
):
685 radioSelected
= event
.GetEventObject()
686 modSelected
= radioSelected
.modID
687 if modSelected
!= self
.demoModules
.GetActiveID():
688 busy
= wx
.BusyInfo("Reloading demo module...")
689 self
.demoModules
.SetActive(modSelected
)
690 self
.ActiveModuleChanged()
693 def ReloadDemo(self
):
694 if self
.demoModules
.name
!= __name__
:
695 self
.mainFrame
.RunModule()
698 def OnCodeModified(self
, event
):
699 self
.btnSave
.Enable(self
.editor
.IsModified())
702 def OnSave(self
, event
):
703 if self
.demoModules
.Exists(modModified
):
704 if self
.demoModules
.GetActiveID() == modOriginal
:
705 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
706 "Do you want to continue?"
707 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
708 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
709 result
= dlg
.ShowModal()
710 if result
== wx
.ID_NO
:
714 self
.demoModules
.SetActive(modModified
)
715 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
717 # Create the demo directory if one doesn't already exist
718 if not os
.path
.exists(GetModifiedDirectory()):
720 os
.makedirs(GetModifiedDirectory())
721 if not os
.path
.exists(GetModifiedDirectory()):
722 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
725 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
728 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
731 f
= open(modifiedFilename
, "wt")
732 source
= self
.editor
.GetText()
738 busy
= wx
.BusyInfo("Reloading demo module...")
739 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
740 self
.ActiveModuleChanged()
743 def OnRestore(self
, event
): # Handles the "Delete Modified" button
744 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
745 self
.demoModules
.Delete(modModified
)
746 os
.unlink(modifiedFilename
) # Delete the modified copy
747 busy
= wx
.BusyInfo("Reloading demo module...")
748 self
.ActiveModuleChanged()
751 #---------------------------------------------------------------------------
754 """Convert paths to the platform-specific separator"""
755 str = apply(os
.path
.join
, tuple(path
.split('/')))
756 # HACK: on Linux, a leading / gets lost...
757 if path
.startswith('/'):
762 def GetModifiedDirectory():
764 Returns the directory where modified versions of the demo files
767 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
770 def GetModifiedFilename(name
):
772 Returns the filename of the modified version of the specified demo
774 if not name
.endswith(".py"):
776 return GetModifiedDirectory() + name
779 def GetOriginalFilename(name
):
781 Returns the filename of the original version of the specified demo
783 if not name
.endswith(".py"):
788 def DoesModifiedExist(name
):
789 """Returns whether the specified demo has a modified copy"""
790 if os
.path
.exists(GetModifiedFilename(name
)):
796 #---------------------------------------------------------------------------
798 class ModuleDictWrapper
:
799 """Emulates a module with a dynamically compiled __dict__"""
800 def __init__(self
, dict):
803 def __getattr__(self
, name
):
804 if name
in self
.dict:
805 return self
.dict[name
]
811 Dynamically manages the original/modified versions of a demo
814 def __init__(self
, name
):
818 # (dict , source , filename , description , error information )
819 # ( 0 , 1 , 2 , 3 , 4 )
820 self
.modules
= [[None, "" , "" , "<original>" , None],
821 [None, "" , "" , "<modified>" , None]]
823 # load original module
824 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
825 self
.SetActive(modOriginal
)
827 # load modified module (if one exists)
828 if DoesModifiedExist(name
):
829 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
832 def LoadFromFile(self
, modID
, filename
):
833 self
.modules
[modID
][2] = filename
834 file = open(filename
, "rt")
835 self
.LoadFromSource(modID
, file.read())
839 def LoadFromSource(self
, modID
, source
):
840 self
.modules
[modID
][1] = source
844 def LoadDict(self
, modID
):
845 if self
.name
!= __name__
:
846 source
= self
.modules
[modID
][1]
847 #description = self.modules[modID][3]
848 description
= self
.modules
[modID
][2]
851 self
.modules
[modID
][0] = {}
852 code
= compile(source
, description
, "exec")
853 exec code
in self
.modules
[modID
][0]
855 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
856 self
.modules
[modID
][0] = None
858 self
.modules
[modID
][4] = None
861 def SetActive(self
, modID
):
862 if modID
!= modOriginal
and modID
!= modModified
:
865 self
.modActive
= modID
869 dict = self
.modules
[self
.modActive
][0]
873 return ModuleDictWrapper(dict)
876 def GetActiveID(self
):
877 return self
.modActive
880 def GetSource(self
, modID
= None):
882 modID
= self
.modActive
883 return self
.modules
[modID
][1]
886 def GetFilename(self
, modID
= None):
888 modID
= self
.modActive
889 return self
.modules
[self
.modActive
][2]
892 def GetErrorInfo(self
, modID
= None):
894 modID
= self
.modActive
895 return self
.modules
[self
.modActive
][4]
898 def Exists(self
, modID
):
899 return self
.modules
[modID
][1] != ""
902 def UpdateFile(self
, modID
= None):
903 """Updates the file from which a module was loaded
904 with (possibly updated) source"""
906 modID
= self
.modActive
908 source
= self
.modules
[modID
][1]
909 filename
= self
.modules
[modID
][2]
912 file = open(filename
, "wt")
918 def Delete(self
, modID
):
919 if self
.modActive
== modID
:
922 self
.modules
[modID
][0] = None
923 self
.modules
[modID
][1] = ""
924 self
.modules
[modID
][2] = ""
927 #---------------------------------------------------------------------------
930 """Wraps and stores information about the current exception"""
931 def __init__(self
, exc_info
):
934 excType
, excValue
= exc_info
[:2]
935 # traceback list entries: (filename, line number, function name, text)
936 self
.traceback
= traceback
.extract_tb(exc_info
[2])
938 # --Based on traceback.py::format_exception_only()--
939 if type(excType
) == types
.ClassType
:
940 self
.exception_type
= excType
.__name
__
942 self
.exception_type
= excType
944 # If it's a syntax error, extra information needs
945 # to be added to the traceback
946 if excType
is SyntaxError:
948 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
953 filename
= "<string>"
955 self
.traceback
.append( (filename
, lineno
, "", line
) )
958 self
.exception_details
= str(excValue
)
960 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
967 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
970 #---------------------------------------------------------------------------
972 class DemoErrorPanel(wx
.Panel
):
973 """Panel put into the demo tab when the demo fails to run due to errors"""
975 def __init__(self
, parent
, codePanel
, demoError
, log
):
976 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
977 self
.codePanel
= codePanel
981 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
984 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
985 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
987 # Exception Information
988 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
989 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
990 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
991 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
992 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
993 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
994 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
995 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
996 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
997 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
999 # Set up the traceback list
1000 # This one automatically resizes last column to take up remaining space
1001 from ListCtrl
import TestListCtrl
1002 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
1003 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
1004 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
1005 self
.list.InsertColumn(0, "Filename")
1006 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
1007 self
.list.InsertColumn(2, "Function")
1008 self
.list.InsertColumn(3, "Code")
1009 self
.InsertTraceback(self
.list, demoError
.traceback
)
1010 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
1011 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
1012 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
1013 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
1014 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
1015 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
1016 + "Double-click on them to go to the offending line")
1017 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
1020 self
.SetSizer(self
.box
)
1023 def InsertTraceback(self
, list, traceback
):
1024 #Add the traceback data
1025 for x
in range(len(traceback
)):
1027 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1028 list.SetStringItem(x
, 1, str(data
[1])) # Line
1029 list.SetStringItem(x
, 2, str(data
[2])) # Function
1030 list.SetStringItem(x
, 3, str(data
[3])) # Code
1032 # Check whether this entry is from the demo module
1033 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1034 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1035 # Give it a blue colour
1036 item
= self
.list.GetItem(x
)
1037 item
.SetTextColour(wx
.BLUE
)
1038 self
.list.SetItem(item
)
1040 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1043 def OnItemSelected(self
, event
):
1044 # This occurs before OnDoubleClick and can be used to set the
1045 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1046 self
.currentItem
= event
.m_itemIndex
1050 def OnDoubleClick(self
, event
):
1051 # If double-clicking on a demo's entry, jump to the line number
1052 line
= self
.list.GetItemData(self
.currentItem
)
1054 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1055 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1059 #---------------------------------------------------------------------------
1061 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1062 TBMENU_RESTORE
= wx
.NewId()
1063 TBMENU_CLOSE
= wx
.NewId()
1064 TBMENU_CHANGE
= wx
.NewId()
1065 TBMENU_REMOVE
= wx
.NewId()
1067 def __init__(self
, frame
):
1068 wx
.TaskBarIcon
.__init
__(self
)
1072 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1073 self
.SetIcon(icon
, "wxPython Demo")
1077 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1078 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1079 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1080 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1081 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1084 def CreatePopupMenu(self
):
1086 This method is called by the base class when it needs to popup
1087 the menu for the default EVT_RIGHT_DOWN event. Just create
1088 the menu how you want it and return it from this function,
1089 the base class takes care of the rest.
1092 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1093 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1094 menu
.AppendSeparator()
1095 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1096 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1100 def MakeIcon(self
, img
):
1102 The various platforms have different requirements for the
1105 if "wxMSW" in wx
.PlatformInfo
:
1106 img
= img
.Scale(16, 16)
1107 elif "wxGTK" in wx
.PlatformInfo
:
1108 img
= img
.Scale(22, 22)
1109 # wxMac can be any size upto 128x128, so leave the source img alone....
1110 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1114 def OnTaskBarActivate(self
, evt
):
1115 if self
.frame
.IsIconized():
1116 self
.frame
.Iconize(False)
1117 if not self
.frame
.IsShown():
1118 self
.frame
.Show(True)
1122 def OnTaskBarClose(self
, evt
):
1126 def OnTaskBarChange(self
, evt
):
1127 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1128 name
= names
[self
.imgidx
]
1130 getFunc
= getattr(images
, "get%sImage" % name
)
1132 if self
.imgidx
>= len(names
):
1135 icon
= self
.MakeIcon(getFunc())
1136 self
.SetIcon(icon
, "This is a new icon: " + name
)
1139 def OnTaskBarRemove(self
, evt
):
1143 #---------------------------------------------------------------------------
1144 class wxPythonDemo(wx
.Frame
):
1145 overviewText
= "wxPython Overview"
1147 def __init__(self
, parent
, title
):
1148 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1149 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1151 self
.SetMinSize((640,480))
1154 self
.cwd
= os
.getcwd()
1155 self
.curOverview
= ""
1156 self
.demoPage
= None
1157 self
.codePage
= None
1159 self
.firstTime
= True
1162 icon
= images
.getWXPdemoIcon()
1166 self
.tbicon
= DemoTaskBarIcon(self
)
1170 wx
.CallAfter(self
.ShowTip
)
1172 self
.otherWin
= None
1173 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1174 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1175 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1176 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1178 self
.Centre(wx
.BOTH
)
1179 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1181 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1182 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1184 def EmptyHandler(evt
): pass
1185 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1186 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1188 # Prevent TreeCtrl from displaying all items after destruction when True
1192 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1195 self
.mainmenu
= wx
.MenuBar()
1197 item
= menu
.Append(-1, '&Redirect Output',
1198 'Redirect print statements to a window',
1200 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1202 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1203 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1204 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1205 self
.mainmenu
.Append(menu
, '&File')
1209 for item
in _treeList
:
1211 for childItem
in item
[1]:
1212 mi
= submenu
.Append(-1, childItem
)
1213 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1214 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1215 self
.mainmenu
.Append(menu
, '&Demo')
1220 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1221 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1222 menu
.AppendSeparator()
1224 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1225 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1226 menu
.AppendSeparator()
1227 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1228 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1230 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1231 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1232 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1233 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1234 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1235 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1236 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1237 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1238 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1239 self
.mainmenu
.Append(menu
, '&Help')
1240 self
.SetMenuBar(self
.mainmenu
)
1242 self
.finddata
= wx
.FindReplaceData()
1243 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1246 # This is another way to set Accelerators, in addition to
1247 # using the '\t<key>' syntax in the menu items.
1248 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1249 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1250 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1251 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1253 self
.SetAcceleratorTable(aTable
)
1259 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1260 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1263 root
= self
.tree
.AddRoot("wxPython Overview")
1265 for item
in _treeList
:
1266 child
= self
.tree
.AppendItem(root
, item
[0])
1267 if not firstChild
: firstChild
= child
1268 for childItem
in item
[1]:
1269 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1270 self
.treeMap
[childItem
] = theDemo
1272 self
.tree
.Expand(root
)
1273 self
.tree
.Expand(firstChild
)
1274 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1275 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1276 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1277 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1279 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1280 # we put it in a panel first because there seems to be a
1281 # refresh bug of some sort (wxGTK) when it is directly in
1284 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1285 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1287 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1288 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1289 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1290 self
.nb
.AddPage(panel
, self
.overviewText
)
1292 def OnOvrSize(evt
, ovr
=self
.ovr
):
1293 ovr
.SetSize(evt
.GetSize())
1294 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1295 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1297 if "gtk2" in wx
.PlatformInfo
:
1298 self
.ovr
.SetStandardFonts()
1299 self
.SetOverview(self
.overviewText
, mainOverview
)
1302 # Set up a log window
1303 self
.log
= wx
.TextCtrl(splitter2
, -1,
1304 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1306 # Set the wxWindows log target to be this textctrl
1307 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1309 # But instead of the above we want to show how to use our own wx.Log class
1310 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1312 # for serious debugging
1313 #wx.Log_SetActiveTarget(wx.LogStderr())
1314 #wx.Log_SetTraceMask(wx.TraceMessages)
1317 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1318 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1320 # add the windows to the splitter and split it.
1321 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1322 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1324 splitter
.SetMinimumPaneSize(120)
1325 splitter2
.SetMinimumPaneSize(60)
1327 # Make the splitter on the right expand the top window when resized
1328 def SplitterOnSize(evt
):
1329 splitter
= evt
.GetEventObject()
1330 sz
= splitter
.GetSize()
1331 splitter
.SetSashPosition(sz
.height
- 160, False)
1334 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1336 # select initial items
1337 self
.nb
.SetSelection(0)
1338 self
.tree
.SelectItem(root
)
1340 # Load 'Main' module
1341 self
.LoadDemo(self
.overviewText
)
1344 # select some other initial module?
1345 if len(sys
.argv
) > 1:
1347 if arg
.endswith('.py'):
1349 selectedDemo
= self
.treeMap
.get(arg
, None)
1351 self
.tree
.SelectItem(selectedDemo
)
1352 self
.tree
.EnsureVisible(selectedDemo
)
1355 #---------------------------------------------
1356 def WriteText(self
, text
):
1357 if text
[-1:] == '\n':
1361 def write(self
, txt
):
1364 #---------------------------------------------
1365 def OnItemExpanded(self
, event
):
1366 item
= event
.GetItem()
1367 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1370 #---------------------------------------------
1371 def OnItemCollapsed(self
, event
):
1372 item
= event
.GetItem()
1373 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1376 #---------------------------------------------
1377 def OnTreeLeftDown(self
, event
):
1378 # reset the overview text if the tree item is clicked on again
1379 pt
= event
.GetPosition();
1380 item
, flags
= self
.tree
.HitTest(pt
)
1381 if item
== self
.tree
.GetSelection():
1382 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1385 #---------------------------------------------
1386 def OnSelChanged(self
, event
):
1387 if self
.dying
or not self
.loaded
:
1390 item
= event
.GetItem()
1391 itemText
= self
.tree
.GetItemText(item
)
1392 self
.LoadDemo(itemText
)
1394 #---------------------------------------------
1395 def LoadDemo(self
, demoName
):
1397 wx
.BeginBusyCursor()
1400 self
.ShutdownDemoModule()
1402 if demoName
== self
.overviewText
:
1403 # User selected the "wxPython Overview" node
1405 # Changing the main window at runtime not yet supported...
1406 self
.demoModules
= DemoModules(__name__
)
1407 self
.SetOverview(self
.overviewText
, mainOverview
)
1408 self
.LoadDemoSource()
1409 self
.UpdateNotebook(0)
1411 if os
.path
.exists(GetOriginalFilename(demoName
)):
1412 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1413 self
.demoModules
= DemoModules(demoName
)
1414 self
.LoadDemoSource()
1417 self
.SetOverview("wxPython", mainOverview
)
1418 self
.codePage
= None
1419 self
.UpdateNotebook(0)
1423 #---------------------------------------------
1424 def LoadDemoSource(self
):
1425 self
.codePage
= None
1426 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1427 self
.codePage
.LoadDemo(self
.demoModules
)
1429 #---------------------------------------------
1430 def RunModule(self
):
1431 """Runs the active module"""
1433 module
= self
.demoModules
.GetActive()
1434 self
.ShutdownDemoModule()
1437 # o The RunTest() for all samples must now return a window that can
1438 # be palced in a tab in the main notebook.
1439 # o If an error occurs (or has occurred before) an error tab is created.
1441 if module
is not None:
1442 wx
.LogMessage("Running demo module...")
1443 if hasattr(module
, "overview"):
1444 overviewText
= module
.overview
1447 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1449 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1450 DemoError(sys
.exc_info()), self
)
1452 assert self
.demoPage
is not None, "runTest must return a window!"
1455 # There was a previous error in compiling or exec-ing
1456 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1457 self
.demoModules
.GetErrorInfo(), self
)
1459 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1462 # cahnge to the demo page the first time a module is run
1463 self
.UpdateNotebook(2)
1464 self
.firstTime
= False
1466 # otherwise just stay on the same tab in case the user has changed to another one
1467 self
.UpdateNotebook()
1469 #---------------------------------------------
1470 def ShutdownDemoModule(self
):
1472 # inform the window that it's time to quit if it cares
1473 if hasattr(self
.demoPage
, "ShutdownDemo"):
1474 self
.demoPage
.ShutdownDemo()
1475 wx
.YieldIfNeeded() # in case the page has pending events
1476 self
.demoPage
= None
1478 #---------------------------------------------
1479 def UpdateNotebook(self
, select
= -1):
1483 def UpdatePage(page
, pageText
):
1486 for i
in range(nb
.GetPageCount()):
1487 if nb
.GetPageText(i
) == pageText
:
1495 nb
.AddPage(page
, pageText
)
1496 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1498 if nb
.GetPage(pagePos
) != page
:
1499 # Reload an existing page
1501 nb
.DeletePage(pagePos
)
1502 nb
.InsertPage(pagePos
, page
, pageText
)
1504 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1506 # Excellent! No redraw/flicker
1507 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1510 nb
.DeletePage(pagePos
)
1511 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1513 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1516 select
= nb
.GetSelection()
1518 UpdatePage(self
.codePage
, "Demo Code")
1519 UpdatePage(self
.demoPage
, "Demo")
1521 if select
>= 0 and select
< nb
.GetPageCount():
1522 nb
.SetSelection(select
)
1524 #---------------------------------------------
1525 def SetOverview(self
, name
, text
):
1526 self
.curOverview
= text
1528 if lead
!= '<html>' and lead
!= '<HTML>':
1529 text
= '<br>'.join(text
.split('\n'))
1531 text
= text
.decode('iso8859_1')
1532 self
.ovr
.SetPage(text
)
1533 self
.nb
.SetPageText(0, name
)
1535 #---------------------------------------------
1537 def OnFileExit(self
, *event
):
1540 def OnToggleRedirect(self
, event
):
1544 print "Print statements and other standard output will now be directed to this window."
1547 print "Print statements and other standard output will now be sent to the usual location."
1549 def OnHelpAbout(self
, event
):
1550 from About
import MyAboutBox
1551 about
= MyAboutBox(self
)
1555 def OnHelpFind(self
, event
):
1556 if self
.finddlg
!= None:
1559 self
.nb
.SetSelection(1)
1560 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1561 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1562 self
.finddlg
.Show(True)
1565 def OnUpdateFindItems(self
, evt
):
1566 evt
.Enable(self
.finddlg
== None)
1569 def OnFind(self
, event
):
1570 editor
= self
.codePage
.editor
1571 self
.nb
.SetSelection(1)
1572 end
= editor
.GetLastPosition()
1573 textstring
= editor
.GetRange(0, end
).lower()
1574 findstring
= self
.finddata
.GetFindString().lower()
1575 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1577 start
= editor
.GetSelection()[0]
1578 loc
= textstring
.rfind(findstring
, 0, start
)
1580 start
= editor
.GetSelection()[1]
1581 loc
= textstring
.find(findstring
, start
)
1582 if loc
== -1 and start
!= 0:
1583 # string not found, start at beginning
1586 loc
= textstring
.rfind(findstring
, 0, start
)
1589 loc
= textstring
.find(findstring
, start
)
1591 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1592 'Find String Not Found in Demo File',
1593 wx
.OK | wx
.ICON_INFORMATION
)
1598 self
.finddlg
.SetFocus()
1601 self
.finddlg
.Destroy()
1603 editor
.ShowPosition(loc
)
1604 editor
.SetSelection(loc
, loc
+ len(findstring
))
1608 def OnFindNext(self
, event
):
1609 if self
.finddata
.GetFindString():
1612 self
.OnHelpFind(event
)
1614 def OnFindClose(self
, event
):
1615 event
.GetDialog().Destroy()
1619 def OnOpenShellWindow(self
, evt
):
1621 # if it already exists then just make sure it's visible
1627 # Make a PyShell window
1629 namespace
= { 'wx' : wx
,
1630 'app' : wx
.GetApp(),
1633 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1634 self
.shell
.SetSize((640,480))
1637 # Hook the close event of the main frame window so that we
1638 # close the shell at the same time if it still exists
1639 def CloseShell(evt
):
1643 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1646 #---------------------------------------------
1647 def OnCloseWindow(self
, event
):
1649 self
.demoPage
= None
1650 self
.codePage
= None
1651 self
.mainmenu
= None
1652 if self
.tbicon
is not None:
1653 self
.tbicon
.Destroy()
1657 #---------------------------------------------
1658 def OnIdle(self
, event
):
1660 self
.otherWin
.Raise()
1661 self
.demoPage
= self
.otherWin
1662 self
.otherWin
= None
1665 #---------------------------------------------
1668 showTipText
= open(opj("data/showTips")).read()
1669 showTip
, index
= eval(showTipText
)
1671 showTip
, index
= (1, 0)
1673 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1675 showTip
= wx
.ShowTip(self
, tp
)
1676 index
= tp
.GetCurrentTip()
1677 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1680 #---------------------------------------------
1681 def OnDemoMenu(self
, event
):
1683 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1687 self
.tree
.SelectItem(selectedDemo
)
1688 self
.tree
.EnsureVisible(selectedDemo
)
1692 #---------------------------------------------
1693 def OnIconfiy(self
, evt
):
1694 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1697 #---------------------------------------------
1698 def OnMaximize(self
, evt
):
1699 wx
.LogMessage("OnMaximize")
1702 #---------------------------------------------
1703 def OnActivate(self
, evt
):
1704 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1707 #---------------------------------------------
1708 def OnAppActivate(self
, evt
):
1709 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1712 #---------------------------------------------------------------------------
1713 #---------------------------------------------------------------------------
1715 class MySplashScreen(wx
.SplashScreen
):
1717 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1718 wx
.SplashScreen
.__init
__(self
, bmp
,
1719 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1721 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1722 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1725 def OnClose(self
, evt
):
1726 # Make sure the default handler runs too so this window gets
1731 # if the timer is still running then go ahead and show the
1733 if self
.fc
.IsRunning():
1739 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1741 if self
.fc
.IsRunning():
1745 class MyApp(wx
.App
):
1748 Create and show the splash screen. It will then create and show
1749 the main frame when it is time to do so.
1752 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1755 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1757 # Normally when using a SplashScreen you would create it, show
1758 # it and then continue on with the applicaiton's
1759 # initialization, finally creating and showing the main
1760 # application window(s). In this case we have nothing else to
1761 # do so we'll delay showing the main frame until later (see
1762 # ShowMain above) so the users can see the SplashScreen effect.
1763 splash
= MySplashScreen()
1770 #---------------------------------------------------------------------------
1774 demoPath
= os
.path
.dirname(__file__
)
1781 #---------------------------------------------------------------------------
1784 mainOverview
= """<html><body>
1787 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1788 language. It allows Python programmers to create programs with a
1789 robust, highly functional graphical user interface, simply and easily.
1790 It is implemented as a Python extension module (native code) that
1791 wraps the popular wxWindows cross platform GUI library, which is
1794 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1795 means that it is free for anyone to use and the source code is
1796 available for anyone to look at and modify. Or anyone can contribute
1797 fixes or enhancements to the project.
1799 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1800 same program will run on multiple platforms without modification.
1801 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1802 or unix-like systems, and Macintosh OS X. Since the language is
1803 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1806 <p> <b>This demo</b> is not only a collection of test cases for
1807 wxPython, but is also designed to help you learn about and how to use
1808 wxPython. Each sample is listed in the tree control on the left.
1809 When a sample is selected in the tree then a module is loaded and run
1810 (usually in a tab of this notebook,) and the source code of the module
1811 is loaded in another tab for you to browse and learn from.
1816 #----------------------------------------------------------------------------
1817 #----------------------------------------------------------------------------
1819 if __name__
== '__main__':
1823 #----------------------------------------------------------------------------