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',
73 # managed windows == things with a (optional) caption you can close
74 ('Frames and Dialogs', [
75 'AUI_DockingWindowMgr',
100 # dialogs from libraries
103 'ScrolledMessageDialog',
107 ('Core Windows/Controls', [
144 ('"Book" Controls', [
153 ('Custom Controls', [
170 # controls coming from other libraries
171 ('More Windows/Controls', [
172 'ActiveX_FlashWindow',
173 'ActiveX_IEHtmlWindow',
175 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
178 'CheckListCtrlMixin',
193 'MaskedEditControls',
196 'MultiSplitterWindow',
213 # How to lay out the controls in a frame/dialog
223 'XmlResourceHandler',
224 'XmlResourceSubclass',
228 ('Process and Events', [
236 ##'infoframe', # needs better explanation and some fixing
240 ('Clipboard and DnD', [
266 ##'DialogUnits', # needs more explanations
285 ('Check out the samples dir too', [
292 #---------------------------------------------------------------------------
293 # Show how to derive a custom wxLog class
295 class MyLog(wx
.PyLog
):
296 def __init__(self
, textCtrl
, logTime
=0):
297 wx
.PyLog
.__init
__(self
)
299 self
.logTime
= logTime
301 def DoLogString(self
, message
, timeStamp
):
302 #print message, timeStamp
304 # message = time.strftime("%X", time.localtime(timeStamp)) + \
307 self
.tc
.AppendText(message
+ '\n')
310 class MyTP(wx
.PyTipProvider
):
312 return "This is my tip"
314 #---------------------------------------------------------------------------
315 # A class to be used to simply display a message in the demo pane
316 # rather than running the sample itself.
318 class MessagePanel(wx
.Panel
):
319 def __init__(self
, parent
, message
, caption
='', flags
=0):
320 wx
.Panel
.__init
__(self
, parent
)
325 if flags
& wx
.ICON_EXCLAMATION
:
326 artid
= wx
.ART_WARNING
327 elif flags
& wx
.ICON_ERROR
:
329 elif flags
& wx
.ICON_QUESTION
:
330 artid
= wx
.ART_QUESTION
331 elif flags
& wx
.ICON_INFORMATION
:
332 artid
= wx
.ART_INFORMATION
334 if artid
is not None:
335 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
336 icon
= wx
.StaticBitmap(self
, -1, bmp
)
338 icon
= (32,32) # make a spacer instead
341 caption
= wx
.StaticText(self
, -1, caption
)
342 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
344 message
= wx
.StaticText(self
, -1, message
)
346 # add to sizers for layout
347 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
353 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
360 box
= wx
.BoxSizer(wx
.VERTICAL
)
362 box
.Add(hbox
, 0, wx
.EXPAND
)
369 #---------------------------------------------------------------------------
370 # A class to be used to display source code in the demo. Try using the
371 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
372 # if there is an error, such as the stc module not being present.
376 ##raise ImportError # for testing the alternate implementation
378 from StyledTextCtrl_2
import PythonSTC
380 class DemoCodeEditor(PythonSTC
):
381 def __init__(self
, parent
):
382 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
385 # Some methods to make it compatible with how the wxTextCtrl is used
386 def SetValue(self
, value
):
388 value
= value
.decode('iso8859_1')
390 self
.EmptyUndoBuffer()
393 def IsModified(self
):
394 return self
.GetModify()
399 def SetInsertionPoint(self
, pos
):
400 self
.SetCurrentPos(pos
)
403 def ShowPosition(self
, pos
):
404 line
= self
.LineFromPosition(pos
)
405 #self.EnsureVisible(line)
408 def GetLastPosition(self
):
409 return self
.GetLength()
411 def GetPositionFromLine(self
, line
):
412 return self
.PositionFromLine(line
)
414 def GetRange(self
, start
, end
):
415 return self
.GetTextRange(start
, end
)
417 def GetSelection(self
):
418 return self
.GetAnchor(), self
.GetCurrentPos()
420 def SetSelection(self
, start
, end
):
421 self
.SetSelectionStart(start
)
422 self
.SetSelectionEnd(end
)
424 def SelectLine(self
, line
):
425 start
= self
.PositionFromLine(line
)
426 end
= self
.GetLineEndPosition(line
)
427 self
.SetSelection(start
, end
)
429 def SetUpEditor(self
):
431 This method carries out the work of setting up the demo editor.
432 It's seperate so as not to clutter up the init code.
436 self
.SetLexer(stc
.STC_LEX_PYTHON
)
437 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
440 self
.SetProperty("fold", "1" )
442 # Highlight tab/space mixing (shouldn't be any)
443 self
.SetProperty("tab.timmy.whinge.level", "1")
445 # Set left and right margins
448 # Set up the numbers in the margin for margin #1
449 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
450 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
451 self
.SetMarginWidth(1, 40)
453 # Indentation and tab stuff
454 self
.SetIndent(4) # Proscribed indent size for wx
455 self
.SetIndentationGuides(True) # Show indent guides
456 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
457 self
.SetTabIndents(True) # Tab key indents
458 self
.SetTabWidth(4) # Proscribed tab size for wx
459 self
.SetUseTabs(False) # Use spaces rather than tabs, or
460 # TabTimmy will complain!
462 self
.SetViewWhiteSpace(False) # Don't view white space
464 # EOL: Since we are loading/saving ourselves, and the
465 # strings will always have \n's in them, set the STC to
466 # edit them that way.
467 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
468 self
.SetViewEOL(False)
470 # No right-edge mode indicator
471 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
473 # Setup a margin to hold fold markers
474 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
475 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
476 self
.SetMarginSensitive(2, True)
477 self
.SetMarginWidth(2, 12)
479 # and now set up the fold markers
480 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
481 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
482 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
483 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
484 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
485 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
486 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
488 # Global default style
489 if wx
.Platform
== '__WXMSW__':
490 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
491 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
493 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
494 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
496 # Clear styles and revert to default.
499 # Following style specs only indicate differences from default.
500 # The rest remains unchanged.
502 # Line numbers in margin
503 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
505 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
507 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
509 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
512 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
514 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
515 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
517 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
518 # Strings and characters
519 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
520 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
522 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
524 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
525 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
527 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
529 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
531 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
532 # Identifiers. I leave this as not bold because everything seems
533 # to be an identifier if it doesn't match the above criterae
534 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
537 self
.SetCaretForeground("BLUE")
538 # Selection background
539 self
.SetSelBackground(1, '#66CCFF')
541 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
542 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
544 def RegisterModifiedEvent(self
, eventHandler
):
545 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
549 class DemoCodeEditor(wx
.TextCtrl
):
550 def __init__(self
, parent
):
551 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
552 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
554 def RegisterModifiedEvent(self
, eventHandler
):
555 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
557 def SetReadOnly(self
, flag
):
558 self
.SetEditable(not flag
)
559 # NOTE: STC already has this method
562 return self
.GetValue()
564 def GetPositionFromLine(self
, line
):
565 return self
.XYToPosition(0,line
)
567 def GotoLine(self
, line
):
568 pos
= self
.GetPositionFromLine(line
)
569 self
.SetInsertionPoint(pos
)
570 self
.ShowPosition(pos
)
572 def SelectLine(self
, line
):
573 start
= self
.GetPositionFromLine(line
)
574 end
= start
+ self
.GetLineLength(line
)
575 self
.SetSelection(start
, end
)
578 #---------------------------------------------------------------------------
579 # Constants for module versions
583 modDefault
= modOriginal
585 #---------------------------------------------------------------------------
587 class DemoCodePanel(wx
.Panel
):
588 """Panel for the 'Demo Code' tab"""
589 def __init__(self
, parent
, mainFrame
):
590 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
591 if 'wxMSW' in wx
.PlatformInfo
:
593 self
.mainFrame
= mainFrame
594 self
.editor
= DemoCodeEditor(self
)
595 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
597 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
598 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
599 self
.btnSave
.Enable(False)
600 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
601 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
603 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
604 modModified
: wx
.RadioButton(self
, -1, "Modified") }
606 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
607 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
608 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
609 for modID
, radioButton
in self
.radioButtons
.items():
610 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
611 radioButton
.modID
= modID
# makes it easier for the event handler
612 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
614 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
615 self
.controlBox
.Add(self
.btnRestore
, 0)
617 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
618 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
619 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
620 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
623 self
.SetSizer(self
.box
)
626 # Loads a demo from a DemoModules object
627 def LoadDemo(self
, demoModules
):
628 self
.demoModules
= demoModules
629 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
630 demoModules
.SetActive(modModified
)
632 demoModules
.SetActive(modOriginal
)
633 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
634 self
.ActiveModuleChanged()
637 def ActiveModuleChanged(self
):
638 self
.LoadDemoSource(self
.demoModules
.GetSource())
639 self
.UpdateControlState()
643 def LoadDemoSource(self
, source
):
645 self
.editor
.SetValue(source
)
647 self
.btnSave
.Enable(False)
650 def JumpToLine(self
, line
, highlight
=False):
651 self
.editor
.GotoLine(line
)
652 self
.editor
.SetFocus()
654 self
.editor
.SelectLine(line
)
657 def UpdateControlState(self
):
658 active
= self
.demoModules
.GetActiveID()
659 # Update the radio/restore buttons
660 for moduleID
in self
.radioButtons
:
661 btn
= self
.radioButtons
[moduleID
]
662 if moduleID
== active
:
667 if self
.demoModules
.Exists(moduleID
):
669 if moduleID
== modModified
:
670 self
.btnRestore
.Enable(True)
673 if moduleID
== modModified
:
674 self
.btnRestore
.Enable(False)
677 def OnRadioButton(self
, event
):
678 radioSelected
= event
.GetEventObject()
679 modSelected
= radioSelected
.modID
680 if modSelected
!= self
.demoModules
.GetActiveID():
681 busy
= wx
.BusyInfo("Reloading demo module...")
682 self
.demoModules
.SetActive(modSelected
)
683 self
.ActiveModuleChanged()
686 def ReloadDemo(self
):
687 if self
.demoModules
.name
!= __name__
:
688 self
.mainFrame
.RunModule()
691 def OnCodeModified(self
, event
):
692 self
.btnSave
.Enable(self
.editor
.IsModified())
695 def OnSave(self
, event
):
696 if self
.demoModules
.Exists(modModified
):
697 if self
.demoModules
.GetActiveID() == modOriginal
:
698 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
699 "Do you want to continue?"
700 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
701 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
702 result
= dlg
.ShowModal()
703 if result
== wx
.ID_NO
:
707 self
.demoModules
.SetActive(modModified
)
708 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
710 # Create the demo directory if one doesn't already exist
711 if not os
.path
.exists(GetModifiedDirectory()):
713 os
.makedirs(GetModifiedDirectory())
714 if not os
.path
.exists(GetModifiedDirectory()):
715 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
718 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
721 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
724 f
= open(modifiedFilename
, "wt")
725 source
= self
.editor
.GetText()
731 busy
= wx
.BusyInfo("Reloading demo module...")
732 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
733 self
.ActiveModuleChanged()
736 def OnRestore(self
, event
): # Handles the "Delete Modified" button
737 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
738 self
.demoModules
.Delete(modModified
)
739 os
.unlink(modifiedFilename
) # Delete the modified copy
740 busy
= wx
.BusyInfo("Reloading demo module...")
741 self
.ActiveModuleChanged()
744 #---------------------------------------------------------------------------
747 """Convert paths to the platform-specific separator"""
748 str = apply(os
.path
.join
, tuple(path
.split('/')))
749 # HACK: on Linux, a leading / gets lost...
750 if path
.startswith('/'):
755 def GetModifiedDirectory():
757 Returns the directory where modified versions of the demo files
760 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
763 def GetModifiedFilename(name
):
765 Returns the filename of the modified version of the specified demo
767 if not name
.endswith(".py"):
769 return GetModifiedDirectory() + name
772 def GetOriginalFilename(name
):
774 Returns the filename of the original version of the specified demo
776 if not name
.endswith(".py"):
781 def DoesModifiedExist(name
):
782 """Returns whether the specified demo has a modified copy"""
783 if os
.path
.exists(GetModifiedFilename(name
)):
789 #---------------------------------------------------------------------------
791 class ModuleDictWrapper
:
792 """Emulates a module with a dynamically compiled __dict__"""
793 def __init__(self
, dict):
796 def __getattr__(self
, name
):
797 if name
in self
.dict:
798 return self
.dict[name
]
804 Dynamically manages the original/modified versions of a demo
807 def __init__(self
, name
):
811 # (dict , source , filename , description , error information )
812 # ( 0 , 1 , 2 , 3 , 4 )
813 self
.modules
= [[None, "" , "" , "<original>" , None],
814 [None, "" , "" , "<modified>" , None]]
816 # load original module
817 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
818 self
.SetActive(modOriginal
)
820 # load modified module (if one exists)
821 if DoesModifiedExist(name
):
822 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
825 def LoadFromFile(self
, modID
, filename
):
826 self
.modules
[modID
][2] = filename
827 file = open(filename
, "rt")
828 self
.LoadFromSource(modID
, file.read())
832 def LoadFromSource(self
, modID
, source
):
833 self
.modules
[modID
][1] = source
837 def LoadDict(self
, modID
):
838 if self
.name
!= __name__
:
839 source
= self
.modules
[modID
][1]
840 #description = self.modules[modID][3]
841 description
= self
.modules
[modID
][2]
844 self
.modules
[modID
][0] = {}
845 code
= compile(source
, description
, "exec")
846 exec code
in self
.modules
[modID
][0]
848 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
849 self
.modules
[modID
][0] = None
851 self
.modules
[modID
][4] = None
854 def SetActive(self
, modID
):
855 if modID
!= modOriginal
and modID
!= modModified
:
858 self
.modActive
= modID
862 dict = self
.modules
[self
.modActive
][0]
866 return ModuleDictWrapper(dict)
869 def GetActiveID(self
):
870 return self
.modActive
873 def GetSource(self
, modID
= None):
875 modID
= self
.modActive
876 return self
.modules
[modID
][1]
879 def GetFilename(self
, modID
= None):
881 modID
= self
.modActive
882 return self
.modules
[self
.modActive
][2]
885 def GetErrorInfo(self
, modID
= None):
887 modID
= self
.modActive
888 return self
.modules
[self
.modActive
][4]
891 def Exists(self
, modID
):
892 return self
.modules
[modID
][1] != ""
895 def UpdateFile(self
, modID
= None):
896 """Updates the file from which a module was loaded
897 with (possibly updated) source"""
899 modID
= self
.modActive
901 source
= self
.modules
[modID
][1]
902 filename
= self
.modules
[modID
][2]
905 file = open(filename
, "wt")
911 def Delete(self
, modID
):
912 if self
.modActive
== modID
:
915 self
.modules
[modID
][0] = None
916 self
.modules
[modID
][1] = ""
917 self
.modules
[modID
][2] = ""
920 #---------------------------------------------------------------------------
923 """Wraps and stores information about the current exception"""
924 def __init__(self
, exc_info
):
927 excType
, excValue
= exc_info
[:2]
928 # traceback list entries: (filename, line number, function name, text)
929 self
.traceback
= traceback
.extract_tb(exc_info
[2])
931 # --Based on traceback.py::format_exception_only()--
932 if type(excType
) == types
.ClassType
:
933 self
.exception_type
= excType
.__name
__
935 self
.exception_type
= excType
937 # If it's a syntax error, extra information needs
938 # to be added to the traceback
939 if excType
is SyntaxError:
941 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
946 filename
= "<string>"
948 self
.traceback
.append( (filename
, lineno
, "", line
) )
951 self
.exception_details
= str(excValue
)
953 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
960 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
963 #---------------------------------------------------------------------------
965 class DemoErrorPanel(wx
.Panel
):
966 """Panel put into the demo tab when the demo fails to run due to errors"""
968 def __init__(self
, parent
, codePanel
, demoError
, log
):
969 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
970 self
.codePanel
= codePanel
974 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
977 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
978 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
980 # Exception Information
981 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
982 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
983 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
984 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
985 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
986 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
987 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
988 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
989 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
990 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
992 # Set up the traceback list
993 # This one automatically resizes last column to take up remaining space
994 from ListCtrl
import TestListCtrl
995 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
996 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
997 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
998 self
.list.InsertColumn(0, "Filename")
999 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
1000 self
.list.InsertColumn(2, "Function")
1001 self
.list.InsertColumn(3, "Code")
1002 self
.InsertTraceback(self
.list, demoError
.traceback
)
1003 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
1004 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
1005 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
1006 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
1007 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
1008 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
1009 + "Double-click on them to go to the offending line")
1010 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
1013 self
.SetSizer(self
.box
)
1016 def InsertTraceback(self
, list, traceback
):
1017 #Add the traceback data
1018 for x
in range(len(traceback
)):
1020 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1021 list.SetStringItem(x
, 1, str(data
[1])) # Line
1022 list.SetStringItem(x
, 2, str(data
[2])) # Function
1023 list.SetStringItem(x
, 3, str(data
[3])) # Code
1025 # Check whether this entry is from the demo module
1026 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1027 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1028 # Give it a blue colour
1029 item
= self
.list.GetItem(x
)
1030 item
.SetTextColour(wx
.BLUE
)
1031 self
.list.SetItem(item
)
1033 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1036 def OnItemSelected(self
, event
):
1037 # This occurs before OnDoubleClick and can be used to set the
1038 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1039 self
.currentItem
= event
.m_itemIndex
1043 def OnDoubleClick(self
, event
):
1044 # If double-clicking on a demo's entry, jump to the line number
1045 line
= self
.list.GetItemData(self
.currentItem
)
1047 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1048 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1052 #---------------------------------------------------------------------------
1054 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1055 TBMENU_RESTORE
= wx
.NewId()
1056 TBMENU_CLOSE
= wx
.NewId()
1057 TBMENU_CHANGE
= wx
.NewId()
1058 TBMENU_REMOVE
= wx
.NewId()
1060 def __init__(self
, frame
):
1061 wx
.TaskBarIcon
.__init
__(self
)
1065 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1066 self
.SetIcon(icon
, "wxPython Demo")
1070 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1071 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1072 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1073 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1074 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1077 def CreatePopupMenu(self
):
1079 This method is called by the base class when it needs to popup
1080 the menu for the default EVT_RIGHT_DOWN event. Just create
1081 the menu how you want it and return it from this function,
1082 the base class takes care of the rest.
1085 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1086 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1087 menu
.AppendSeparator()
1088 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1089 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1093 def MakeIcon(self
, img
):
1095 The various platforms have different requirements for the
1098 if "wxMSW" in wx
.PlatformInfo
:
1099 img
= img
.Scale(16, 16)
1100 elif "wxGTK" in wx
.PlatformInfo
:
1101 img
= img
.Scale(22, 22)
1102 # wxMac can be any size upto 128x128, so leave the source img alone....
1103 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1107 def OnTaskBarActivate(self
, evt
):
1108 if self
.frame
.IsIconized():
1109 self
.frame
.Iconize(False)
1110 if not self
.frame
.IsShown():
1111 self
.frame
.Show(True)
1115 def OnTaskBarClose(self
, evt
):
1119 def OnTaskBarChange(self
, evt
):
1120 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1121 name
= names
[self
.imgidx
]
1123 getFunc
= getattr(images
, "get%sImage" % name
)
1125 if self
.imgidx
>= len(names
):
1128 icon
= self
.MakeIcon(getFunc())
1129 self
.SetIcon(icon
, "This is a new icon: " + name
)
1132 def OnTaskBarRemove(self
, evt
):
1136 #---------------------------------------------------------------------------
1137 class wxPythonDemo(wx
.Frame
):
1138 overviewText
= "wxPython Overview"
1140 def __init__(self
, parent
, title
):
1141 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1142 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1144 self
.SetMinSize((640,480))
1147 self
.cwd
= os
.getcwd()
1148 self
.curOverview
= ""
1149 self
.demoPage
= None
1150 self
.codePage
= None
1152 self
.firstTime
= True
1155 icon
= images
.getWXPdemoIcon()
1159 self
.tbicon
= DemoTaskBarIcon(self
)
1163 wx
.CallAfter(self
.ShowTip
)
1165 self
.otherWin
= None
1166 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1167 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1168 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1169 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1171 self
.Centre(wx
.BOTH
)
1172 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1174 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1175 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1177 def EmptyHandler(evt
): pass
1178 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1179 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1181 # Prevent TreeCtrl from displaying all items after destruction when True
1185 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1188 self
.mainmenu
= wx
.MenuBar()
1190 item
= menu
.Append(-1, '&Redirect Output',
1191 'Redirect print statements to a window',
1193 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1195 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1196 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1197 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1198 self
.mainmenu
.Append(menu
, '&File')
1202 for item
in _treeList
:
1204 for childItem
in item
[1]:
1205 mi
= submenu
.Append(-1, childItem
)
1206 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1207 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1208 self
.mainmenu
.Append(menu
, '&Demo')
1213 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1214 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1215 menu
.AppendSeparator()
1217 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1218 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1219 menu
.AppendSeparator()
1220 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1221 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1223 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1224 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1225 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1226 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1227 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1228 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1229 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1230 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1231 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1232 self
.mainmenu
.Append(menu
, '&Help')
1233 self
.SetMenuBar(self
.mainmenu
)
1235 self
.finddata
= wx
.FindReplaceData()
1236 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1239 # This is another way to set Accelerators, in addition to
1240 # using the '\t<key>' syntax in the menu items.
1241 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1242 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1243 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1244 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1246 self
.SetAcceleratorTable(aTable
)
1252 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1253 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1256 root
= self
.tree
.AddRoot("wxPython Overview")
1258 for item
in _treeList
:
1259 child
= self
.tree
.AppendItem(root
, item
[0])
1260 if not firstChild
: firstChild
= child
1261 for childItem
in item
[1]:
1262 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1263 self
.treeMap
[childItem
] = theDemo
1265 self
.tree
.Expand(root
)
1266 self
.tree
.Expand(firstChild
)
1267 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1268 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1269 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1270 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1272 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1273 # we put it in a panel first because there seems to be a
1274 # refresh bug of some sort (wxGTK) when it is directly in
1277 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1278 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1280 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1281 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1282 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1283 self
.nb
.AddPage(panel
, self
.overviewText
)
1285 def OnOvrSize(evt
, ovr
=self
.ovr
):
1286 ovr
.SetSize(evt
.GetSize())
1287 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1288 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1290 if "gtk2" in wx
.PlatformInfo
:
1291 self
.ovr
.SetStandardFonts()
1292 self
.SetOverview(self
.overviewText
, mainOverview
)
1295 # Set up a log window
1296 self
.log
= wx
.TextCtrl(splitter2
, -1,
1297 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1299 # Set the wxWindows log target to be this textctrl
1300 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1302 # But instead of the above we want to show how to use our own wx.Log class
1303 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1305 # for serious debugging
1306 #wx.Log_SetActiveTarget(wx.LogStderr())
1307 #wx.Log_SetTraceMask(wx.TraceMessages)
1310 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1311 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1313 # add the windows to the splitter and split it.
1314 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1315 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1317 splitter
.SetMinimumPaneSize(120)
1318 splitter2
.SetMinimumPaneSize(60)
1320 # Make the splitter on the right expand the top window when resized
1321 def SplitterOnSize(evt
):
1322 splitter
= evt
.GetEventObject()
1323 sz
= splitter
.GetSize()
1324 splitter
.SetSashPosition(sz
.height
- 160, False)
1327 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1329 # select initial items
1330 self
.nb
.SetSelection(0)
1331 self
.tree
.SelectItem(root
)
1333 # Load 'Main' module
1334 self
.LoadDemo(self
.overviewText
)
1337 # select some other initial module?
1338 if len(sys
.argv
) > 1:
1340 if arg
.endswith('.py'):
1342 selectedDemo
= self
.treeMap
.get(arg
, None)
1344 self
.tree
.SelectItem(selectedDemo
)
1345 self
.tree
.EnsureVisible(selectedDemo
)
1348 #---------------------------------------------
1349 def WriteText(self
, text
):
1350 if text
[-1:] == '\n':
1354 def write(self
, txt
):
1357 #---------------------------------------------
1358 def OnItemExpanded(self
, event
):
1359 item
= event
.GetItem()
1360 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1363 #---------------------------------------------
1364 def OnItemCollapsed(self
, event
):
1365 item
= event
.GetItem()
1366 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1369 #---------------------------------------------
1370 def OnTreeLeftDown(self
, event
):
1371 # reset the overview text if the tree item is clicked on again
1372 pt
= event
.GetPosition();
1373 item
, flags
= self
.tree
.HitTest(pt
)
1374 if item
== self
.tree
.GetSelection():
1375 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1378 #---------------------------------------------
1379 def OnSelChanged(self
, event
):
1380 if self
.dying
or not self
.loaded
:
1383 item
= event
.GetItem()
1384 itemText
= self
.tree
.GetItemText(item
)
1385 self
.LoadDemo(itemText
)
1387 #---------------------------------------------
1388 def LoadDemo(self
, demoName
):
1390 wx
.BeginBusyCursor()
1393 self
.ShutdownDemoModule()
1395 if demoName
== self
.overviewText
:
1396 # User selected the "wxPython Overview" node
1398 # Changing the main window at runtime not yet supported...
1399 self
.demoModules
= DemoModules(__name__
)
1400 self
.SetOverview(self
.overviewText
, mainOverview
)
1401 self
.LoadDemoSource()
1402 self
.UpdateNotebook(0)
1404 if os
.path
.exists(GetOriginalFilename(demoName
)):
1405 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1406 self
.demoModules
= DemoModules(demoName
)
1407 self
.LoadDemoSource()
1410 self
.SetOverview("wxPython", mainOverview
)
1411 self
.codePage
= None
1412 self
.UpdateNotebook(0)
1416 #---------------------------------------------
1417 def LoadDemoSource(self
):
1418 self
.codePage
= None
1419 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1420 self
.codePage
.LoadDemo(self
.demoModules
)
1422 #---------------------------------------------
1423 def RunModule(self
):
1424 """Runs the active module"""
1426 module
= self
.demoModules
.GetActive()
1427 self
.ShutdownDemoModule()
1430 # o The RunTest() for all samples must now return a window that can
1431 # be palced in a tab in the main notebook.
1432 # o If an error occurs (or has occurred before) an error tab is created.
1434 if module
is not None:
1435 wx
.LogMessage("Running demo module...")
1436 if hasattr(module
, "overview"):
1437 overviewText
= module
.overview
1440 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1442 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1443 DemoError(sys
.exc_info()), self
)
1445 assert self
.demoPage
is not None, "runTest must return a window!"
1448 # There was a previous error in compiling or exec-ing
1449 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1450 self
.demoModules
.GetErrorInfo(), self
)
1452 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1455 # cahnge to the demo page the first time a module is run
1456 self
.UpdateNotebook(2)
1457 self
.firstTime
= False
1459 # otherwise just stay on the same tab in case the user has changed to another one
1460 self
.UpdateNotebook()
1462 #---------------------------------------------
1463 def ShutdownDemoModule(self
):
1465 # inform the window that it's time to quit if it cares
1466 if hasattr(self
.demoPage
, "ShutdownDemo"):
1467 self
.demoPage
.ShutdownDemo()
1468 wx
.YieldIfNeeded() # in case the page has pending events
1469 self
.demoPage
= None
1471 #---------------------------------------------
1472 def UpdateNotebook(self
, select
= -1):
1476 def UpdatePage(page
, pageText
):
1479 for i
in range(nb
.GetPageCount()):
1480 if nb
.GetPageText(i
) == pageText
:
1488 nb
.AddPage(page
, pageText
)
1489 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1491 if nb
.GetPage(pagePos
) != page
:
1492 # Reload an existing page
1494 nb
.DeletePage(pagePos
)
1495 nb
.InsertPage(pagePos
, page
, pageText
)
1497 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1499 # Excellent! No redraw/flicker
1500 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1503 nb
.DeletePage(pagePos
)
1504 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1506 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1509 select
= nb
.GetSelection()
1511 UpdatePage(self
.codePage
, "Demo Code")
1512 UpdatePage(self
.demoPage
, "Demo")
1514 if select
>= 0 and select
< nb
.GetPageCount():
1515 nb
.SetSelection(select
)
1517 #---------------------------------------------
1518 def SetOverview(self
, name
, text
):
1519 self
.curOverview
= text
1521 if lead
!= '<html>' and lead
!= '<HTML>':
1522 text
= '<br>'.join(text
.split('\n'))
1524 text
= text
.decode('iso8859_1')
1525 self
.ovr
.SetPage(text
)
1526 self
.nb
.SetPageText(0, name
)
1528 #---------------------------------------------
1530 def OnFileExit(self
, *event
):
1533 def OnToggleRedirect(self
, event
):
1537 print "Print statements and other standard output will now be directed to this window."
1540 print "Print statements and other standard output will now be sent to the usual location."
1542 def OnHelpAbout(self
, event
):
1543 from About
import MyAboutBox
1544 about
= MyAboutBox(self
)
1548 def OnHelpFind(self
, event
):
1549 if self
.finddlg
!= None:
1552 self
.nb
.SetSelection(1)
1553 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1554 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1555 self
.finddlg
.Show(True)
1558 def OnUpdateFindItems(self
, evt
):
1559 evt
.Enable(self
.finddlg
== None)
1562 def OnFind(self
, event
):
1563 editor
= self
.codePage
.editor
1564 self
.nb
.SetSelection(1)
1565 end
= editor
.GetLastPosition()
1566 textstring
= editor
.GetRange(0, end
).lower()
1567 findstring
= self
.finddata
.GetFindString().lower()
1568 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1570 start
= editor
.GetSelection()[0]
1571 loc
= textstring
.rfind(findstring
, 0, start
)
1573 start
= editor
.GetSelection()[1]
1574 loc
= textstring
.find(findstring
, start
)
1575 if loc
== -1 and start
!= 0:
1576 # string not found, start at beginning
1579 loc
= textstring
.rfind(findstring
, 0, start
)
1582 loc
= textstring
.find(findstring
, start
)
1584 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1585 'Find String Not Found in Demo File',
1586 wx
.OK | wx
.ICON_INFORMATION
)
1591 self
.finddlg
.SetFocus()
1594 self
.finddlg
.Destroy()
1596 editor
.ShowPosition(loc
)
1597 editor
.SetSelection(loc
, loc
+ len(findstring
))
1601 def OnFindNext(self
, event
):
1602 if self
.finddata
.GetFindString():
1605 self
.OnHelpFind(event
)
1607 def OnFindClose(self
, event
):
1608 event
.GetDialog().Destroy()
1612 def OnOpenShellWindow(self
, evt
):
1614 # if it already exists then just make sure it's visible
1620 # Make a PyShell window
1622 namespace
= { 'wx' : wx
,
1623 'app' : wx
.GetApp(),
1626 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1627 self
.shell
.SetSize((640,480))
1630 # Hook the close event of the main frame window so that we
1631 # close the shell at the same time if it still exists
1632 def CloseShell(evt
):
1636 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1639 #---------------------------------------------
1640 def OnCloseWindow(self
, event
):
1642 self
.demoPage
= None
1643 self
.codePage
= None
1644 self
.mainmenu
= None
1645 if self
.tbicon
is not None:
1646 self
.tbicon
.Destroy()
1650 #---------------------------------------------
1651 def OnIdle(self
, event
):
1653 self
.otherWin
.Raise()
1654 self
.demoPage
= self
.otherWin
1655 self
.otherWin
= None
1658 #---------------------------------------------
1661 showTipText
= open(opj("data/showTips")).read()
1662 showTip
, index
= eval(showTipText
)
1664 showTip
, index
= (1, 0)
1666 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1668 showTip
= wx
.ShowTip(self
, tp
)
1669 index
= tp
.GetCurrentTip()
1670 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1673 #---------------------------------------------
1674 def OnDemoMenu(self
, event
):
1676 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1680 self
.tree
.SelectItem(selectedDemo
)
1681 self
.tree
.EnsureVisible(selectedDemo
)
1685 #---------------------------------------------
1686 def OnIconfiy(self
, evt
):
1687 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1690 #---------------------------------------------
1691 def OnMaximize(self
, evt
):
1692 wx
.LogMessage("OnMaximize")
1695 #---------------------------------------------
1696 def OnActivate(self
, evt
):
1697 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1700 #---------------------------------------------
1701 def OnAppActivate(self
, evt
):
1702 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1705 #---------------------------------------------------------------------------
1706 #---------------------------------------------------------------------------
1708 class MySplashScreen(wx
.SplashScreen
):
1710 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1711 wx
.SplashScreen
.__init
__(self
, bmp
,
1712 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1714 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1715 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1718 def OnClose(self
, evt
):
1719 # Make sure the default handler runs too so this window gets
1724 # if the timer is still running then go ahead and show the
1726 if self
.fc
.IsRunning():
1732 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1734 if self
.fc
.IsRunning():
1738 class MyApp(wx
.App
):
1741 Create and show the splash screen. It will then create and show
1742 the main frame when it is time to do so.
1745 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1748 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1750 # Normally when using a SplashScreen you would create it, show
1751 # it and then continue on with the applicaiton's
1752 # initialization, finally creating and showing the main
1753 # application window(s). In this case we have nothing else to
1754 # do so we'll delay showing the main frame until later (see
1755 # ShowMain above) so the users can see the SplashScreen effect.
1756 splash
= MySplashScreen()
1763 #---------------------------------------------------------------------------
1767 demoPath
= os
.path
.dirname(__file__
)
1774 #---------------------------------------------------------------------------
1777 mainOverview
= """<html><body>
1780 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1781 language. It allows Python programmers to create programs with a
1782 robust, highly functional graphical user interface, simply and easily.
1783 It is implemented as a Python extension module (native code) that
1784 wraps the popular wxWindows cross platform GUI library, which is
1787 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1788 means that it is free for anyone to use and the source code is
1789 available for anyone to look at and modify. Or anyone can contribute
1790 fixes or enhancements to the project.
1792 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1793 same program will run on multiple platforms without modification.
1794 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1795 or unix-like systems, and Macintosh OS X. Since the language is
1796 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1799 <p> <b>This demo</b> is not only a collection of test cases for
1800 wxPython, but is also designed to help you learn about and how to use
1801 wxPython. Each sample is listed in the tree control on the left.
1802 When a sample is selected in the tree then a module is loaded and run
1803 (usually in a tab of this notebook,) and the source code of the module
1804 is loaded in another tab for you to browse and learn from.
1809 #----------------------------------------------------------------------------
1810 #----------------------------------------------------------------------------
1812 if __name__
== '__main__':
1816 #----------------------------------------------------------------------------