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')
495 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
496 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
498 # Clear styles and revert to default.
501 # Following style specs only indicate differences from default.
502 # The rest remains unchanged.
504 # Line numbers in margin
505 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
507 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
509 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
511 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
514 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
516 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
517 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
519 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
520 # Strings and characters
521 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
522 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
524 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
526 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
527 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
529 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
531 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
533 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
534 # Identifiers. I leave this as not bold because everything seems
535 # to be an identifier if it doesn't match the above criterae
536 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
539 self
.SetCaretForeground("BLUE")
540 # Selection background
541 self
.SetSelBackground(1, '#66CCFF')
543 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
544 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
546 def RegisterModifiedEvent(self
, eventHandler
):
547 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
551 class DemoCodeEditor(wx
.TextCtrl
):
552 def __init__(self
, parent
):
553 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
554 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
556 def RegisterModifiedEvent(self
, eventHandler
):
557 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
559 def SetReadOnly(self
, flag
):
560 self
.SetEditable(not flag
)
561 # NOTE: STC already has this method
564 return self
.GetValue()
566 def GetPositionFromLine(self
, line
):
567 return self
.XYToPosition(0,line
)
569 def GotoLine(self
, line
):
570 pos
= self
.GetPositionFromLine(line
)
571 self
.SetInsertionPoint(pos
)
572 self
.ShowPosition(pos
)
574 def SelectLine(self
, line
):
575 start
= self
.GetPositionFromLine(line
)
576 end
= start
+ self
.GetLineLength(line
)
577 self
.SetSelection(start
, end
)
580 #---------------------------------------------------------------------------
581 # Constants for module versions
585 modDefault
= modOriginal
587 #---------------------------------------------------------------------------
589 class DemoCodePanel(wx
.Panel
):
590 """Panel for the 'Demo Code' tab"""
591 def __init__(self
, parent
, mainFrame
):
592 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
593 if 'wxMSW' in wx
.PlatformInfo
:
595 self
.mainFrame
= mainFrame
596 self
.editor
= DemoCodeEditor(self
)
597 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
599 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
600 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
601 self
.btnSave
.Enable(False)
602 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
603 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
605 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
606 modModified
: wx
.RadioButton(self
, -1, "Modified") }
608 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
609 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
610 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
611 for modID
, radioButton
in self
.radioButtons
.items():
612 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
613 radioButton
.modID
= modID
# makes it easier for the event handler
614 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
616 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
617 self
.controlBox
.Add(self
.btnRestore
, 0)
619 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
620 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
621 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
622 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
625 self
.SetSizer(self
.box
)
628 # Loads a demo from a DemoModules object
629 def LoadDemo(self
, demoModules
):
630 self
.demoModules
= demoModules
631 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
632 demoModules
.SetActive(modModified
)
634 demoModules
.SetActive(modOriginal
)
635 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
636 self
.ActiveModuleChanged()
639 def ActiveModuleChanged(self
):
640 self
.LoadDemoSource(self
.demoModules
.GetSource())
641 self
.UpdateControlState()
645 def LoadDemoSource(self
, source
):
647 self
.editor
.SetValue(source
)
649 self
.btnSave
.Enable(False)
652 def JumpToLine(self
, line
, highlight
=False):
653 self
.editor
.GotoLine(line
)
654 self
.editor
.SetFocus()
656 self
.editor
.SelectLine(line
)
659 def UpdateControlState(self
):
660 active
= self
.demoModules
.GetActiveID()
661 # Update the radio/restore buttons
662 for moduleID
in self
.radioButtons
:
663 btn
= self
.radioButtons
[moduleID
]
664 if moduleID
== active
:
669 if self
.demoModules
.Exists(moduleID
):
671 if moduleID
== modModified
:
672 self
.btnRestore
.Enable(True)
675 if moduleID
== modModified
:
676 self
.btnRestore
.Enable(False)
679 def OnRadioButton(self
, event
):
680 radioSelected
= event
.GetEventObject()
681 modSelected
= radioSelected
.modID
682 if modSelected
!= self
.demoModules
.GetActiveID():
683 busy
= wx
.BusyInfo("Reloading demo module...")
684 self
.demoModules
.SetActive(modSelected
)
685 self
.ActiveModuleChanged()
688 def ReloadDemo(self
):
689 if self
.demoModules
.name
!= __name__
:
690 self
.mainFrame
.RunModule()
693 def OnCodeModified(self
, event
):
694 self
.btnSave
.Enable(self
.editor
.IsModified())
697 def OnSave(self
, event
):
698 if self
.demoModules
.Exists(modModified
):
699 if self
.demoModules
.GetActiveID() == modOriginal
:
700 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
701 "Do you want to continue?"
702 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
703 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
704 result
= dlg
.ShowModal()
705 if result
== wx
.ID_NO
:
709 self
.demoModules
.SetActive(modModified
)
710 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
712 # Create the demo directory if one doesn't already exist
713 if not os
.path
.exists(GetModifiedDirectory()):
715 os
.makedirs(GetModifiedDirectory())
716 if not os
.path
.exists(GetModifiedDirectory()):
717 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
720 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
723 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
726 f
= open(modifiedFilename
, "wt")
727 source
= self
.editor
.GetText()
733 busy
= wx
.BusyInfo("Reloading demo module...")
734 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
735 self
.ActiveModuleChanged()
738 def OnRestore(self
, event
): # Handles the "Delete Modified" button
739 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
740 self
.demoModules
.Delete(modModified
)
741 os
.unlink(modifiedFilename
) # Delete the modified copy
742 busy
= wx
.BusyInfo("Reloading demo module...")
743 self
.ActiveModuleChanged()
746 #---------------------------------------------------------------------------
749 """Convert paths to the platform-specific separator"""
750 str = apply(os
.path
.join
, tuple(path
.split('/')))
751 # HACK: on Linux, a leading / gets lost...
752 if path
.startswith('/'):
757 def GetModifiedDirectory():
759 Returns the directory where modified versions of the demo files
762 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
765 def GetModifiedFilename(name
):
767 Returns the filename of the modified version of the specified demo
769 if not name
.endswith(".py"):
771 return GetModifiedDirectory() + name
774 def GetOriginalFilename(name
):
776 Returns the filename of the original version of the specified demo
778 if not name
.endswith(".py"):
783 def DoesModifiedExist(name
):
784 """Returns whether the specified demo has a modified copy"""
785 if os
.path
.exists(GetModifiedFilename(name
)):
791 #---------------------------------------------------------------------------
793 class ModuleDictWrapper
:
794 """Emulates a module with a dynamically compiled __dict__"""
795 def __init__(self
, dict):
798 def __getattr__(self
, name
):
799 if name
in self
.dict:
800 return self
.dict[name
]
806 Dynamically manages the original/modified versions of a demo
809 def __init__(self
, name
):
813 # (dict , source , filename , description , error information )
814 # ( 0 , 1 , 2 , 3 , 4 )
815 self
.modules
= [[None, "" , "" , "<original>" , None],
816 [None, "" , "" , "<modified>" , None]]
818 # load original module
819 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
820 self
.SetActive(modOriginal
)
822 # load modified module (if one exists)
823 if DoesModifiedExist(name
):
824 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
827 def LoadFromFile(self
, modID
, filename
):
828 self
.modules
[modID
][2] = filename
829 file = open(filename
, "rt")
830 self
.LoadFromSource(modID
, file.read())
834 def LoadFromSource(self
, modID
, source
):
835 self
.modules
[modID
][1] = source
839 def LoadDict(self
, modID
):
840 if self
.name
!= __name__
:
841 source
= self
.modules
[modID
][1]
842 #description = self.modules[modID][3]
843 description
= self
.modules
[modID
][2]
846 self
.modules
[modID
][0] = {}
847 code
= compile(source
, description
, "exec")
848 exec code
in self
.modules
[modID
][0]
850 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
851 self
.modules
[modID
][0] = None
853 self
.modules
[modID
][4] = None
856 def SetActive(self
, modID
):
857 if modID
!= modOriginal
and modID
!= modModified
:
860 self
.modActive
= modID
864 dict = self
.modules
[self
.modActive
][0]
868 return ModuleDictWrapper(dict)
871 def GetActiveID(self
):
872 return self
.modActive
875 def GetSource(self
, modID
= None):
877 modID
= self
.modActive
878 return self
.modules
[modID
][1]
881 def GetFilename(self
, modID
= None):
883 modID
= self
.modActive
884 return self
.modules
[self
.modActive
][2]
887 def GetErrorInfo(self
, modID
= None):
889 modID
= self
.modActive
890 return self
.modules
[self
.modActive
][4]
893 def Exists(self
, modID
):
894 return self
.modules
[modID
][1] != ""
897 def UpdateFile(self
, modID
= None):
898 """Updates the file from which a module was loaded
899 with (possibly updated) source"""
901 modID
= self
.modActive
903 source
= self
.modules
[modID
][1]
904 filename
= self
.modules
[modID
][2]
907 file = open(filename
, "wt")
913 def Delete(self
, modID
):
914 if self
.modActive
== modID
:
917 self
.modules
[modID
][0] = None
918 self
.modules
[modID
][1] = ""
919 self
.modules
[modID
][2] = ""
922 #---------------------------------------------------------------------------
925 """Wraps and stores information about the current exception"""
926 def __init__(self
, exc_info
):
929 excType
, excValue
= exc_info
[:2]
930 # traceback list entries: (filename, line number, function name, text)
931 self
.traceback
= traceback
.extract_tb(exc_info
[2])
933 # --Based on traceback.py::format_exception_only()--
934 if type(excType
) == types
.ClassType
:
935 self
.exception_type
= excType
.__name
__
937 self
.exception_type
= excType
939 # If it's a syntax error, extra information needs
940 # to be added to the traceback
941 if excType
is SyntaxError:
943 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
948 filename
= "<string>"
950 self
.traceback
.append( (filename
, lineno
, "", line
) )
953 self
.exception_details
= str(excValue
)
955 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
962 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
965 #---------------------------------------------------------------------------
967 class DemoErrorPanel(wx
.Panel
):
968 """Panel put into the demo tab when the demo fails to run due to errors"""
970 def __init__(self
, parent
, codePanel
, demoError
, log
):
971 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
972 self
.codePanel
= codePanel
976 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
979 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
980 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
982 # Exception Information
983 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
984 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
985 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
986 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
987 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
988 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
989 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
990 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
991 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
992 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
994 # Set up the traceback list
995 # This one automatically resizes last column to take up remaining space
996 from ListCtrl
import TestListCtrl
997 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
998 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
999 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
1000 self
.list.InsertColumn(0, "Filename")
1001 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
1002 self
.list.InsertColumn(2, "Function")
1003 self
.list.InsertColumn(3, "Code")
1004 self
.InsertTraceback(self
.list, demoError
.traceback
)
1005 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
1006 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
1007 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
1008 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
1009 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
1010 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
1011 + "Double-click on them to go to the offending line")
1012 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
1015 self
.SetSizer(self
.box
)
1018 def InsertTraceback(self
, list, traceback
):
1019 #Add the traceback data
1020 for x
in range(len(traceback
)):
1022 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1023 list.SetStringItem(x
, 1, str(data
[1])) # Line
1024 list.SetStringItem(x
, 2, str(data
[2])) # Function
1025 list.SetStringItem(x
, 3, str(data
[3])) # Code
1027 # Check whether this entry is from the demo module
1028 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1029 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1030 # Give it a blue colour
1031 item
= self
.list.GetItem(x
)
1032 item
.SetTextColour(wx
.BLUE
)
1033 self
.list.SetItem(item
)
1035 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1038 def OnItemSelected(self
, event
):
1039 # This occurs before OnDoubleClick and can be used to set the
1040 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1041 self
.currentItem
= event
.m_itemIndex
1045 def OnDoubleClick(self
, event
):
1046 # If double-clicking on a demo's entry, jump to the line number
1047 line
= self
.list.GetItemData(self
.currentItem
)
1049 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1050 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1054 #---------------------------------------------------------------------------
1056 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1057 TBMENU_RESTORE
= wx
.NewId()
1058 TBMENU_CLOSE
= wx
.NewId()
1059 TBMENU_CHANGE
= wx
.NewId()
1060 TBMENU_REMOVE
= wx
.NewId()
1062 def __init__(self
, frame
):
1063 wx
.TaskBarIcon
.__init
__(self
)
1067 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1068 self
.SetIcon(icon
, "wxPython Demo")
1072 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1073 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1074 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1075 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1076 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1079 def CreatePopupMenu(self
):
1081 This method is called by the base class when it needs to popup
1082 the menu for the default EVT_RIGHT_DOWN event. Just create
1083 the menu how you want it and return it from this function,
1084 the base class takes care of the rest.
1087 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1088 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1089 menu
.AppendSeparator()
1090 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1091 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1095 def MakeIcon(self
, img
):
1097 The various platforms have different requirements for the
1100 if "wxMSW" in wx
.PlatformInfo
:
1101 img
= img
.Scale(16, 16)
1102 elif "wxGTK" in wx
.PlatformInfo
:
1103 img
= img
.Scale(22, 22)
1104 # wxMac can be any size upto 128x128, so leave the source img alone....
1105 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1109 def OnTaskBarActivate(self
, evt
):
1110 if self
.frame
.IsIconized():
1111 self
.frame
.Iconize(False)
1112 if not self
.frame
.IsShown():
1113 self
.frame
.Show(True)
1117 def OnTaskBarClose(self
, evt
):
1121 def OnTaskBarChange(self
, evt
):
1122 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1123 name
= names
[self
.imgidx
]
1125 getFunc
= getattr(images
, "get%sImage" % name
)
1127 if self
.imgidx
>= len(names
):
1130 icon
= self
.MakeIcon(getFunc())
1131 self
.SetIcon(icon
, "This is a new icon: " + name
)
1134 def OnTaskBarRemove(self
, evt
):
1138 #---------------------------------------------------------------------------
1139 class wxPythonDemo(wx
.Frame
):
1140 overviewText
= "wxPython Overview"
1142 def __init__(self
, parent
, title
):
1143 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1144 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1146 self
.SetMinSize((640,480))
1149 self
.cwd
= os
.getcwd()
1150 self
.curOverview
= ""
1151 self
.demoPage
= None
1152 self
.codePage
= None
1154 self
.firstTime
= True
1157 icon
= images
.getWXPdemoIcon()
1161 self
.tbicon
= DemoTaskBarIcon(self
)
1165 wx
.CallAfter(self
.ShowTip
)
1167 self
.otherWin
= None
1168 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1169 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1170 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1171 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1173 self
.Centre(wx
.BOTH
)
1174 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1176 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1177 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1179 def EmptyHandler(evt
): pass
1180 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1181 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1183 # Prevent TreeCtrl from displaying all items after destruction when True
1187 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1190 self
.mainmenu
= wx
.MenuBar()
1192 item
= menu
.Append(-1, '&Redirect Output',
1193 'Redirect print statements to a window',
1195 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1197 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1198 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1199 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1200 self
.mainmenu
.Append(menu
, '&File')
1204 for item
in _treeList
:
1206 for childItem
in item
[1]:
1207 mi
= submenu
.Append(-1, childItem
)
1208 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1209 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1210 self
.mainmenu
.Append(menu
, '&Demo')
1215 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1216 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1217 menu
.AppendSeparator()
1219 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1220 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1221 menu
.AppendSeparator()
1222 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1223 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1225 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1226 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1227 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1228 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1229 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1230 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1231 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1232 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1233 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1234 self
.mainmenu
.Append(menu
, '&Help')
1235 self
.SetMenuBar(self
.mainmenu
)
1237 self
.finddata
= wx
.FindReplaceData()
1238 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1241 # This is another way to set Accelerators, in addition to
1242 # using the '\t<key>' syntax in the menu items.
1243 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1244 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1245 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1246 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1248 self
.SetAcceleratorTable(aTable
)
1254 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1255 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1258 root
= self
.tree
.AddRoot("wxPython Overview")
1260 for item
in _treeList
:
1261 child
= self
.tree
.AppendItem(root
, item
[0])
1262 if not firstChild
: firstChild
= child
1263 for childItem
in item
[1]:
1264 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1265 self
.treeMap
[childItem
] = theDemo
1267 self
.tree
.Expand(root
)
1268 self
.tree
.Expand(firstChild
)
1269 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1270 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1271 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1272 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1274 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1275 # we put it in a panel first because there seems to be a
1276 # refresh bug of some sort (wxGTK) when it is directly in
1279 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1280 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1282 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1283 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1284 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1285 self
.nb
.AddPage(panel
, self
.overviewText
)
1287 def OnOvrSize(evt
, ovr
=self
.ovr
):
1288 ovr
.SetSize(evt
.GetSize())
1289 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1290 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1292 if "gtk2" in wx
.PlatformInfo
:
1293 self
.ovr
.SetStandardFonts()
1294 self
.SetOverview(self
.overviewText
, mainOverview
)
1297 # Set up a log window
1298 self
.log
= wx
.TextCtrl(splitter2
, -1,
1299 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1301 # Set the wxWindows log target to be this textctrl
1302 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1304 # But instead of the above we want to show how to use our own wx.Log class
1305 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1307 # for serious debugging
1308 #wx.Log_SetActiveTarget(wx.LogStderr())
1309 #wx.Log_SetTraceMask(wx.TraceMessages)
1312 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1313 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1315 # add the windows to the splitter and split it.
1316 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1317 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1319 splitter
.SetMinimumPaneSize(120)
1320 splitter2
.SetMinimumPaneSize(60)
1322 # Make the splitter on the right expand the top window when resized
1323 def SplitterOnSize(evt
):
1324 splitter
= evt
.GetEventObject()
1325 sz
= splitter
.GetSize()
1326 splitter
.SetSashPosition(sz
.height
- 160, False)
1329 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1331 # select initial items
1332 self
.nb
.SetSelection(0)
1333 self
.tree
.SelectItem(root
)
1335 # Load 'Main' module
1336 self
.LoadDemo(self
.overviewText
)
1339 # select some other initial module?
1340 if len(sys
.argv
) > 1:
1342 if arg
.endswith('.py'):
1344 selectedDemo
= self
.treeMap
.get(arg
, None)
1346 self
.tree
.SelectItem(selectedDemo
)
1347 self
.tree
.EnsureVisible(selectedDemo
)
1350 #---------------------------------------------
1351 def WriteText(self
, text
):
1352 if text
[-1:] == '\n':
1356 def write(self
, txt
):
1359 #---------------------------------------------
1360 def OnItemExpanded(self
, event
):
1361 item
= event
.GetItem()
1362 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1365 #---------------------------------------------
1366 def OnItemCollapsed(self
, event
):
1367 item
= event
.GetItem()
1368 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1371 #---------------------------------------------
1372 def OnTreeLeftDown(self
, event
):
1373 # reset the overview text if the tree item is clicked on again
1374 pt
= event
.GetPosition();
1375 item
, flags
= self
.tree
.HitTest(pt
)
1376 if item
== self
.tree
.GetSelection():
1377 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1380 #---------------------------------------------
1381 def OnSelChanged(self
, event
):
1382 if self
.dying
or not self
.loaded
:
1385 item
= event
.GetItem()
1386 itemText
= self
.tree
.GetItemText(item
)
1387 self
.LoadDemo(itemText
)
1389 #---------------------------------------------
1390 def LoadDemo(self
, demoName
):
1392 wx
.BeginBusyCursor()
1395 self
.ShutdownDemoModule()
1397 if demoName
== self
.overviewText
:
1398 # User selected the "wxPython Overview" node
1400 # Changing the main window at runtime not yet supported...
1401 self
.demoModules
= DemoModules(__name__
)
1402 self
.SetOverview(self
.overviewText
, mainOverview
)
1403 self
.LoadDemoSource()
1404 self
.UpdateNotebook(0)
1406 if os
.path
.exists(GetOriginalFilename(demoName
)):
1407 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1408 self
.demoModules
= DemoModules(demoName
)
1409 self
.LoadDemoSource()
1412 self
.SetOverview("wxPython", mainOverview
)
1413 self
.codePage
= None
1414 self
.UpdateNotebook(0)
1418 #---------------------------------------------
1419 def LoadDemoSource(self
):
1420 self
.codePage
= None
1421 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1422 self
.codePage
.LoadDemo(self
.demoModules
)
1424 #---------------------------------------------
1425 def RunModule(self
):
1426 """Runs the active module"""
1428 module
= self
.demoModules
.GetActive()
1429 self
.ShutdownDemoModule()
1432 # o The RunTest() for all samples must now return a window that can
1433 # be palced in a tab in the main notebook.
1434 # o If an error occurs (or has occurred before) an error tab is created.
1436 if module
is not None:
1437 wx
.LogMessage("Running demo module...")
1438 if hasattr(module
, "overview"):
1439 overviewText
= module
.overview
1442 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1444 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1445 DemoError(sys
.exc_info()), self
)
1447 assert self
.demoPage
is not None, "runTest must return a window!"
1450 # There was a previous error in compiling or exec-ing
1451 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1452 self
.demoModules
.GetErrorInfo(), self
)
1454 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1457 # cahnge to the demo page the first time a module is run
1458 self
.UpdateNotebook(2)
1459 self
.firstTime
= False
1461 # otherwise just stay on the same tab in case the user has changed to another one
1462 self
.UpdateNotebook()
1464 #---------------------------------------------
1465 def ShutdownDemoModule(self
):
1467 # inform the window that it's time to quit if it cares
1468 if hasattr(self
.demoPage
, "ShutdownDemo"):
1469 self
.demoPage
.ShutdownDemo()
1470 wx
.YieldIfNeeded() # in case the page has pending events
1471 self
.demoPage
= None
1473 #---------------------------------------------
1474 def UpdateNotebook(self
, select
= -1):
1478 def UpdatePage(page
, pageText
):
1481 for i
in range(nb
.GetPageCount()):
1482 if nb
.GetPageText(i
) == pageText
:
1490 nb
.AddPage(page
, pageText
)
1491 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1493 if nb
.GetPage(pagePos
) != page
:
1494 # Reload an existing page
1496 nb
.DeletePage(pagePos
)
1497 nb
.InsertPage(pagePos
, page
, pageText
)
1499 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1501 # Excellent! No redraw/flicker
1502 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1505 nb
.DeletePage(pagePos
)
1506 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1508 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1511 select
= nb
.GetSelection()
1513 UpdatePage(self
.codePage
, "Demo Code")
1514 UpdatePage(self
.demoPage
, "Demo")
1516 if select
>= 0 and select
< nb
.GetPageCount():
1517 nb
.SetSelection(select
)
1519 #---------------------------------------------
1520 def SetOverview(self
, name
, text
):
1521 self
.curOverview
= text
1523 if lead
!= '<html>' and lead
!= '<HTML>':
1524 text
= '<br>'.join(text
.split('\n'))
1526 text
= text
.decode('iso8859_1')
1527 self
.ovr
.SetPage(text
)
1528 self
.nb
.SetPageText(0, name
)
1530 #---------------------------------------------
1532 def OnFileExit(self
, *event
):
1535 def OnToggleRedirect(self
, event
):
1539 print "Print statements and other standard output will now be directed to this window."
1542 print "Print statements and other standard output will now be sent to the usual location."
1544 def OnHelpAbout(self
, event
):
1545 from About
import MyAboutBox
1546 about
= MyAboutBox(self
)
1550 def OnHelpFind(self
, event
):
1551 if self
.finddlg
!= None:
1554 self
.nb
.SetSelection(1)
1555 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1556 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1557 self
.finddlg
.Show(True)
1560 def OnUpdateFindItems(self
, evt
):
1561 evt
.Enable(self
.finddlg
== None)
1564 def OnFind(self
, event
):
1565 editor
= self
.codePage
.editor
1566 self
.nb
.SetSelection(1)
1567 end
= editor
.GetLastPosition()
1568 textstring
= editor
.GetRange(0, end
).lower()
1569 findstring
= self
.finddata
.GetFindString().lower()
1570 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1572 start
= editor
.GetSelection()[0]
1573 loc
= textstring
.rfind(findstring
, 0, start
)
1575 start
= editor
.GetSelection()[1]
1576 loc
= textstring
.find(findstring
, start
)
1577 if loc
== -1 and start
!= 0:
1578 # string not found, start at beginning
1581 loc
= textstring
.rfind(findstring
, 0, start
)
1584 loc
= textstring
.find(findstring
, start
)
1586 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1587 'Find String Not Found in Demo File',
1588 wx
.OK | wx
.ICON_INFORMATION
)
1593 self
.finddlg
.SetFocus()
1596 self
.finddlg
.Destroy()
1598 editor
.ShowPosition(loc
)
1599 editor
.SetSelection(loc
, loc
+ len(findstring
))
1603 def OnFindNext(self
, event
):
1604 if self
.finddata
.GetFindString():
1607 self
.OnHelpFind(event
)
1609 def OnFindClose(self
, event
):
1610 event
.GetDialog().Destroy()
1614 def OnOpenShellWindow(self
, evt
):
1616 # if it already exists then just make sure it's visible
1622 # Make a PyShell window
1624 namespace
= { 'wx' : wx
,
1625 'app' : wx
.GetApp(),
1628 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1629 self
.shell
.SetSize((640,480))
1632 # Hook the close event of the main frame window so that we
1633 # close the shell at the same time if it still exists
1634 def CloseShell(evt
):
1638 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1641 #---------------------------------------------
1642 def OnCloseWindow(self
, event
):
1644 self
.demoPage
= None
1645 self
.codePage
= None
1646 self
.mainmenu
= None
1647 if self
.tbicon
is not None:
1648 self
.tbicon
.Destroy()
1652 #---------------------------------------------
1653 def OnIdle(self
, event
):
1655 self
.otherWin
.Raise()
1656 self
.demoPage
= self
.otherWin
1657 self
.otherWin
= None
1660 #---------------------------------------------
1663 showTipText
= open(opj("data/showTips")).read()
1664 showTip
, index
= eval(showTipText
)
1666 showTip
, index
= (1, 0)
1668 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1670 showTip
= wx
.ShowTip(self
, tp
)
1671 index
= tp
.GetCurrentTip()
1672 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1675 #---------------------------------------------
1676 def OnDemoMenu(self
, event
):
1678 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1682 self
.tree
.SelectItem(selectedDemo
)
1683 self
.tree
.EnsureVisible(selectedDemo
)
1687 #---------------------------------------------
1688 def OnIconfiy(self
, evt
):
1689 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1692 #---------------------------------------------
1693 def OnMaximize(self
, evt
):
1694 wx
.LogMessage("OnMaximize")
1697 #---------------------------------------------
1698 def OnActivate(self
, evt
):
1699 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1702 #---------------------------------------------
1703 def OnAppActivate(self
, evt
):
1704 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1707 #---------------------------------------------------------------------------
1708 #---------------------------------------------------------------------------
1710 class MySplashScreen(wx
.SplashScreen
):
1712 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1713 wx
.SplashScreen
.__init
__(self
, bmp
,
1714 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1716 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1717 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1720 def OnClose(self
, evt
):
1721 # Make sure the default handler runs too so this window gets
1726 # if the timer is still running then go ahead and show the
1728 if self
.fc
.IsRunning():
1734 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1736 if self
.fc
.IsRunning():
1740 class MyApp(wx
.App
):
1743 Create and show the splash screen. It will then create and show
1744 the main frame when it is time to do so.
1747 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1750 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1752 # Normally when using a SplashScreen you would create it, show
1753 # it and then continue on with the applicaiton's
1754 # initialization, finally creating and showing the main
1755 # application window(s). In this case we have nothing else to
1756 # do so we'll delay showing the main frame until later (see
1757 # ShowMain above) so the users can see the SplashScreen effect.
1758 splash
= MySplashScreen()
1765 #---------------------------------------------------------------------------
1769 demoPath
= os
.path
.dirname(__file__
)
1776 #---------------------------------------------------------------------------
1779 mainOverview
= """<html><body>
1782 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1783 language. It allows Python programmers to create programs with a
1784 robust, highly functional graphical user interface, simply and easily.
1785 It is implemented as a Python extension module (native code) that
1786 wraps the popular wxWindows cross platform GUI library, which is
1789 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1790 means that it is free for anyone to use and the source code is
1791 available for anyone to look at and modify. Or anyone can contribute
1792 fixes or enhancements to the project.
1794 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1795 same program will run on multiple platforms without modification.
1796 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1797 or unix-like systems, and Macintosh OS X. Since the language is
1798 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1801 <p> <b>This demo</b> is not only a collection of test cases for
1802 wxPython, but is also designed to help you learn about and how to use
1803 wxPython. Each sample is listed in the tree control on the left.
1804 When a sample is selected in the tree then a module is loaded and run
1805 (usually in a tab of this notebook,) and the source code of the module
1806 is loaded in another tab for you to browse and learn from.
1811 #----------------------------------------------------------------------------
1812 #----------------------------------------------------------------------------
1814 if __name__
== '__main__':
1818 #----------------------------------------------------------------------------