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',
61 # managed windows == things with a (optional) caption you can close
62 ('Frames and Dialogs', [
63 'AUI_DockingWindowMgr',
87 # dialogs from libraries
90 'ScrolledMessageDialog',
94 ('Core Windows/Controls', [
131 ('"Book" Controls', [
140 ('Custom Controls', [
153 # controls coming from other libraries
154 ('More Windows/Controls', [
155 'ActiveX_FlashWindow',
156 'ActiveX_IEHtmlWindow',
158 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
161 'CheckListCtrlMixin',
176 'MaskedEditControls',
179 'MultiSplitterWindow',
196 # How to lay out the controls in a frame/dialog
206 'XmlResourceHandler',
207 'XmlResourceSubclass',
211 ('Process and Events', [
218 ##'infoframe', # needs better explanation and some fixing
222 ('Clipboard and DnD', [
244 ##'DialogUnits', # needs more explanations
262 ('Check out the samples dir too', [
269 #---------------------------------------------------------------------------
270 # Show how to derive a custom wxLog class
272 class MyLog(wx
.PyLog
):
273 def __init__(self
, textCtrl
, logTime
=0):
274 wx
.PyLog
.__init
__(self
)
276 self
.logTime
= logTime
278 def DoLogString(self
, message
, timeStamp
):
279 #print message, timeStamp
281 # message = time.strftime("%X", time.localtime(timeStamp)) + \
284 self
.tc
.AppendText(message
+ '\n')
287 class MyTP(wx
.PyTipProvider
):
289 return "This is my tip"
291 #---------------------------------------------------------------------------
292 # A class to be used to simply display a message in the demo pane
293 # rather than running the sample itself.
295 class MessagePanel(wx
.Panel
):
296 def __init__(self
, parent
, message
, caption
='', flags
=0):
297 wx
.Panel
.__init
__(self
, parent
)
302 if flags
& wx
.ICON_EXCLAMATION
:
303 artid
= wx
.ART_WARNING
304 elif flags
& wx
.ICON_ERROR
:
306 elif flags
& wx
.ICON_QUESTION
:
307 artid
= wx
.ART_QUESTION
308 elif flags
& wx
.ICON_INFORMATION
:
309 artid
= wx
.ART_INFORMATION
311 if artid
is not None:
312 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
313 icon
= wx
.StaticBitmap(self
, -1, bmp
)
315 icon
= (32,32) # make a spacer instead
318 caption
= wx
.StaticText(self
, -1, caption
)
319 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
321 message
= wx
.StaticText(self
, -1, message
)
323 # add to sizers for layout
324 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
330 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
337 box
= wx
.BoxSizer(wx
.VERTICAL
)
339 box
.Add(hbox
, 0, wx
.EXPAND
)
346 #---------------------------------------------------------------------------
347 # A class to be used to display source code in the demo. Try using the
348 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
349 # if there is an error, such as the stc module not being present.
353 ##raise ImportError # for testing the alternate implementation
355 from StyledTextCtrl_2
import PythonSTC
357 class DemoCodeEditor(PythonSTC
):
358 def __init__(self
, parent
):
359 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
362 # Some methods to make it compatible with how the wxTextCtrl is used
363 def SetValue(self
, value
):
365 value
= value
.decode('iso8859_1')
367 self
.EmptyUndoBuffer()
370 def IsModified(self
):
371 return self
.GetModify()
376 def SetInsertionPoint(self
, pos
):
377 self
.SetCurrentPos(pos
)
380 def ShowPosition(self
, pos
):
381 line
= self
.LineFromPosition(pos
)
382 #self.EnsureVisible(line)
385 def GetLastPosition(self
):
386 return self
.GetLength()
388 def GetPositionFromLine(self
, line
):
389 return self
.PositionFromLine(line
)
391 def GetRange(self
, start
, end
):
392 return self
.GetTextRange(start
, end
)
394 def GetSelection(self
):
395 return self
.GetAnchor(), self
.GetCurrentPos()
397 def SetSelection(self
, start
, end
):
398 self
.SetSelectionStart(start
)
399 self
.SetSelectionEnd(end
)
401 def SelectLine(self
, line
):
402 start
= self
.PositionFromLine(line
)
403 end
= self
.GetLineEndPosition(line
)
404 self
.SetSelection(start
, end
)
406 def SetUpEditor(self
):
408 This method carries out the work of setting up the demo editor.
409 It's seperate so as not to clutter up the init code.
413 self
.SetLexer(stc
.STC_LEX_PYTHON
)
414 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
417 self
.SetProperty("fold", "1" )
419 # Highlight tab/space mixing (shouldn't be any)
420 self
.SetProperty("tab.timmy.whinge.level", "1")
422 # Set left and right margins
425 # Set up the numbers in the margin for margin #1
426 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
427 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
428 self
.SetMarginWidth(1, 40)
430 # Indentation and tab stuff
431 self
.SetIndent(4) # Proscribed indent size for wx
432 self
.SetIndentationGuides(True) # Show indent guides
433 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
434 self
.SetTabIndents(True) # Tab key indents
435 self
.SetTabWidth(4) # Proscribed tab size for wx
436 self
.SetUseTabs(False) # Use spaces rather than tabs, or
437 # TabTimmy will complain!
439 self
.SetViewWhiteSpace(False) # Don't view white space
441 # EOL: Since we are loading/saving ourselves, and the
442 # strings will always have \n's in them, set the STC to
443 # edit them that way.
444 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
445 self
.SetViewEOL(False)
447 # No right-edge mode indicator
448 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
450 # Setup a margin to hold fold markers
451 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
452 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
453 self
.SetMarginSensitive(2, True)
454 self
.SetMarginWidth(2, 12)
456 # and now set up the fold markers
457 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
458 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
459 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
460 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
461 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
462 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
463 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
465 # Global default style
466 if wx
.Platform
== '__WXMSW__':
467 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
468 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
470 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
471 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
473 # Clear styles and revert to default.
476 # Following style specs only indicate differences from default.
477 # The rest remains unchanged.
479 # Line numbers in margin
480 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
482 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
484 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
486 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
489 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
491 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
492 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
494 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
495 # Strings and characters
496 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
497 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
499 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
501 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
502 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
504 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
506 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
508 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
509 # Identifiers. I leave this as not bold because everything seems
510 # to be an identifier if it doesn't match the above criterae
511 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
514 self
.SetCaretForeground("BLUE")
515 # Selection background
516 self
.SetSelBackground(1, '#66CCFF')
518 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
519 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
521 def RegisterModifiedEvent(self
, eventHandler
):
522 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
526 class DemoCodeEditor(wx
.TextCtrl
):
527 def __init__(self
, parent
):
528 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
529 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
531 def RegisterModifiedEvent(self
, eventHandler
):
532 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
534 def SetReadOnly(self
, flag
):
535 self
.SetEditable(not flag
)
536 # NOTE: STC already has this method
539 return self
.GetValue()
541 def GetPositionFromLine(self
, line
):
542 return self
.XYToPosition(0,line
)
544 def GotoLine(self
, line
):
545 pos
= self
.GetPositionFromLine(line
)
546 self
.SetInsertionPoint(pos
)
547 self
.ShowPosition(pos
)
549 def SelectLine(self
, line
):
550 start
= self
.GetPositionFromLine(line
)
551 end
= start
+ self
.GetLineLength(line
)
552 self
.SetSelection(start
, end
)
555 #---------------------------------------------------------------------------
556 # Constants for module versions
560 modDefault
= modOriginal
562 #---------------------------------------------------------------------------
564 class DemoCodePanel(wx
.Panel
):
565 """Panel for the 'Demo Code' tab"""
566 def __init__(self
, parent
, mainFrame
):
567 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
568 if 'wxMSW' in wx
.PlatformInfo
:
570 self
.mainFrame
= mainFrame
571 self
.editor
= DemoCodeEditor(self
)
572 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
574 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
575 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
576 self
.btnSave
.Enable(False)
577 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
578 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
580 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
581 modModified
: wx
.RadioButton(self
, -1, "Modified") }
583 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
584 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
585 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
586 for modID
, radioButton
in self
.radioButtons
.items():
587 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
588 radioButton
.modID
= modID
# makes it easier for the event handler
589 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
591 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
592 self
.controlBox
.Add(self
.btnRestore
, 0)
594 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
595 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
596 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
597 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
600 self
.SetSizer(self
.box
)
603 # Loads a demo from a DemoModules object
604 def LoadDemo(self
, demoModules
):
605 self
.demoModules
= demoModules
606 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
607 demoModules
.SetActive(modModified
)
609 demoModules
.SetActive(modOriginal
)
610 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
611 self
.ActiveModuleChanged()
614 def ActiveModuleChanged(self
):
615 self
.LoadDemoSource(self
.demoModules
.GetSource())
616 self
.UpdateControlState()
620 def LoadDemoSource(self
, source
):
622 self
.editor
.SetValue(source
)
624 self
.btnSave
.Enable(False)
627 def JumpToLine(self
, line
, highlight
=False):
628 self
.editor
.GotoLine(line
)
629 self
.editor
.SetFocus()
631 self
.editor
.SelectLine(line
)
634 def UpdateControlState(self
):
635 active
= self
.demoModules
.GetActiveID()
636 # Update the radio/restore buttons
637 for moduleID
in self
.radioButtons
:
638 btn
= self
.radioButtons
[moduleID
]
639 if moduleID
== active
:
644 if self
.demoModules
.Exists(moduleID
):
646 if moduleID
== modModified
:
647 self
.btnRestore
.Enable(True)
650 if moduleID
== modModified
:
651 self
.btnRestore
.Enable(False)
654 def OnRadioButton(self
, event
):
655 radioSelected
= event
.GetEventObject()
656 modSelected
= radioSelected
.modID
657 if modSelected
!= self
.demoModules
.GetActiveID():
658 busy
= wx
.BusyInfo("Reloading demo module...")
659 self
.demoModules
.SetActive(modSelected
)
660 self
.ActiveModuleChanged()
663 def ReloadDemo(self
):
664 if self
.demoModules
.name
!= __name__
:
665 self
.mainFrame
.RunModule()
668 def OnCodeModified(self
, event
):
669 self
.btnSave
.Enable(self
.editor
.IsModified())
672 def OnSave(self
, event
):
673 if self
.demoModules
.Exists(modModified
):
674 if self
.demoModules
.GetActiveID() == modOriginal
:
675 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
676 "Do you want to continue?"
677 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
678 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
679 result
= dlg
.ShowModal()
680 if result
== wx
.ID_NO
:
684 self
.demoModules
.SetActive(modModified
)
685 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
687 # Create the demo directory if one doesn't already exist
688 if not os
.path
.exists(GetModifiedDirectory()):
690 os
.makedirs(GetModifiedDirectory())
691 if not os
.path
.exists(GetModifiedDirectory()):
692 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
695 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
698 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
701 f
= open(modifiedFilename
, "wt")
702 source
= self
.editor
.GetText()
708 busy
= wx
.BusyInfo("Reloading demo module...")
709 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
710 self
.ActiveModuleChanged()
713 def OnRestore(self
, event
): # Handles the "Delete Modified" button
714 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
715 self
.demoModules
.Delete(modModified
)
716 os
.unlink(modifiedFilename
) # Delete the modified copy
717 busy
= wx
.BusyInfo("Reloading demo module...")
718 self
.ActiveModuleChanged()
721 #---------------------------------------------------------------------------
724 """Convert paths to the platform-specific separator"""
725 str = apply(os
.path
.join
, tuple(path
.split('/')))
726 # HACK: on Linux, a leading / gets lost...
727 if path
.startswith('/'):
732 def GetModifiedDirectory():
734 Returns the directory where modified versions of the demo files
737 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
740 def GetModifiedFilename(name
):
742 Returns the filename of the modified version of the specified demo
744 if not name
.endswith(".py"):
746 return GetModifiedDirectory() + name
749 def GetOriginalFilename(name
):
751 Returns the filename of the original version of the specified demo
753 if not name
.endswith(".py"):
758 def DoesModifiedExist(name
):
759 """Returns whether the specified demo has a modified copy"""
760 if os
.path
.exists(GetModifiedFilename(name
)):
766 #---------------------------------------------------------------------------
768 class ModuleDictWrapper
:
769 """Emulates a module with a dynamically compiled __dict__"""
770 def __init__(self
, dict):
773 def __getattr__(self
, name
):
774 if name
in self
.dict:
775 return self
.dict[name
]
781 Dynamically manages the original/modified versions of a demo
784 def __init__(self
, name
):
788 # (dict , source , filename , description , error information )
789 # ( 0 , 1 , 2 , 3 , 4 )
790 self
.modules
= [[None, "" , "" , "<original>" , None],
791 [None, "" , "" , "<modified>" , None]]
793 # load original module
794 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
795 self
.SetActive(modOriginal
)
797 # load modified module (if one exists)
798 if DoesModifiedExist(name
):
799 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
802 def LoadFromFile(self
, modID
, filename
):
803 self
.modules
[modID
][2] = filename
804 file = open(filename
, "rt")
805 self
.LoadFromSource(modID
, file.read())
809 def LoadFromSource(self
, modID
, source
):
810 self
.modules
[modID
][1] = source
814 def LoadDict(self
, modID
):
815 if self
.name
!= __name__
:
816 source
= self
.modules
[modID
][1]
817 #description = self.modules[modID][3]
818 description
= self
.modules
[modID
][2]
821 self
.modules
[modID
][0] = {}
822 code
= compile(source
, description
, "exec")
823 exec code
in self
.modules
[modID
][0]
825 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
826 self
.modules
[modID
][0] = None
828 self
.modules
[modID
][4] = None
831 def SetActive(self
, modID
):
832 if modID
!= modOriginal
and modID
!= modModified
:
835 self
.modActive
= modID
839 dict = self
.modules
[self
.modActive
][0]
843 return ModuleDictWrapper(dict)
846 def GetActiveID(self
):
847 return self
.modActive
850 def GetSource(self
, modID
= None):
852 modID
= self
.modActive
853 return self
.modules
[modID
][1]
856 def GetFilename(self
, modID
= None):
858 modID
= self
.modActive
859 return self
.modules
[self
.modActive
][2]
862 def GetErrorInfo(self
, modID
= None):
864 modID
= self
.modActive
865 return self
.modules
[self
.modActive
][4]
868 def Exists(self
, modID
):
869 return self
.modules
[modID
][1] != ""
872 def UpdateFile(self
, modID
= None):
873 """Updates the file from which a module was loaded
874 with (possibly updated) source"""
876 modID
= self
.modActive
878 source
= self
.modules
[modID
][1]
879 filename
= self
.modules
[modID
][2]
882 file = open(filename
, "wt")
888 def Delete(self
, modID
):
889 if self
.modActive
== modID
:
892 self
.modules
[modID
][0] = None
893 self
.modules
[modID
][1] = ""
894 self
.modules
[modID
][2] = ""
897 #---------------------------------------------------------------------------
900 """Wraps and stores information about the current exception"""
901 def __init__(self
, exc_info
):
904 excType
, excValue
= exc_info
[:2]
905 # traceback list entries: (filename, line number, function name, text)
906 self
.traceback
= traceback
.extract_tb(exc_info
[2])
908 # --Based on traceback.py::format_exception_only()--
909 if type(excType
) == types
.ClassType
:
910 self
.exception_type
= excType
.__name
__
912 self
.exception_type
= excType
914 # If it's a syntax error, extra information needs
915 # to be added to the traceback
916 if excType
is SyntaxError:
918 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
923 filename
= "<string>"
925 self
.traceback
.append( (filename
, lineno
, "", line
) )
928 self
.exception_details
= str(excValue
)
930 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
937 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
940 #---------------------------------------------------------------------------
942 class DemoErrorPanel(wx
.Panel
):
943 """Panel put into the demo tab when the demo fails to run due to errors"""
945 def __init__(self
, parent
, codePanel
, demoError
, log
):
946 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
947 self
.codePanel
= codePanel
951 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
954 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
955 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
957 # Exception Information
958 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
959 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
960 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
961 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
962 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
963 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
964 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
965 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
966 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
967 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
969 # Set up the traceback list
970 # This one automatically resizes last column to take up remaining space
971 from ListCtrl
import TestListCtrl
972 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
973 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
974 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
975 self
.list.InsertColumn(0, "Filename")
976 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
977 self
.list.InsertColumn(2, "Function")
978 self
.list.InsertColumn(3, "Code")
979 self
.InsertTraceback(self
.list, demoError
.traceback
)
980 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
981 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
982 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
983 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
984 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
985 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
986 + "Double-click on them to go to the offending line")
987 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
990 self
.SetSizer(self
.box
)
993 def InsertTraceback(self
, list, traceback
):
994 #Add the traceback data
995 for x
in range(len(traceback
)):
997 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
998 list.SetStringItem(x
, 1, str(data
[1])) # Line
999 list.SetStringItem(x
, 2, str(data
[2])) # Function
1000 list.SetStringItem(x
, 3, str(data
[3])) # Code
1002 # Check whether this entry is from the demo module
1003 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1004 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1005 # Give it a blue colour
1006 item
= self
.list.GetItem(x
)
1007 item
.SetTextColour(wx
.BLUE
)
1008 self
.list.SetItem(item
)
1010 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1013 def OnItemSelected(self
, event
):
1014 # This occurs before OnDoubleClick and can be used to set the
1015 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1016 self
.currentItem
= event
.m_itemIndex
1020 def OnDoubleClick(self
, event
):
1021 # If double-clicking on a demo's entry, jump to the line number
1022 line
= self
.list.GetItemData(self
.currentItem
)
1024 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1025 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1029 #---------------------------------------------------------------------------
1031 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1032 TBMENU_RESTORE
= wx
.NewId()
1033 TBMENU_CLOSE
= wx
.NewId()
1034 TBMENU_CHANGE
= wx
.NewId()
1035 TBMENU_REMOVE
= wx
.NewId()
1037 def __init__(self
, frame
):
1038 wx
.TaskBarIcon
.__init
__(self
)
1042 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1043 self
.SetIcon(icon
, "wxPython Demo")
1047 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1048 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1049 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1050 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1051 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1054 def CreatePopupMenu(self
):
1056 This method is called by the base class when it needs to popup
1057 the menu for the default EVT_RIGHT_DOWN event. Just create
1058 the menu how you want it and return it from this function,
1059 the base class takes care of the rest.
1062 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1063 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1064 menu
.AppendSeparator()
1065 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1066 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1070 def MakeIcon(self
, img
):
1072 The various platforms have different requirements for the
1075 if "wxMSW" in wx
.PlatformInfo
:
1076 img
= img
.Scale(16, 16)
1077 elif "wxGTK" in wx
.PlatformInfo
:
1078 img
= img
.Scale(22, 22)
1079 # wxMac can be any size upto 128x128, so leave the source img alone....
1080 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1084 def OnTaskBarActivate(self
, evt
):
1085 if self
.frame
.IsIconized():
1086 self
.frame
.Iconize(False)
1087 if not self
.frame
.IsShown():
1088 self
.frame
.Show(True)
1092 def OnTaskBarClose(self
, evt
):
1096 def OnTaskBarChange(self
, evt
):
1097 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1098 name
= names
[self
.imgidx
]
1100 getFunc
= getattr(images
, "get%sImage" % name
)
1102 if self
.imgidx
>= len(names
):
1105 icon
= self
.MakeIcon(getFunc())
1106 self
.SetIcon(icon
, "This is a new icon: " + name
)
1109 def OnTaskBarRemove(self
, evt
):
1113 #---------------------------------------------------------------------------
1114 class wxPythonDemo(wx
.Frame
):
1115 overviewText
= "wxPython Overview"
1117 def __init__(self
, parent
, title
):
1118 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1119 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1121 self
.SetMinSize((640,480))
1124 self
.cwd
= os
.getcwd()
1125 self
.curOverview
= ""
1126 self
.demoPage
= None
1127 self
.codePage
= None
1129 self
.firstTime
= True
1132 icon
= images
.getWXPdemoIcon()
1135 self
.tbicon
= DemoTaskBarIcon(self
)
1137 wx
.CallAfter(self
.ShowTip
)
1139 self
.otherWin
= None
1140 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1141 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1142 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1143 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1145 self
.Centre(wx
.BOTH
)
1146 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1148 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1149 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1151 def EmptyHandler(evt
): pass
1152 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1153 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1155 # Prevent TreeCtrl from displaying all items after destruction when True
1159 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1162 self
.mainmenu
= wx
.MenuBar()
1164 item
= menu
.Append(-1, '&Redirect Output',
1165 'Redirect print statements to a window',
1167 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1169 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1170 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1171 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1172 self
.mainmenu
.Append(menu
, '&File')
1176 for item
in _treeList
:
1178 for childItem
in item
[1]:
1179 mi
= submenu
.Append(-1, childItem
)
1180 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1181 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1182 self
.mainmenu
.Append(menu
, '&Demo')
1187 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1188 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1189 menu
.AppendSeparator()
1191 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1192 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1193 menu
.AppendSeparator()
1194 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1195 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1197 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1198 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1199 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1200 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1201 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1202 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1203 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1204 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1205 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1206 self
.mainmenu
.Append(menu
, '&Help')
1207 self
.SetMenuBar(self
.mainmenu
)
1209 self
.finddata
= wx
.FindReplaceData()
1210 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1213 # This is another way to set Accelerators, in addition to
1214 # using the '\t<key>' syntax in the menu items.
1215 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1216 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1217 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1218 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1220 self
.SetAcceleratorTable(aTable
)
1226 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1227 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1230 root
= self
.tree
.AddRoot("wxPython Overview")
1232 for item
in _treeList
:
1233 child
= self
.tree
.AppendItem(root
, item
[0])
1234 if not firstChild
: firstChild
= child
1235 for childItem
in item
[1]:
1236 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1237 self
.treeMap
[childItem
] = theDemo
1239 self
.tree
.Expand(root
)
1240 self
.tree
.Expand(firstChild
)
1241 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1242 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1243 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1244 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1246 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1247 # we put it in a panel first because there seems to be a
1248 # refresh bug of some sort (wxGTK) when it is directly in
1251 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1252 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1254 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1255 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1256 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1257 self
.nb
.AddPage(panel
, self
.overviewText
)
1259 def OnOvrSize(evt
, ovr
=self
.ovr
):
1260 ovr
.SetSize(evt
.GetSize())
1261 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1262 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1264 if "gtk2" in wx
.PlatformInfo
:
1265 self
.ovr
.SetStandardFonts()
1266 self
.SetOverview(self
.overviewText
, mainOverview
)
1269 # Set up a log window
1270 self
.log
= wx
.TextCtrl(splitter2
, -1,
1271 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1273 # Set the wxWindows log target to be this textctrl
1274 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1276 # But instead of the above we want to show how to use our own wx.Log class
1277 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1279 # for serious debugging
1280 #wx.Log_SetActiveTarget(wx.LogStderr())
1281 #wx.Log_SetTraceMask(wx.TraceMessages)
1284 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1285 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1287 # add the windows to the splitter and split it.
1288 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1289 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1291 splitter
.SetMinimumPaneSize(120)
1292 splitter2
.SetMinimumPaneSize(60)
1294 # Make the splitter on the right expand the top window when resized
1295 def SplitterOnSize(evt
):
1296 splitter
= evt
.GetEventObject()
1297 sz
= splitter
.GetSize()
1298 splitter
.SetSashPosition(sz
.height
- 160, False)
1301 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1303 # select initial items
1304 self
.nb
.SetSelection(0)
1305 self
.tree
.SelectItem(root
)
1307 # Load 'Main' module
1308 self
.LoadDemo(self
.overviewText
)
1311 # select some other initial module?
1312 if len(sys
.argv
) > 1:
1314 if arg
.endswith('.py'):
1316 selectedDemo
= self
.treeMap
.get(arg
, None)
1318 self
.tree
.SelectItem(selectedDemo
)
1319 self
.tree
.EnsureVisible(selectedDemo
)
1322 #---------------------------------------------
1323 def WriteText(self
, text
):
1324 if text
[-1:] == '\n':
1328 def write(self
, txt
):
1331 #---------------------------------------------
1332 def OnItemExpanded(self
, event
):
1333 item
= event
.GetItem()
1334 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1337 #---------------------------------------------
1338 def OnItemCollapsed(self
, event
):
1339 item
= event
.GetItem()
1340 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1343 #---------------------------------------------
1344 def OnTreeLeftDown(self
, event
):
1345 # reset the overview text if the tree item is clicked on again
1346 pt
= event
.GetPosition();
1347 item
, flags
= self
.tree
.HitTest(pt
)
1348 if item
== self
.tree
.GetSelection():
1349 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1352 #---------------------------------------------
1353 def OnSelChanged(self
, event
):
1354 if self
.dying
or not self
.loaded
:
1357 item
= event
.GetItem()
1358 itemText
= self
.tree
.GetItemText(item
)
1359 self
.LoadDemo(itemText
)
1361 #---------------------------------------------
1362 def LoadDemo(self
, demoName
):
1364 wx
.BeginBusyCursor()
1367 self
.ShutdownDemoModule()
1369 if demoName
== self
.overviewText
:
1370 # User selected the "wxPython Overview" node
1372 # Changing the main window at runtime not yet supported...
1373 self
.demoModules
= DemoModules(__name__
)
1374 self
.SetOverview(self
.overviewText
, mainOverview
)
1375 self
.LoadDemoSource()
1376 self
.UpdateNotebook(0)
1378 if os
.path
.exists(GetOriginalFilename(demoName
)):
1379 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1380 self
.demoModules
= DemoModules(demoName
)
1381 self
.LoadDemoSource()
1384 self
.SetOverview("wxPython", mainOverview
)
1385 self
.codePage
= None
1386 self
.UpdateNotebook(0)
1390 #---------------------------------------------
1391 def LoadDemoSource(self
):
1392 self
.codePage
= None
1393 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1394 self
.codePage
.LoadDemo(self
.demoModules
)
1396 #---------------------------------------------
1397 def RunModule(self
):
1398 """Runs the active module"""
1400 module
= self
.demoModules
.GetActive()
1401 self
.ShutdownDemoModule()
1404 # o The RunTest() for all samples must now return a window that can
1405 # be palced in a tab in the main notebook.
1406 # o If an error occurs (or has occurred before) an error tab is created.
1408 if module
is not None:
1409 wx
.LogMessage("Running demo module...")
1410 if hasattr(module
, "overview"):
1411 overviewText
= module
.overview
1414 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1416 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1417 DemoError(sys
.exc_info()), self
)
1419 assert self
.demoPage
is not None, "runTest must return a window!"
1422 # There was a previous error in compiling or exec-ing
1423 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1424 self
.demoModules
.GetErrorInfo(), self
)
1426 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1429 # cahnge to the demo page the first time a module is run
1430 self
.UpdateNotebook(2)
1431 self
.firstTime
= False
1433 # otherwise just stay on the same tab in case the user has changed to another one
1434 self
.UpdateNotebook()
1436 #---------------------------------------------
1437 def ShutdownDemoModule(self
):
1439 # inform the window that it's time to quit if it cares
1440 if hasattr(self
.demoPage
, "ShutdownDemo"):
1441 self
.demoPage
.ShutdownDemo()
1442 wx
.YieldIfNeeded() # in case the page has pending events
1443 self
.demoPage
= None
1445 #---------------------------------------------
1446 def UpdateNotebook(self
, select
= -1):
1450 def UpdatePage(page
, pageText
):
1453 for i
in range(nb
.GetPageCount()):
1454 if nb
.GetPageText(i
) == pageText
:
1462 nb
.AddPage(page
, pageText
)
1463 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1465 if nb
.GetPage(pagePos
) != page
:
1466 # Reload an existing page
1468 nb
.DeletePage(pagePos
)
1469 nb
.InsertPage(pagePos
, page
, pageText
)
1471 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1473 # Excellent! No redraw/flicker
1474 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1477 nb
.DeletePage(pagePos
)
1478 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1480 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1483 select
= nb
.GetSelection()
1485 UpdatePage(self
.codePage
, "Demo Code")
1486 UpdatePage(self
.demoPage
, "Demo")
1488 if select
>= 0 and select
< nb
.GetPageCount():
1489 nb
.SetSelection(select
)
1491 #---------------------------------------------
1492 def SetOverview(self
, name
, text
):
1493 self
.curOverview
= text
1495 if lead
!= '<html>' and lead
!= '<HTML>':
1496 text
= '<br>'.join(text
.split('\n'))
1498 text
= text
.decode('iso8859_1')
1499 self
.ovr
.SetPage(text
)
1500 self
.nb
.SetPageText(0, name
)
1502 #---------------------------------------------
1504 def OnFileExit(self
, *event
):
1507 def OnToggleRedirect(self
, event
):
1511 print "Print statements and other standard output will now be directed to this window."
1514 print "Print statements and other standard output will now be sent to the usual location."
1516 def OnHelpAbout(self
, event
):
1517 from About
import MyAboutBox
1518 about
= MyAboutBox(self
)
1522 def OnHelpFind(self
, event
):
1523 if self
.finddlg
!= None:
1526 self
.nb
.SetSelection(1)
1527 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1528 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1529 self
.finddlg
.Show(True)
1532 def OnUpdateFindItems(self
, evt
):
1533 evt
.Enable(self
.finddlg
== None)
1536 def OnFind(self
, event
):
1537 editor
= self
.codePage
.editor
1538 self
.nb
.SetSelection(1)
1539 end
= editor
.GetLastPosition()
1540 textstring
= editor
.GetRange(0, end
).lower()
1541 findstring
= self
.finddata
.GetFindString().lower()
1542 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1544 start
= editor
.GetSelection()[0]
1545 loc
= textstring
.rfind(findstring
, 0, start
)
1547 start
= editor
.GetSelection()[1]
1548 loc
= textstring
.find(findstring
, start
)
1549 if loc
== -1 and start
!= 0:
1550 # string not found, start at beginning
1553 loc
= textstring
.rfind(findstring
, 0, start
)
1556 loc
= textstring
.find(findstring
, start
)
1558 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1559 'Find String Not Found in Demo File',
1560 wx
.OK | wx
.ICON_INFORMATION
)
1565 self
.finddlg
.SetFocus()
1568 self
.finddlg
.Destroy()
1570 editor
.ShowPosition(loc
)
1571 editor
.SetSelection(loc
, loc
+ len(findstring
))
1575 def OnFindNext(self
, event
):
1576 if self
.finddata
.GetFindString():
1579 self
.OnHelpFind(event
)
1581 def OnFindClose(self
, event
):
1582 event
.GetDialog().Destroy()
1586 def OnOpenShellWindow(self
, evt
):
1588 # if it already exists then just make sure it's visible
1594 # Make a PyShell window
1596 namespace
= { 'wx' : wx
,
1597 'app' : wx
.GetApp(),
1600 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1601 self
.shell
.SetSize((640,480))
1604 # Hook the close event of the main frame window so that we
1605 # close the shell at the same time if it still exists
1606 def CloseShell(evt
):
1610 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1613 #---------------------------------------------
1614 def OnCloseWindow(self
, event
):
1616 self
.demoPage
= None
1617 self
.codePage
= None
1618 self
.mainmenu
= None
1619 self
.tbicon
.Destroy()
1623 #---------------------------------------------
1624 def OnIdle(self
, event
):
1626 self
.otherWin
.Raise()
1627 self
.demoPage
= self
.otherWin
1628 self
.otherWin
= None
1631 #---------------------------------------------
1634 showTipText
= open(opj("data/showTips")).read()
1635 showTip
, index
= eval(showTipText
)
1637 showTip
, index
= (1, 0)
1639 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1641 showTip
= wx
.ShowTip(self
, tp
)
1642 index
= tp
.GetCurrentTip()
1643 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1646 #---------------------------------------------
1647 def OnDemoMenu(self
, event
):
1649 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1653 self
.tree
.SelectItem(selectedDemo
)
1654 self
.tree
.EnsureVisible(selectedDemo
)
1658 #---------------------------------------------
1659 def OnIconfiy(self
, evt
):
1660 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1663 #---------------------------------------------
1664 def OnMaximize(self
, evt
):
1665 wx
.LogMessage("OnMaximize")
1668 #---------------------------------------------
1669 def OnActivate(self
, evt
):
1670 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1673 #---------------------------------------------
1674 def OnAppActivate(self
, evt
):
1675 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1678 #---------------------------------------------------------------------------
1679 #---------------------------------------------------------------------------
1681 class MySplashScreen(wx
.SplashScreen
):
1683 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1684 wx
.SplashScreen
.__init
__(self
, bmp
,
1685 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1687 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1688 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1691 def OnClose(self
, evt
):
1692 # Make sure the default handler runs too so this window gets
1697 # if the timer is still running then go ahead and show the
1699 if self
.fc
.IsRunning():
1705 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1707 if self
.fc
.IsRunning():
1711 class MyApp(wx
.App
):
1714 Create and show the splash screen. It will then create and show
1715 the main frame when it is time to do so.
1718 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1721 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1723 # Normally when using a SplashScreen you would create it, show
1724 # it and then continue on with the applicaiton's
1725 # initialization, finally creating and showing the main
1726 # application window(s). In this case we have nothing else to
1727 # do so we'll delay showing the main frame until later (see
1728 # ShowMain above) so the users can see the SplashScreen effect.
1729 splash
= MySplashScreen()
1736 #---------------------------------------------------------------------------
1740 demoPath
= os
.path
.dirname(__file__
)
1747 #---------------------------------------------------------------------------
1750 mainOverview
= """<html><body>
1753 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1754 language. It allows Python programmers to create programs with a
1755 robust, highly functional graphical user interface, simply and easily.
1756 It is implemented as a Python extension module (native code) that
1757 wraps the popular wxWindows cross platform GUI library, which is
1760 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1761 means that it is free for anyone to use and the source code is
1762 available for anyone to look at and modify. Or anyone can contribute
1763 fixes or enhancements to the project.
1765 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1766 same program will run on multiple platforms without modification.
1767 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1768 or unix-like systems, and Macintosh OS X. Since the language is
1769 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1772 <p> <b>This demo</b> is not only a collection of test cases for
1773 wxPython, but is also designed to help you learn about and how to use
1774 wxPython. Each sample is listed in the tree control on the left.
1775 When a sample is selected in the tree then a module is loaded and run
1776 (usually in a tab of this notebook,) and the source code of the module
1777 is loaded in another tab for you to browse and learn from.
1782 #----------------------------------------------------------------------------
1783 #----------------------------------------------------------------------------
1785 if __name__
== '__main__':
1789 #----------------------------------------------------------------------------