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', [
58 # managed windows == things with a (optional) caption you can close
59 ('Frames and Dialogs', [
83 # dialogs from libraries
86 'ScrolledMessageDialog',
90 ('Core Windows/Controls', [
127 ('"Book" Controls', [
135 ('Custom Controls', [
148 # controls coming from other libraries
149 ('More Windows/Controls', [
150 'ActiveX_FlashWindow',
151 'ActiveX_IEHtmlWindow',
153 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
156 'CheckListCtrlMixin',
171 'MaskedEditControls',
174 'MultiSplitterWindow',
191 # How to lay out the controls in a frame/dialog
201 'XmlResourceHandler',
202 'XmlResourceSubclass',
206 ('Process and Events', [
213 ##'infoframe', # needs better explanation and some fixing
217 ('Clipboard and DnD', [
239 ##'DialogUnits', # needs more explanations
256 ('Check out the samples dir too', [
263 #---------------------------------------------------------------------------
264 # Show how to derive a custom wxLog class
266 class MyLog(wx
.PyLog
):
267 def __init__(self
, textCtrl
, logTime
=0):
268 wx
.PyLog
.__init
__(self
)
270 self
.logTime
= logTime
272 def DoLogString(self
, message
, timeStamp
):
273 #print message, timeStamp
275 # message = time.strftime("%X", time.localtime(timeStamp)) + \
278 self
.tc
.AppendText(message
+ '\n')
281 class MyTP(wx
.PyTipProvider
):
283 return "This is my tip"
285 #---------------------------------------------------------------------------
286 # A class to be used to simply display a message in the demo pane
287 # rather than running the sample itself.
289 class MessagePanel(wx
.Panel
):
290 def __init__(self
, parent
, message
, caption
='', flags
=0):
291 wx
.Panel
.__init
__(self
, parent
)
296 if flags
& wx
.ICON_EXCLAMATION
:
297 artid
= wx
.ART_WARNING
298 elif flags
& wx
.ICON_ERROR
:
300 elif flags
& wx
.ICON_QUESTION
:
301 artid
= wx
.ART_QUESTION
302 elif flags
& wx
.ICON_INFORMATION
:
303 artid
= wx
.ART_INFORMATION
305 if artid
is not None:
306 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
307 icon
= wx
.StaticBitmap(self
, -1, bmp
)
309 icon
= (32,32) # make a spacer instead
312 caption
= wx
.StaticText(self
, -1, caption
)
313 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
315 message
= wx
.StaticText(self
, -1, message
)
317 # add to sizers for layout
318 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
324 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
331 box
= wx
.BoxSizer(wx
.VERTICAL
)
333 box
.Add(hbox
, 0, wx
.EXPAND
)
340 #---------------------------------------------------------------------------
341 # A class to be used to display source code in the demo. Try using the
342 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
343 # if there is an error, such as the stc module not being present.
347 ##raise ImportError # for testing the alternate implementation
349 from StyledTextCtrl_2
import PythonSTC
351 class DemoCodeEditor(PythonSTC
):
352 def __init__(self
, parent
):
353 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
356 # Some methods to make it compatible with how the wxTextCtrl is used
357 def SetValue(self
, value
):
359 value
= value
.decode('iso8859_1')
361 self
.EmptyUndoBuffer()
364 def IsModified(self
):
365 return self
.GetModify()
370 def SetInsertionPoint(self
, pos
):
371 self
.SetCurrentPos(pos
)
374 def ShowPosition(self
, pos
):
375 line
= self
.LineFromPosition(pos
)
376 #self.EnsureVisible(line)
379 def GetLastPosition(self
):
380 return self
.GetLength()
382 def GetPositionFromLine(self
, line
):
383 return self
.PositionFromLine(line
)
385 def GetRange(self
, start
, end
):
386 return self
.GetTextRange(start
, end
)
388 def GetSelection(self
):
389 return self
.GetAnchor(), self
.GetCurrentPos()
391 def SetSelection(self
, start
, end
):
392 self
.SetSelectionStart(start
)
393 self
.SetSelectionEnd(end
)
395 def SelectLine(self
, line
):
396 start
= self
.PositionFromLine(line
)
397 end
= self
.GetLineEndPosition(line
)
398 self
.SetSelection(start
, end
)
400 def SetUpEditor(self
):
402 This method carries out the work of setting up the demo editor.
403 It's seperate so as not to clutter up the init code.
407 self
.SetLexer(stc
.STC_LEX_PYTHON
)
408 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
411 self
.SetProperty("fold", "1" )
413 # Highlight tab/space mixing (shouldn't be any)
414 self
.SetProperty("tab.timmy.whinge.level", "1")
416 # Set left and right margins
419 # Set up the numbers in the margin for margin #1
420 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
421 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
422 self
.SetMarginWidth(1, 40)
424 # Indentation and tab stuff
425 self
.SetIndent(4) # Proscribed indent size for wx
426 self
.SetIndentationGuides(True) # Show indent guides
427 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
428 self
.SetTabIndents(True) # Tab key indents
429 self
.SetTabWidth(4) # Proscribed tab size for wx
430 self
.SetUseTabs(False) # Use spaces rather than tabs, or
431 # TabTimmy will complain!
433 self
.SetViewWhiteSpace(False) # Don't view white space
435 # EOL: Since we are loading/saving ourselves, and the
436 # strings will always have \n's in them, set the STC to
437 # edit them that way.
438 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
439 self
.SetViewEOL(False)
441 # No right-edge mode indicator
442 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
444 # Setup a margin to hold fold markers
445 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
446 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
447 self
.SetMarginSensitive(2, True)
448 self
.SetMarginWidth(2, 12)
450 # and now set up the fold markers
451 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
452 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
453 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
454 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
455 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
456 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
457 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
459 # Global default style
460 if wx
.Platform
== '__WXMSW__':
461 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
462 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
464 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
465 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
467 # Clear styles and revert to default.
470 # Following style specs only indicate differences from default.
471 # The rest remains unchanged.
473 # Line numbers in margin
474 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
476 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
478 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
480 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
483 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
485 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
486 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
488 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
489 # Strings and characters
490 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
491 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
493 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
495 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
496 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
498 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
500 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
502 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
503 # Identifiers. I leave this as not bold because everything seems
504 # to be an identifier if it doesn't match the above criterae
505 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
508 self
.SetCaretForeground("BLUE")
509 # Selection background
510 self
.SetSelBackground(1, '#66CCFF')
512 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
513 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
515 def RegisterModifiedEvent(self
, eventHandler
):
516 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
520 class DemoCodeEditor(wx
.TextCtrl
):
521 def __init__(self
, parent
):
522 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
523 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
525 def RegisterModifiedEvent(self
, eventHandler
):
526 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
528 def SetReadOnly(self
, flag
):
529 self
.SetEditable(not flag
)
530 # NOTE: STC already has this method
533 return self
.GetValue()
535 def GetPositionFromLine(self
, line
):
536 return self
.XYToPosition(0,line
)
538 def GotoLine(self
, line
):
539 pos
= self
.GetPositionFromLine(line
)
540 self
.SetInsertionPoint(pos
)
541 self
.ShowPosition(pos
)
543 def SelectLine(self
, line
):
544 start
= self
.GetPositionFromLine(line
)
545 end
= start
+ self
.GetLineLength(line
)
546 self
.SetSelection(start
, end
)
549 #---------------------------------------------------------------------------
550 # Constants for module versions
554 modDefault
= modOriginal
556 #---------------------------------------------------------------------------
558 class DemoCodePanel(wx
.Panel
):
559 """Panel for the 'Demo Code' tab"""
560 def __init__(self
, parent
, mainFrame
):
561 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
562 if 'wxMSW' in wx
.PlatformInfo
:
564 self
.mainFrame
= mainFrame
565 self
.editor
= DemoCodeEditor(self
)
566 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
568 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
569 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
570 self
.btnSave
.Enable(False)
571 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
572 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
574 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
575 modModified
: wx
.RadioButton(self
, -1, "Modified") }
577 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
578 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
579 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
580 for modID
, radioButton
in self
.radioButtons
.items():
581 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
582 radioButton
.modID
= modID
# makes it easier for the event handler
583 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
585 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
586 self
.controlBox
.Add(self
.btnRestore
, 0)
588 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
589 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
590 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
591 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
594 self
.SetSizer(self
.box
)
597 # Loads a demo from a DemoModules object
598 def LoadDemo(self
, demoModules
):
599 self
.demoModules
= demoModules
600 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
601 demoModules
.SetActive(modModified
)
603 demoModules
.SetActive(modOriginal
)
604 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
605 self
.ActiveModuleChanged()
608 def ActiveModuleChanged(self
):
609 self
.LoadDemoSource(self
.demoModules
.GetSource())
610 self
.UpdateControlState()
614 def LoadDemoSource(self
, source
):
616 self
.editor
.SetValue(source
)
618 self
.btnSave
.Enable(False)
621 def JumpToLine(self
, line
, highlight
=False):
622 self
.editor
.GotoLine(line
)
623 self
.editor
.SetFocus()
625 self
.editor
.SelectLine(line
)
628 def UpdateControlState(self
):
629 active
= self
.demoModules
.GetActiveID()
630 # Update the radio/restore buttons
631 for moduleID
in self
.radioButtons
:
632 btn
= self
.radioButtons
[moduleID
]
633 if moduleID
== active
:
638 if self
.demoModules
.Exists(moduleID
):
640 if moduleID
== modModified
:
641 self
.btnRestore
.Enable(True)
644 if moduleID
== modModified
:
645 self
.btnRestore
.Enable(False)
648 def OnRadioButton(self
, event
):
649 radioSelected
= event
.GetEventObject()
650 modSelected
= radioSelected
.modID
651 if modSelected
!= self
.demoModules
.GetActiveID():
652 busy
= wx
.BusyInfo("Reloading demo module...")
653 self
.demoModules
.SetActive(modSelected
)
654 self
.ActiveModuleChanged()
657 def ReloadDemo(self
):
658 if self
.demoModules
.name
!= __name__
:
659 self
.mainFrame
.RunModule()
662 def OnCodeModified(self
, event
):
663 self
.btnSave
.Enable(self
.editor
.IsModified())
666 def OnSave(self
, event
):
667 if self
.demoModules
.Exists(modModified
):
668 if self
.demoModules
.GetActiveID() == modOriginal
:
669 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
670 "Do you want to continue?"
671 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
672 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
673 result
= dlg
.ShowModal()
674 if result
== wx
.ID_NO
:
678 self
.demoModules
.SetActive(modModified
)
679 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
681 # Create the demo directory if one doesn't already exist
682 if not os
.path
.exists(GetModifiedDirectory()):
684 os
.makedirs(GetModifiedDirectory())
685 if not os
.path
.exists(GetModifiedDirectory()):
686 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
689 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
692 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
695 f
= open(modifiedFilename
, "wt")
696 source
= self
.editor
.GetText()
702 busy
= wx
.BusyInfo("Reloading demo module...")
703 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
704 self
.ActiveModuleChanged()
707 def OnRestore(self
, event
): # Handles the "Delete Modified" button
708 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
709 self
.demoModules
.Delete(modModified
)
710 os
.unlink(modifiedFilename
) # Delete the modified copy
711 busy
= wx
.BusyInfo("Reloading demo module...")
712 self
.ActiveModuleChanged()
715 #---------------------------------------------------------------------------
718 """Convert paths to the platform-specific separator"""
719 str = apply(os
.path
.join
, tuple(path
.split('/')))
720 # HACK: on Linux, a leading / gets lost...
721 if path
.startswith('/'):
726 def GetModifiedDirectory():
728 Returns the directory where modified versions of the demo files
731 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
734 def GetModifiedFilename(name
):
736 Returns the filename of the modified version of the specified demo
738 if not name
.endswith(".py"):
740 return GetModifiedDirectory() + name
743 def GetOriginalFilename(name
):
745 Returns the filename of the original version of the specified demo
747 if not name
.endswith(".py"):
752 def DoesModifiedExist(name
):
753 """Returns whether the specified demo has a modified copy"""
754 if os
.path
.exists(GetModifiedFilename(name
)):
760 #---------------------------------------------------------------------------
762 class ModuleDictWrapper
:
763 """Emulates a module with a dynamically compiled __dict__"""
764 def __init__(self
, dict):
767 def __getattr__(self
, name
):
768 if name
in self
.dict:
769 return self
.dict[name
]
775 Dynamically manages the original/modified versions of a demo
778 def __init__(self
, name
):
782 # (dict , source , filename , description , error information )
783 # ( 0 , 1 , 2 , 3 , 4 )
784 self
.modules
= [[None, "" , "" , "<original>" , None],
785 [None, "" , "" , "<modified>" , None]]
787 # load original module
788 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
789 self
.SetActive(modOriginal
)
791 # load modified module (if one exists)
792 if DoesModifiedExist(name
):
793 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
796 def LoadFromFile(self
, modID
, filename
):
797 self
.modules
[modID
][2] = filename
798 file = open(filename
, "rt")
799 self
.LoadFromSource(modID
, file.read())
803 def LoadFromSource(self
, modID
, source
):
804 self
.modules
[modID
][1] = source
808 def LoadDict(self
, modID
):
809 if self
.name
!= __name__
:
810 source
= self
.modules
[modID
][1]
811 #description = self.modules[modID][3]
812 description
= self
.modules
[modID
][2]
815 self
.modules
[modID
][0] = {}
816 code
= compile(source
, description
, "exec")
817 exec code
in self
.modules
[modID
][0]
819 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
820 self
.modules
[modID
][0] = None
822 self
.modules
[modID
][4] = None
825 def SetActive(self
, modID
):
826 if modID
!= modOriginal
and modID
!= modModified
:
829 self
.modActive
= modID
833 dict = self
.modules
[self
.modActive
][0]
837 return ModuleDictWrapper(dict)
840 def GetActiveID(self
):
841 return self
.modActive
844 def GetSource(self
, modID
= None):
846 modID
= self
.modActive
847 return self
.modules
[modID
][1]
850 def GetFilename(self
, modID
= None):
852 modID
= self
.modActive
853 return self
.modules
[self
.modActive
][2]
856 def GetErrorInfo(self
, modID
= None):
858 modID
= self
.modActive
859 return self
.modules
[self
.modActive
][4]
862 def Exists(self
, modID
):
863 return self
.modules
[modID
][1] != ""
866 def UpdateFile(self
, modID
= None):
867 """Updates the file from which a module was loaded
868 with (possibly updated) source"""
870 modID
= self
.modActive
872 source
= self
.modules
[modID
][1]
873 filename
= self
.modules
[modID
][2]
876 file = open(filename
, "wt")
882 def Delete(self
, modID
):
883 if self
.modActive
== modID
:
886 self
.modules
[modID
][0] = None
887 self
.modules
[modID
][1] = ""
888 self
.modules
[modID
][2] = ""
891 #---------------------------------------------------------------------------
894 """Wraps and stores information about the current exception"""
895 def __init__(self
, exc_info
):
898 excType
, excValue
= exc_info
[:2]
899 # traceback list entries: (filename, line number, function name, text)
900 self
.traceback
= traceback
.extract_tb(exc_info
[2])
902 # --Based on traceback.py::format_exception_only()--
903 if type(excType
) == types
.ClassType
:
904 self
.exception_type
= excType
.__name
__
906 self
.exception_type
= excType
908 # If it's a syntax error, extra information needs
909 # to be added to the traceback
910 if excType
is SyntaxError:
912 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
917 filename
= "<string>"
919 self
.traceback
.append( (filename
, lineno
, "", line
) )
922 self
.exception_details
= str(excValue
)
924 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
931 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
934 #---------------------------------------------------------------------------
936 class DemoErrorPanel(wx
.Panel
):
937 """Panel put into the demo tab when the demo fails to run due to errors"""
939 def __init__(self
, parent
, codePanel
, demoError
, log
):
940 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
941 self
.codePanel
= codePanel
945 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
948 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
949 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
951 # Exception Information
952 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
953 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
954 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
955 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
956 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
957 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
958 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
959 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
960 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
961 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
963 # Set up the traceback list
964 # This one automatically resizes last column to take up remaining space
965 from ListCtrl
import TestListCtrl
966 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
967 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
968 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
969 self
.list.InsertColumn(0, "Filename")
970 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
971 self
.list.InsertColumn(2, "Function")
972 self
.list.InsertColumn(3, "Code")
973 self
.InsertTraceback(self
.list, demoError
.traceback
)
974 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
975 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
976 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
977 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
978 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
979 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
980 + "Double-click on them to go to the offending line")
981 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
984 self
.SetSizer(self
.box
)
987 def InsertTraceback(self
, list, traceback
):
988 #Add the traceback data
989 for x
in range(len(traceback
)):
991 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
992 list.SetStringItem(x
, 1, str(data
[1])) # Line
993 list.SetStringItem(x
, 2, str(data
[2])) # Function
994 list.SetStringItem(x
, 3, str(data
[3])) # Code
996 # Check whether this entry is from the demo module
997 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
998 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
999 # Give it a blue colour
1000 item
= self
.list.GetItem(x
)
1001 item
.SetTextColour(wx
.BLUE
)
1002 self
.list.SetItem(item
)
1004 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1007 def OnItemSelected(self
, event
):
1008 # This occurs before OnDoubleClick and can be used to set the
1009 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1010 self
.currentItem
= event
.m_itemIndex
1014 def OnDoubleClick(self
, event
):
1015 # If double-clicking on a demo's entry, jump to the line number
1016 line
= self
.list.GetItemData(self
.currentItem
)
1018 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1019 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1023 #---------------------------------------------------------------------------
1025 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1026 TBMENU_RESTORE
= wx
.NewId()
1027 TBMENU_CLOSE
= wx
.NewId()
1028 TBMENU_CHANGE
= wx
.NewId()
1029 TBMENU_REMOVE
= wx
.NewId()
1031 def __init__(self
, frame
):
1032 wx
.TaskBarIcon
.__init
__(self
)
1036 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1037 self
.SetIcon(icon
, "wxPython Demo")
1041 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1042 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1043 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1044 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1045 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1048 def CreatePopupMenu(self
):
1050 This method is called by the base class when it needs to popup
1051 the menu for the default EVT_RIGHT_DOWN event. Just create
1052 the menu how you want it and return it from this function,
1053 the base class takes care of the rest.
1056 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1057 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1058 menu
.AppendSeparator()
1059 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1060 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1064 def MakeIcon(self
, img
):
1066 The various platforms have different requirements for the
1069 if "wxMSW" in wx
.PlatformInfo
:
1070 img
= img
.Scale(16, 16)
1071 elif "wxGTK" in wx
.PlatformInfo
:
1072 img
= img
.Scale(22, 22)
1073 # wxMac can be any size upto 128x128, so leave the source img alone....
1074 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1078 def OnTaskBarActivate(self
, evt
):
1079 if self
.frame
.IsIconized():
1080 self
.frame
.Iconize(False)
1081 if not self
.frame
.IsShown():
1082 self
.frame
.Show(True)
1086 def OnTaskBarClose(self
, evt
):
1090 def OnTaskBarChange(self
, evt
):
1091 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1092 name
= names
[self
.imgidx
]
1094 getFunc
= getattr(images
, "get%sImage" % name
)
1096 if self
.imgidx
>= len(names
):
1099 icon
= self
.MakeIcon(getFunc())
1100 self
.SetIcon(icon
, "This is a new icon: " + name
)
1103 def OnTaskBarRemove(self
, evt
):
1107 #---------------------------------------------------------------------------
1108 class wxPythonDemo(wx
.Frame
):
1109 overviewText
= "wxPython Overview"
1111 def __init__(self
, parent
, title
):
1112 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1113 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1115 self
.SetMinSize((640,480))
1118 self
.cwd
= os
.getcwd()
1119 self
.curOverview
= ""
1120 self
.demoPage
= None
1121 self
.codePage
= None
1123 self
.firstTime
= True
1126 icon
= images
.getWXPdemoIcon()
1129 self
.tbicon
= DemoTaskBarIcon(self
)
1131 wx
.CallAfter(self
.ShowTip
)
1133 self
.otherWin
= None
1134 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1135 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1136 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1137 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1139 self
.Centre(wx
.BOTH
)
1140 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1142 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1143 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1145 def EmptyHandler(evt
): pass
1146 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1147 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1149 # Prevent TreeCtrl from displaying all items after destruction when True
1153 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1156 self
.mainmenu
= wx
.MenuBar()
1158 item
= menu
.Append(-1, '&Redirect Output',
1159 'Redirect print statements to a window',
1161 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1163 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1164 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1165 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1166 self
.mainmenu
.Append(menu
, '&File')
1170 for item
in _treeList
:
1172 for childItem
in item
[1]:
1173 mi
= submenu
.Append(-1, childItem
)
1174 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1175 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1176 self
.mainmenu
.Append(menu
, '&Demo')
1181 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1182 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1183 menu
.AppendSeparator()
1185 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1186 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1187 menu
.AppendSeparator()
1188 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1189 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1191 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1192 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1193 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1194 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1195 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1196 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1197 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1198 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1199 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1200 self
.mainmenu
.Append(menu
, '&Help')
1201 self
.SetMenuBar(self
.mainmenu
)
1203 self
.finddata
= wx
.FindReplaceData()
1204 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1207 # This is another way to set Accelerators, in addition to
1208 # using the '\t<key>' syntax in the menu items.
1209 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1210 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1211 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1212 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1214 self
.SetAcceleratorTable(aTable
)
1220 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1221 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1224 root
= self
.tree
.AddRoot("wxPython Overview")
1226 for item
in _treeList
:
1227 child
= self
.tree
.AppendItem(root
, item
[0])
1228 if not firstChild
: firstChild
= child
1229 for childItem
in item
[1]:
1230 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1231 self
.treeMap
[childItem
] = theDemo
1233 self
.tree
.Expand(root
)
1234 self
.tree
.Expand(firstChild
)
1235 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1236 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1237 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1238 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1240 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1241 # we put it in a panel first because there seems to be a
1242 # refresh bug of some sort (wxGTK) when it is directly in
1245 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1246 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1248 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1249 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1250 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1251 self
.nb
.AddPage(panel
, self
.overviewText
)
1253 def OnOvrSize(evt
, ovr
=self
.ovr
):
1254 ovr
.SetSize(evt
.GetSize())
1255 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1256 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1258 if "gtk2" in wx
.PlatformInfo
:
1259 self
.ovr
.SetStandardFonts()
1260 self
.SetOverview(self
.overviewText
, mainOverview
)
1263 # Set up a log window
1264 self
.log
= wx
.TextCtrl(splitter2
, -1,
1265 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1267 # Set the wxWindows log target to be this textctrl
1268 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1270 # But instead of the above we want to show how to use our own wx.Log class
1271 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1273 # for serious debugging
1274 #wx.Log_SetActiveTarget(wx.LogStderr())
1275 #wx.Log_SetTraceMask(wx.TraceMessages)
1278 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1279 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1281 # add the windows to the splitter and split it.
1282 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1283 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1285 splitter
.SetMinimumPaneSize(120)
1286 splitter2
.SetMinimumPaneSize(60)
1288 # Make the splitter on the right expand the top window when resized
1289 def SplitterOnSize(evt
):
1290 splitter
= evt
.GetEventObject()
1291 sz
= splitter
.GetSize()
1292 splitter
.SetSashPosition(sz
.height
- 160, False)
1295 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1297 # select initial items
1298 self
.nb
.SetSelection(0)
1299 self
.tree
.SelectItem(root
)
1301 # Load 'Main' module
1302 self
.LoadDemo(self
.overviewText
)
1305 # select some other initial module?
1306 if len(sys
.argv
) > 1:
1308 if arg
.endswith('.py'):
1310 selectedDemo
= self
.treeMap
.get(arg
, None)
1312 self
.tree
.SelectItem(selectedDemo
)
1313 self
.tree
.EnsureVisible(selectedDemo
)
1316 #---------------------------------------------
1317 def WriteText(self
, text
):
1318 if text
[-1:] == '\n':
1322 def write(self
, txt
):
1325 #---------------------------------------------
1326 def OnItemExpanded(self
, event
):
1327 item
= event
.GetItem()
1328 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1331 #---------------------------------------------
1332 def OnItemCollapsed(self
, event
):
1333 item
= event
.GetItem()
1334 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1337 #---------------------------------------------
1338 def OnTreeLeftDown(self
, event
):
1339 # reset the overview text if the tree item is clicked on again
1340 pt
= event
.GetPosition();
1341 item
, flags
= self
.tree
.HitTest(pt
)
1342 if item
== self
.tree
.GetSelection():
1343 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1346 #---------------------------------------------
1347 def OnSelChanged(self
, event
):
1348 if self
.dying
or not self
.loaded
:
1351 item
= event
.GetItem()
1352 itemText
= self
.tree
.GetItemText(item
)
1353 self
.LoadDemo(itemText
)
1355 #---------------------------------------------
1356 def LoadDemo(self
, demoName
):
1358 wx
.BeginBusyCursor()
1361 self
.ShutdownDemoModule()
1363 if demoName
== self
.overviewText
:
1364 # User selected the "wxPython Overview" node
1366 # Changing the main window at runtime not yet supported...
1367 self
.demoModules
= DemoModules(__name__
)
1368 self
.SetOverview(self
.overviewText
, mainOverview
)
1369 self
.LoadDemoSource()
1370 self
.UpdateNotebook(0)
1372 if os
.path
.exists(GetOriginalFilename(demoName
)):
1373 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1374 self
.demoModules
= DemoModules(demoName
)
1375 self
.LoadDemoSource()
1378 self
.SetOverview("wxPython", mainOverview
)
1379 self
.codePage
= None
1380 self
.UpdateNotebook(0)
1384 #---------------------------------------------
1385 def LoadDemoSource(self
):
1386 self
.codePage
= None
1387 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1388 self
.codePage
.LoadDemo(self
.demoModules
)
1390 #---------------------------------------------
1391 def RunModule(self
):
1392 """Runs the active module"""
1394 module
= self
.demoModules
.GetActive()
1395 self
.ShutdownDemoModule()
1398 # o The RunTest() for all samples must now return a window that can
1399 # be palced in a tab in the main notebook.
1400 # o If an error occurs (or has occurred before) an error tab is created.
1402 if module
is not None:
1403 wx
.LogMessage("Running demo module...")
1404 if hasattr(module
, "overview"):
1405 overviewText
= module
.overview
1408 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1410 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1411 DemoError(sys
.exc_info()), self
)
1413 assert self
.demoPage
is not None, "runTest must return a window!"
1416 # There was a previous error in compiling or exec-ing
1417 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1418 self
.demoModules
.GetErrorInfo(), self
)
1420 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1423 # cahnge to the demo page the first time a module is run
1424 self
.UpdateNotebook(2)
1425 self
.firstTime
= False
1427 # otherwise just stay on the same tab in case the user has changed to another one
1428 self
.UpdateNotebook()
1430 #---------------------------------------------
1431 def ShutdownDemoModule(self
):
1433 # inform the window that it's time to quit if it cares
1434 if hasattr(self
.demoPage
, "ShutdownDemo"):
1435 self
.demoPage
.ShutdownDemo()
1436 wx
.YieldIfNeeded() # in case the page has pending events
1437 self
.demoPage
= None
1439 #---------------------------------------------
1440 def UpdateNotebook(self
, select
= -1):
1444 def UpdatePage(page
, pageText
):
1447 for i
in range(nb
.GetPageCount()):
1448 if nb
.GetPageText(i
) == pageText
:
1456 nb
.AddPage(page
, pageText
)
1457 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1459 if nb
.GetPage(pagePos
) != page
:
1460 # Reload an existing page
1462 nb
.DeletePage(pagePos
)
1463 nb
.InsertPage(pagePos
, page
, pageText
)
1465 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1467 # Excellent! No redraw/flicker
1468 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1471 nb
.DeletePage(pagePos
)
1472 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1474 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1477 select
= nb
.GetSelection()
1479 UpdatePage(self
.codePage
, "Demo Code")
1480 UpdatePage(self
.demoPage
, "Demo")
1482 if select
>= 0 and select
< nb
.GetPageCount():
1483 nb
.SetSelection(select
)
1485 #---------------------------------------------
1486 def SetOverview(self
, name
, text
):
1487 self
.curOverview
= text
1489 if lead
!= '<html>' and lead
!= '<HTML>':
1490 text
= '<br>'.join(text
.split('\n'))
1492 text
= text
.decode('iso8859_1')
1493 self
.ovr
.SetPage(text
)
1494 self
.nb
.SetPageText(0, name
)
1496 #---------------------------------------------
1498 def OnFileExit(self
, *event
):
1501 def OnToggleRedirect(self
, event
):
1505 print "Print statements and other standard output will now be directed to this window."
1508 print "Print statements and other standard output will now be sent to the usual location."
1510 def OnHelpAbout(self
, event
):
1511 from About
import MyAboutBox
1512 about
= MyAboutBox(self
)
1516 def OnHelpFind(self
, event
):
1517 if self
.finddlg
!= None:
1520 self
.nb
.SetSelection(1)
1521 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1522 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1523 self
.finddlg
.Show(True)
1526 def OnUpdateFindItems(self
, evt
):
1527 evt
.Enable(self
.finddlg
== None)
1530 def OnFind(self
, event
):
1531 editor
= self
.codePage
.editor
1532 self
.nb
.SetSelection(1)
1533 end
= editor
.GetLastPosition()
1534 textstring
= editor
.GetRange(0, end
).lower()
1535 findstring
= self
.finddata
.GetFindString().lower()
1536 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1538 start
= editor
.GetSelection()[0]
1539 loc
= textstring
.rfind(findstring
, 0, start
)
1541 start
= editor
.GetSelection()[1]
1542 loc
= textstring
.find(findstring
, start
)
1543 if loc
== -1 and start
!= 0:
1544 # string not found, start at beginning
1547 loc
= textstring
.rfind(findstring
, 0, start
)
1550 loc
= textstring
.find(findstring
, start
)
1552 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1553 'Find String Not Found in Demo File',
1554 wx
.OK | wx
.ICON_INFORMATION
)
1559 self
.finddlg
.SetFocus()
1562 self
.finddlg
.Destroy()
1564 editor
.ShowPosition(loc
)
1565 editor
.SetSelection(loc
, loc
+ len(findstring
))
1569 def OnFindNext(self
, event
):
1570 if self
.finddata
.GetFindString():
1573 self
.OnHelpFind(event
)
1575 def OnFindClose(self
, event
):
1576 event
.GetDialog().Destroy()
1580 def OnOpenShellWindow(self
, evt
):
1582 # if it already exists then just make sure it's visible
1588 # Make a PyShell window
1590 namespace
= { 'wx' : wx
,
1591 'app' : wx
.GetApp(),
1594 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1595 self
.shell
.SetSize((640,480))
1598 # Hook the close event of the main frame window so that we
1599 # close the shell at the same time if it still exists
1600 def CloseShell(evt
):
1604 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1607 #---------------------------------------------
1608 def OnCloseWindow(self
, event
):
1610 self
.demoPage
= None
1611 self
.codePage
= None
1612 self
.mainmenu
= None
1613 self
.tbicon
.Destroy()
1617 #---------------------------------------------
1618 def OnIdle(self
, event
):
1620 self
.otherWin
.Raise()
1621 self
.demoPage
= self
.otherWin
1622 self
.otherWin
= None
1625 #---------------------------------------------
1628 showTipText
= open(opj("data/showTips")).read()
1629 showTip
, index
= eval(showTipText
)
1631 showTip
, index
= (1, 0)
1633 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1635 showTip
= wx
.ShowTip(self
, tp
)
1636 index
= tp
.GetCurrentTip()
1637 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1640 #---------------------------------------------
1641 def OnDemoMenu(self
, event
):
1643 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1647 self
.tree
.SelectItem(selectedDemo
)
1648 self
.tree
.EnsureVisible(selectedDemo
)
1652 #---------------------------------------------
1653 def OnIconfiy(self
, evt
):
1654 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1657 #---------------------------------------------
1658 def OnMaximize(self
, evt
):
1659 wx
.LogMessage("OnMaximize")
1662 #---------------------------------------------
1663 def OnActivate(self
, evt
):
1664 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1667 #---------------------------------------------
1668 def OnAppActivate(self
, evt
):
1669 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1672 #---------------------------------------------------------------------------
1673 #---------------------------------------------------------------------------
1675 class MySplashScreen(wx
.SplashScreen
):
1677 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1678 wx
.SplashScreen
.__init
__(self
, bmp
,
1679 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1681 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1682 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1685 def OnClose(self
, evt
):
1686 # Make sure the default handler runs too so this window gets
1691 # if the timer is still running then go ahead and show the
1693 if self
.fc
.IsRunning():
1699 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1701 if self
.fc
.IsRunning():
1705 class MyApp(wx
.App
):
1708 Create and show the splash screen. It will then create and show
1709 the main frame when it is time to do so.
1712 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1715 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1717 # Normally when using a SplashScreen you would create it, show
1718 # it and then continue on with the applicaiton's
1719 # initialization, finally creating and showing the main
1720 # application window(s). In this case we have nothing else to
1721 # do so we'll delay showing the main frame until later (see
1722 # ShowMain above) so the users can see the SplashScreen effect.
1723 splash
= MySplashScreen()
1730 #---------------------------------------------------------------------------
1734 demoPath
= os
.path
.dirname(__file__
)
1741 #---------------------------------------------------------------------------
1744 mainOverview
= """<html><body>
1747 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1748 language. It allows Python programmers to create programs with a
1749 robust, highly functional graphical user interface, simply and easily.
1750 It is implemented as a Python extension module (native code) that
1751 wraps the popular wxWindows cross platform GUI library, which is
1754 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1755 means that it is free for anyone to use and the source code is
1756 available for anyone to look at and modify. Or anyone can contribute
1757 fixes or enhancements to the project.
1759 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1760 same program will run on multiple platforms without modification.
1761 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1762 or unix-like systems, and Macintosh OS X. Since the language is
1763 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1766 <p> <b>This demo</b> is not only a collection of test cases for
1767 wxPython, but is also designed to help you learn about and how to use
1768 wxPython. Each sample is listed in the tree control on the left.
1769 When a sample is selected in the tree then a module is loaded and run
1770 (usually in a tab of this notebook,) and the source code of the module
1771 is loaded in another tab for you to browse and learn from.
1776 #----------------------------------------------------------------------------
1777 #----------------------------------------------------------------------------
1779 if __name__
== '__main__':
1783 #----------------------------------------------------------------------------