sure of their origin or license. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@34322 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			1780 lines
		
	
	
		
			60 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1780 lines
		
	
	
		
			60 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/bin/env python
 | |
| #----------------------------------------------------------------------------
 | |
| # Name:         Main.py
 | |
| # Purpose:      Testing lots of stuff, controls, window types, etc.
 | |
| #
 | |
| # Author:       Robin Dunn
 | |
| #
 | |
| # Created:      A long time ago, in a galaxy far, far away...
 | |
| # RCS-ID:       $Id$
 | |
| # Copyright:    (c) 1999 by Total Control Software
 | |
| # Licence:      wxWindows license
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| # FIXME List:
 | |
| # * Problems with flickering related to ERASE_BACKGROUND
 | |
| #     and the splitters. Might be a problem with this 2.5 beta...?
 | |
| #     UPDATE: can't see on 2.5.2 GTK - maybe just a faster machine :)
 | |
| # * Demo Code menu?
 | |
| # * Annoying switching between tabs and resulting flicker
 | |
| #     how to replace a page in the notebook without deleting/adding?
 | |
| #     Where is SetPage!? tried freeze...tried reparent of dummy panel....
 | |
| 
 | |
| # TODO List:
 | |
| # * UI design more prefessional
 | |
| # * save file positions (new field in demoModules) (@ LoadDemoSource)
 | |
| # * Update main overview
 | |
| 
 | |
| # * Why don't we move _treeList into a separate module
 | |
| 
 | |
| import sys, os, time, traceback, types
 | |
| 
 | |
| import wx                  # This module uses the new wx namespace
 | |
| import wx.html
 | |
| 
 | |
| import images
 | |
| 
 | |
| # For debugging
 | |
| ##wx.Trap();
 | |
| ##print "wx.VERSION_STRING = ", wx.VERSION_STRING
 | |
| ##print os.getpid();
 | |
| ##raw_input("Press Enter...")
 | |
| 
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| _treeList = [
 | |
|     # new stuff
 | |
|     ('Recent Additions/Updates', [
 | |
|         'FoldPanelBar',
 | |
|         'GIFAnimationCtrl',
 | |
|         'HyperLinkCtrl',
 | |
|         ]),
 | |
| 
 | |
|     # managed windows == things with a (optional) caption you can close
 | |
|     ('Frames and Dialogs', [
 | |
|         'Dialog',
 | |
|         'Frame',
 | |
|         'MDIWindows',
 | |
|         'MiniFrame',
 | |
|         'Wizard',
 | |
|         ]),
 | |
| 
 | |
|     # the common dialogs
 | |
|     ('Common Dialogs', [
 | |
|         'ColourDialog',
 | |
|         'DirDialog',
 | |
|         'FileDialog',
 | |
|         'FindReplaceDialog',
 | |
|         'FontDialog',
 | |
|         'MessageDialog',
 | |
|         'MultiChoiceDialog',
 | |
|         'PageSetupDialog',
 | |
|         'PrintDialog',
 | |
|         'ProgressDialog',
 | |
|         'SingleChoiceDialog',
 | |
|         'TextEntryDialog',
 | |
|         ]),
 | |
| 
 | |
|     # dialogs from libraries
 | |
|     ('More Dialogs', [
 | |
|         'ImageBrowser',
 | |
|         'MultipleChoiceDialog',
 | |
|         'ScrolledMessageDialog',
 | |
|         ]),
 | |
| 
 | |
|     # core controls
 | |
|     ('Core Windows/Controls', [
 | |
|         'BitmapButton',
 | |
|         'Button',
 | |
|         'CheckBox',
 | |
|         'CheckListBox',
 | |
|         'Choice',
 | |
|         'Choicebook',
 | |
|         'ComboBox',
 | |
|         'Gauge',
 | |
|         'Grid',
 | |
|         'Grid_MegaExample',
 | |
|         'ListBox',
 | |
|         'ListCtrl',
 | |
|         'ListCtrl_virtual',
 | |
|         'ListCtrl_edit',
 | |
|         'Listbook',
 | |
|         'Menu',
 | |
|         'Notebook',
 | |
|         'PopupMenu',
 | |
|         'PopupWindow',
 | |
|         'RadioBox',
 | |
|         'RadioButton',
 | |
|         'SashWindow',
 | |
|         'ScrolledWindow',
 | |
|         'Slider',
 | |
|         'SpinButton',
 | |
|         'SpinCtrl',
 | |
|         'SplitterWindow',
 | |
|         'StaticBitmap',
 | |
|         'StaticBox',
 | |
|         'StaticText',
 | |
|         'StatusBar',
 | |
|         'StockButtons',
 | |
|         'TextCtrl',
 | |
|         'ToggleButton',
 | |
|         'ToolBar',
 | |
|         'TreeCtrl',
 | |
|         'Validator',
 | |
|         ]),
 | |
| 
 | |
|     ('Custom Controls', [
 | |
|         'AnalogClockWindow',
 | |
|         'ColourSelect',
 | |
|         'Editor',
 | |
|         'GenericButtons',
 | |
|         'GenericDirCtrl',
 | |
|         'LEDNumberCtrl',
 | |
|         'MultiSash',
 | |
|         'PopupControl',
 | |
|         'PyColourChooser',
 | |
|         'TreeListCtrl',
 | |
|     ]),
 | |
|     
 | |
|     # controls coming from other libraries
 | |
|     ('More Windows/Controls', [
 | |
|         'ActiveX_FlashWindow',
 | |
|         'ActiveX_IEHtmlWindow',
 | |
|         'ActiveX_PDFWindow',
 | |
|         #'RightTextCtrl',     deprecated as we have wxTE_RIGHT now.
 | |
|         'Calendar',
 | |
|         'CalendarCtrl',
 | |
|         'ContextHelp',
 | |
|         'DatePickerCtrl',
 | |
|         'DynamicSashWindow',
 | |
|         'EditableListBox',
 | |
|         'FancyText',
 | |
|         'FileBrowseButton',
 | |
|         'FloatBar',  
 | |
|         'FloatCanvas',
 | |
|         'FoldPanelBar',
 | |
|         'GIFAnimationCtrl',
 | |
|         'HtmlWindow',
 | |
|         'HyperLinkCtrl',
 | |
|         'IntCtrl',
 | |
|         'MediaCtrl',
 | |
|         'MVCTree',   
 | |
|         'MaskedEditControls',
 | |
|         'MaskedNumCtrl',
 | |
|         'MimeTypesManager',
 | |
|         'PyCrust',
 | |
|         'PyPlot',
 | |
|         'PyShell',
 | |
|         'ScrolledPanel',
 | |
|         'SplitTree',
 | |
|         'StyledTextCtrl_1',
 | |
|         'StyledTextCtrl_2',
 | |
|         'TablePrint',
 | |
|         'Throbber',
 | |
|         'Ticker',
 | |
|         'TimeCtrl',
 | |
|         'VListBox',
 | |
|         ]),
 | |
| 
 | |
|     # How to lay out the controls in a frame/dialog
 | |
|     ('Window Layout', [
 | |
|         'GridBagSizer',
 | |
|         'LayoutAnchors',
 | |
|         'LayoutConstraints',
 | |
|         'Layoutf',
 | |
|         'RowColSizer',
 | |
|         'ScrolledPanel',
 | |
|         'Sizers',
 | |
|         'XmlResource',
 | |
|         'XmlResourceHandler',
 | |
|         'XmlResourceSubclass',
 | |
|         ]),
 | |
| 
 | |
|     # ditto
 | |
|     ('Process and Events', [
 | |
|         'EventManager',
 | |
|         'KeyEvents',
 | |
|         'Process',
 | |
|         'PythonEvents',
 | |
|         'Threads',
 | |
|         'Timer',
 | |
|         ##'infoframe',    # needs better explanation and some fixing
 | |
|         ]),
 | |
| 
 | |
|     # Clipboard and DnD
 | |
|     ('Clipboard and DnD', [
 | |
|         'CustomDragAndDrop',
 | |
|         'DragAndDrop',
 | |
|         'URLDragAndDrop',
 | |
|         ]),
 | |
| 
 | |
|     # Images
 | |
|     ('Using Images', [
 | |
|         'ArtProvider',
 | |
|         'Cursor',
 | |
|         'DragImage',
 | |
|         'GIFAnimationCtrl',
 | |
|         'Image',
 | |
|         'ImageAlpha',
 | |
|         'ImageFromStream',
 | |
|         'Mask',
 | |
|         'Throbber',
 | |
|         ]),
 | |
| 
 | |
|     # Other stuff
 | |
|     ('Miscellaneous', [
 | |
|         'ColourDB',
 | |
|         ##'DialogUnits',   # needs more explanations
 | |
|         'DrawXXXList',
 | |
|         'FileHistory',
 | |
|         'FontEnumerator',
 | |
|         'Joystick',
 | |
|         'MouseGestures',
 | |
|         'OGL',
 | |
|         'PrintFramework',
 | |
|         'ShapedWindow',
 | |
|         'Sound',
 | |
|         'StandardPaths',
 | |
|         'Unicode',
 | |
|         ]),
 | |
| 
 | |
|     # need libs not coming with the demo
 | |
|     ('Samples using an external library', [
 | |
|         'GLCanvas',
 | |
|         ]),
 | |
| 
 | |
| 
 | |
|     ('Check out the samples dir too', [
 | |
|         ]),
 | |
| 
 | |
| ]
 | |
| 
 | |
| 
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # Show how to derive a custom wxLog class
 | |
| 
 | |
| class MyLog(wx.PyLog):
 | |
|     def __init__(self, textCtrl, logTime=0):
 | |
|         wx.PyLog.__init__(self)
 | |
|         self.tc = textCtrl
 | |
|         self.logTime = logTime
 | |
| 
 | |
|     def DoLogString(self, message, timeStamp):
 | |
|         #print message, timeStamp
 | |
|         #if self.logTime:
 | |
|         #    message = time.strftime("%X", time.localtime(timeStamp)) + \
 | |
|         #              ": " + message
 | |
|         if self.tc:
 | |
|             self.tc.AppendText(message + '\n')
 | |
| 
 | |
| 
 | |
| class MyTP(wx.PyTipProvider):
 | |
|     def GetTip(self):
 | |
|         return "This is my tip"
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # A class to be used to simply display a message in the demo pane
 | |
| # rather than running the sample itself.
 | |
| 
 | |
| class MessagePanel(wx.Panel):
 | |
|     def __init__(self, parent, message, caption='', flags=0):
 | |
|         wx.Panel.__init__(self, parent)
 | |
| 
 | |
|         # Make widgets
 | |
|         if flags:
 | |
|             artid = None
 | |
|             if flags & wx.ICON_EXCLAMATION:
 | |
|                 artid = wx.ART_WARNING            
 | |
|             elif flags & wx.ICON_ERROR:
 | |
|                 artid = wx.ART_ERROR
 | |
|             elif flags & wx.ICON_QUESTION:
 | |
|                 artid = wx.ART_QUESTION
 | |
|             elif flags & wx.ICON_INFORMATION:
 | |
|                 artid = wx.ART_INFORMATION
 | |
| 
 | |
|             if artid is not None:
 | |
|                 bmp = wx.ArtProvider.GetBitmap(artid, wx.ART_MESSAGE_BOX, (32,32))
 | |
|                 icon = wx.StaticBitmap(self, -1, bmp)
 | |
|             else:
 | |
|                 icon = (32,32) # make a spacer instead
 | |
| 
 | |
|         if caption:
 | |
|             caption = wx.StaticText(self, -1, caption)
 | |
|             caption.SetFont(wx.Font(28, wx.SWISS, wx.NORMAL, wx.BOLD))
 | |
| 
 | |
|         message = wx.StaticText(self, -1, message)
 | |
| 
 | |
|         # add to sizers for layout
 | |
|         tbox = wx.BoxSizer(wx.VERTICAL)
 | |
|         if caption:
 | |
|             tbox.Add(caption)
 | |
|             tbox.Add((10,10))
 | |
|         tbox.Add(message)
 | |
|         
 | |
|         hbox = wx.BoxSizer(wx.HORIZONTAL)
 | |
|         hbox.Add((10,10), 1)
 | |
|         hbox.Add(icon)
 | |
|         hbox.Add((10,10))
 | |
|         hbox.Add(tbox)
 | |
|         hbox.Add((10,10), 1)
 | |
| 
 | |
|         box = wx.BoxSizer(wx.VERTICAL)
 | |
|         box.Add((10,10), 1)
 | |
|         box.Add(hbox, 0, wx.EXPAND)
 | |
|         box.Add((10,10), 2)
 | |
| 
 | |
|         self.SetSizer(box)
 | |
|         self.Fit()
 | |
|         
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # A class to be used to display source code in the demo.  Try using the
 | |
| # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
 | |
| # if there is an error, such as the stc module not being present.
 | |
| #
 | |
| 
 | |
| try:
 | |
|     ##raise ImportError     # for testing the alternate implementation
 | |
|     from wx import stc
 | |
|     from StyledTextCtrl_2 import PythonSTC
 | |
| 
 | |
|     class DemoCodeEditor(PythonSTC):
 | |
|         def __init__(self, parent):
 | |
|             PythonSTC.__init__(self, parent, -1, style=wx.BORDER_NONE)
 | |
|             self.SetUpEditor()
 | |
| 
 | |
|         # Some methods to make it compatible with how the wxTextCtrl is used
 | |
|         def SetValue(self, value):
 | |
|             if wx.USE_UNICODE:
 | |
|                 value = value.decode('iso8859_1')
 | |
|             self.SetText(value)
 | |
|             self.EmptyUndoBuffer()
 | |
|             self.SetSavePoint()
 | |
| 
 | |
|         def IsModified(self):
 | |
|             return self.GetModify()
 | |
| 
 | |
|         def Clear(self):
 | |
|             self.ClearAll()
 | |
| 
 | |
|         def SetInsertionPoint(self, pos):
 | |
|             self.SetCurrentPos(pos)
 | |
|             self.SetAnchor(pos)
 | |
| 
 | |
|         def ShowPosition(self, pos):
 | |
|             line = self.LineFromPosition(pos)
 | |
|             #self.EnsureVisible(line)
 | |
|             self.GotoLine(line)
 | |
| 
 | |
|         def GetLastPosition(self):
 | |
|             return self.GetLength()
 | |
| 
 | |
|         def GetPositionFromLine(self, line):
 | |
|             return self.PositionFromLine(line)
 | |
| 
 | |
|         def GetRange(self, start, end):
 | |
|             return self.GetTextRange(start, end)
 | |
| 
 | |
|         def GetSelection(self):
 | |
|             return self.GetAnchor(), self.GetCurrentPos()
 | |
| 
 | |
|         def SetSelection(self, start, end):
 | |
|             self.SetSelectionStart(start)
 | |
|             self.SetSelectionEnd(end)
 | |
| 
 | |
|         def SelectLine(self, line):
 | |
|             start = self.PositionFromLine(line)
 | |
|             end = self.GetLineEndPosition(line)
 | |
|             self.SetSelection(start, end)
 | |
|             
 | |
|         def SetUpEditor(self):
 | |
|             """
 | |
|             This method carries out the work of setting up the demo editor.            
 | |
|             It's seperate so as not to clutter up the init code.
 | |
|             """
 | |
|             import keyword
 | |
|             
 | |
|             self.SetLexer(stc.STC_LEX_PYTHON)
 | |
|             self.SetKeyWords(0, " ".join(keyword.kwlist))
 | |
|     
 | |
|             # Enable folding
 | |
|             self.SetProperty("fold", "1" ) 
 | |
| 
 | |
|             # Highlight tab/space mixing (shouldn't be any)
 | |
|             self.SetProperty("tab.timmy.whinge.level", "1")
 | |
| 
 | |
|             # Set left and right margins
 | |
|             self.SetMargins(2,2)
 | |
|     
 | |
|             # Set up the numbers in the margin for margin #1
 | |
|             self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
 | |
|             # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
 | |
|             self.SetMarginWidth(1, 40)
 | |
|     
 | |
|             # Indentation and tab stuff
 | |
|             self.SetIndent(4)               # Proscribed indent size for wx
 | |
|             self.SetIndentationGuides(True) # Show indent guides
 | |
|             self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
 | |
|             self.SetTabIndents(True)        # Tab key indents
 | |
|             self.SetTabWidth(4)             # Proscribed tab size for wx
 | |
|             self.SetUseTabs(False)          # Use spaces rather than tabs, or
 | |
|                                             # TabTimmy will complain!    
 | |
|             # White space
 | |
|             self.SetViewWhiteSpace(False)   # Don't view white space
 | |
|     
 | |
|             # EOL: Since we are loading/saving ourselves, and the
 | |
|             # strings will always have \n's in them, set the STC to
 | |
|             # edit them that way.            
 | |
|             self.SetEOLMode(wx.stc.STC_EOL_LF)
 | |
|             self.SetViewEOL(False)
 | |
|             
 | |
|             # No right-edge mode indicator
 | |
|             self.SetEdgeMode(stc.STC_EDGE_NONE)
 | |
|     
 | |
|             # Setup a margin to hold fold markers
 | |
|             self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
 | |
|             self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
 | |
|             self.SetMarginSensitive(2, True)
 | |
|             self.SetMarginWidth(2, 12)
 | |
|     
 | |
|             # and now set up the fold markers
 | |
|             self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "black")
 | |
|             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "black")
 | |
|             self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,  "white", "black")
 | |
|             self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,  "white", "black")
 | |
|             self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,    "white", "black")
 | |
|             self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,  "white", "black")
 | |
|             self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS, "white", "black")
 | |
|     
 | |
|             # Global default style
 | |
|             if wx.Platform == '__WXMSW__':
 | |
|                 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, 
 | |
|                                   'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
 | |
|             else:
 | |
|                 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, 
 | |
|                                   'fore:#000000,back:#FFFFFF,face:Courier,size:12')
 | |
|     
 | |
|             # Clear styles and revert to default.
 | |
|             self.StyleClearAll()
 | |
| 
 | |
|             # Following style specs only indicate differences from default.
 | |
|             # The rest remains unchanged.
 | |
| 
 | |
|             # Line numbers in margin
 | |
|             self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')    
 | |
|             # Highlighted brace
 | |
|             self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
 | |
|             # Unmatched brace
 | |
|             self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
 | |
|             # Indentation guide
 | |
|             self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
 | |
|     
 | |
|             # Python styles
 | |
|             self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
 | |
|             # Comments
 | |
|             self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE,  'fore:#008000,back:#F0FFF0')
 | |
|             self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
 | |
|             # Numbers
 | |
|             self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
 | |
|             # Strings and characters
 | |
|             self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
 | |
|             self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
 | |
|             # Keywords
 | |
|             self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
 | |
|             # Triple quotes
 | |
|             self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
 | |
|             self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
 | |
|             # Class names
 | |
|             self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
 | |
|             # Function names
 | |
|             self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
 | |
|             # Operators
 | |
|             self.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
 | |
|             # Identifiers. I leave this as not bold because everything seems
 | |
|             # to be an identifier if it doesn't match the above criterae
 | |
|             self.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
 | |
| 
 | |
|             # Caret color
 | |
|             self.SetCaretForeground("BLUE")
 | |
|             # Selection background
 | |
|             self.SetSelBackground(1, '#66CCFF')
 | |
| 
 | |
|             self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
 | |
|             self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
 | |
| 
 | |
|         def RegisterModifiedEvent(self, eventHandler):
 | |
|             self.Bind(wx.stc.EVT_STC_CHANGE, eventHandler)
 | |
| 
 | |
| 
 | |
| except ImportError:
 | |
|     class DemoCodeEditor(wx.TextCtrl):
 | |
|         def __init__(self, parent):
 | |
|             wx.TextCtrl.__init__(self, parent, -1, style =
 | |
|                                  wx.TE_MULTILINE | wx.HSCROLL | wx.TE_RICH2 | wx.TE_NOHIDESEL)
 | |
| 
 | |
|         def RegisterModifiedEvent(self, eventHandler):
 | |
|             self.Bind(wx.EVT_TEXT, eventHandler)
 | |
| 
 | |
|         def SetReadOnly(self, flag):
 | |
|             self.SetEditable(not flag)
 | |
|             # NOTE: STC already has this method
 | |
|     
 | |
|         def GetText(self):
 | |
|             return self.GetValue()
 | |
| 
 | |
|         def GetPositionFromLine(self, line):
 | |
|             return self.XYToPosition(0,line)
 | |
| 
 | |
|         def GotoLine(self, line):
 | |
|             pos = self.GetPositionFromLine(line)
 | |
|             self.SetInsertionPoint(pos)
 | |
|             self.ShowPosition(pos)
 | |
| 
 | |
|         def SelectLine(self, line):
 | |
|             start = self.GetPositionFromLine(line)
 | |
|             end = start + self.GetLineLength(line)
 | |
|             self.SetSelection(start, end)
 | |
| 
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| # Constants for module versions
 | |
| 
 | |
| modOriginal = 0
 | |
| modModified = 1
 | |
| modDefault = modOriginal
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| class DemoCodePanel(wx.Panel):
 | |
|     """Panel for the 'Demo Code' tab"""
 | |
|     def __init__(self, parent, mainFrame):
 | |
|         wx.Panel.__init__(self, parent, size=(1,1))
 | |
|         if 'wxMSW' in wx.PlatformInfo:
 | |
|             self.Hide()
 | |
|         self.mainFrame = mainFrame
 | |
|         self.editor = DemoCodeEditor(self)
 | |
|         self.editor.RegisterModifiedEvent(self.OnCodeModified)
 | |
| 
 | |
|         self.btnSave = wx.Button(self, -1, "Save Changes")
 | |
|         self.btnRestore = wx.Button(self, -1, "Delete Modified")
 | |
|         self.btnSave.Enable(False)
 | |
|         self.btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
 | |
|         self.btnRestore.Bind(wx.EVT_BUTTON, self.OnRestore)
 | |
| 
 | |
|         self.radioButtons = { modOriginal: wx.RadioButton(self, -1, "Original", style = wx.RB_GROUP),
 | |
|                               modModified: wx.RadioButton(self, -1, "Modified") }
 | |
| 
 | |
|         self.controlBox = wx.BoxSizer(wx.HORIZONTAL)
 | |
|         self.controlBox.Add(wx.StaticText(self, -1, "Active Version:"), 0,
 | |
|                             wx.RIGHT | wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
 | |
|         for modID, radioButton in self.radioButtons.items():
 | |
|             self.controlBox.Add(radioButton, 0, wx.EXPAND | wx.RIGHT, 5)
 | |
|             radioButton.modID = modID # makes it easier for the event handler
 | |
|             radioButton.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton)
 | |
|             
 | |
|         self.controlBox.Add(self.btnSave, 0, wx.RIGHT, 5)
 | |
|         self.controlBox.Add(self.btnRestore, 0)
 | |
| 
 | |
|         self.box = wx.BoxSizer(wx.VERTICAL)
 | |
|         self.box.Add(self.controlBox, 0, wx.EXPAND)
 | |
|         self.box.Add(wx.StaticLine(self), 0, wx.EXPAND)
 | |
|         self.box.Add(self.editor, 1, wx.EXPAND)
 | |
|         
 | |
|         self.box.Fit(self)
 | |
|         self.SetSizer(self.box)
 | |
| 
 | |
| 
 | |
|     # Loads a demo from a DemoModules object
 | |
|     def LoadDemo(self, demoModules):
 | |
|         self.demoModules = demoModules
 | |
|         if (modDefault == modModified) and demoModules.Exists(modModified):
 | |
|             demoModules.SetActive(modModified)
 | |
|         else:
 | |
|             demoModules.SetActive(modOriginal)
 | |
|         self.radioButtons[demoModules.GetActiveID()].Enable(True)
 | |
|         self.ActiveModuleChanged()
 | |
| 
 | |
| 
 | |
|     def ActiveModuleChanged(self):
 | |
|         self.LoadDemoSource(self.demoModules.GetSource())
 | |
|         self.UpdateControlState()
 | |
|         self.ReloadDemo()
 | |
| 
 | |
|         
 | |
|     def LoadDemoSource(self, source):
 | |
|         self.editor.Clear()
 | |
|         self.editor.SetValue(source)
 | |
|         self.JumpToLine(0)
 | |
|         self.btnSave.Enable(False)
 | |
| 
 | |
| 
 | |
|     def JumpToLine(self, line, highlight=False):
 | |
|         self.editor.GotoLine(line)
 | |
|         self.editor.SetFocus()
 | |
|         if highlight:
 | |
|             self.editor.SelectLine(line)
 | |
|         
 | |
|        
 | |
|     def UpdateControlState(self):
 | |
|         active = self.demoModules.GetActiveID()
 | |
|         # Update the radio/restore buttons
 | |
|         for moduleID in self.radioButtons:
 | |
|             btn = self.radioButtons[moduleID]
 | |
|             if moduleID == active:
 | |
|                 btn.SetValue(True)
 | |
|             else:
 | |
|                 btn.SetValue(False)
 | |
| 
 | |
|             if self.demoModules.Exists(moduleID):
 | |
|                 btn.Enable(True)
 | |
|                 if moduleID == modModified:
 | |
|                     self.btnRestore.Enable(True)
 | |
|             else:
 | |
|                 btn.Enable(False)
 | |
|                 if moduleID == modModified:
 | |
|                     self.btnRestore.Enable(False)
 | |
| 
 | |
|                     
 | |
|     def OnRadioButton(self, event):
 | |
|         radioSelected = event.GetEventObject()
 | |
|         modSelected = radioSelected.modID
 | |
|         if modSelected != self.demoModules.GetActiveID():
 | |
|             busy = wx.BusyInfo("Reloading demo module...")
 | |
|             self.demoModules.SetActive(modSelected)
 | |
|             self.ActiveModuleChanged()
 | |
| 
 | |
| 
 | |
|     def ReloadDemo(self):
 | |
|         if self.demoModules.name != __name__:
 | |
|             self.mainFrame.RunModule()
 | |
| 
 | |
|                 
 | |
|     def OnCodeModified(self, event):
 | |
|         self.btnSave.Enable(self.editor.IsModified())
 | |
| 
 | |
|         
 | |
|     def OnSave(self, event):
 | |
|         if self.demoModules.Exists(modModified):
 | |
|             if self.demoModules.GetActiveID() == modOriginal:
 | |
|                 overwriteMsg = "You are about to overwrite an already existing modified copy\n" + \
 | |
|                                "Do you want to continue?"
 | |
|                 dlg = wx.MessageDialog(self, overwriteMsg, "wxPython Demo",
 | |
|                                        wx.YES_NO | wx.NO_DEFAULT| wx.ICON_EXCLAMATION)
 | |
|                 result = dlg.ShowModal()
 | |
|                 if result == wx.ID_NO:
 | |
|                     return
 | |
|                 dlg.Destroy()
 | |
|             
 | |
|         self.demoModules.SetActive(modModified)
 | |
|         modifiedFilename = GetModifiedFilename(self.demoModules.name)
 | |
| 
 | |
|         # Create the demo directory if one doesn't already exist
 | |
|         if not os.path.exists(GetModifiedDirectory()):
 | |
|             try:
 | |
|                 os.makedirs(GetModifiedDirectory())
 | |
|                 if not os.path.exists(GetModifiedDirectory()):
 | |
|                     wx.LogMessage("BUG: Created demo directory but it still doesn't exist")
 | |
|                     raise AssetionError
 | |
|             except:
 | |
|                 wx.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
 | |
|                 return
 | |
|             else:
 | |
|                 wx.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
 | |
|             
 | |
|         # Save
 | |
|         f = open(modifiedFilename, "wt")
 | |
|         source = self.editor.GetText()
 | |
|         try:
 | |
|             f.write(source)
 | |
|         finally:
 | |
|             f.close()
 | |
|             
 | |
|         busy = wx.BusyInfo("Reloading demo module...")
 | |
|         self.demoModules.LoadFromFile(modModified, modifiedFilename)
 | |
|         self.ActiveModuleChanged()
 | |
| 
 | |
| 
 | |
|     def OnRestore(self, event): # Handles the "Delete Modified" button
 | |
|         modifiedFilename = GetModifiedFilename(self.demoModules.name)
 | |
|         self.demoModules.Delete(modModified)
 | |
|         os.unlink(modifiedFilename) # Delete the modified copy
 | |
|         busy = wx.BusyInfo("Reloading demo module...")
 | |
|         self.ActiveModuleChanged()
 | |
| 
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| def opj(path):
 | |
|     """Convert paths to the platform-specific separator"""
 | |
|     str = apply(os.path.join, tuple(path.split('/')))
 | |
|     # HACK: on Linux, a leading / gets lost...
 | |
|     if path.startswith('/'):
 | |
|         str = '/' + str
 | |
|     return str
 | |
| 
 | |
| 
 | |
| def GetModifiedDirectory():
 | |
|     """
 | |
|     Returns the directory where modified versions of the demo files
 | |
|     are stored
 | |
|     """
 | |
|     return opj(wx.GetHomeDir() + "/.wxPyDemo/modified/")
 | |
| 
 | |
| 
 | |
| def GetModifiedFilename(name):
 | |
|     """
 | |
|     Returns the filename of the modified version of the specified demo
 | |
|     """
 | |
|     if not name.endswith(".py"):
 | |
|         name = name + ".py"
 | |
|     return GetModifiedDirectory() + name
 | |
| 
 | |
| 
 | |
| def GetOriginalFilename(name):
 | |
|     """
 | |
|     Returns the filename of the original version of the specified demo
 | |
|     """
 | |
|     if not name.endswith(".py"):
 | |
|         name = name + ".py"
 | |
|     return name
 | |
| 
 | |
| 
 | |
| def DoesModifiedExist(name):
 | |
|     """Returns whether the specified demo has a modified copy"""
 | |
|     if os.path.exists(GetModifiedFilename(name)):
 | |
|         return True
 | |
|     else:
 | |
|         return False
 | |
| 
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| class ModuleDictWrapper:
 | |
|     """Emulates a module with a dynamically compiled __dict__"""
 | |
|     def __init__(self, dict):
 | |
|         self.dict = dict
 | |
|         
 | |
|     def __getattr__(self, name):
 | |
|         if name in self.dict:
 | |
|             return self.dict[name]
 | |
|         else:
 | |
|             raise AttributeError
 | |
| 
 | |
| class DemoModules:
 | |
|     """
 | |
|     Dynamically manages the original/modified versions of a demo
 | |
|     module
 | |
|     """
 | |
|     def __init__(self, name):
 | |
|         self.modActive = -1
 | |
|         self.name = name
 | |
|         
 | |
|         #              (dict , source ,  filename , description   , error information )        
 | |
|         #              (  0  ,   1    ,     2     ,      3        ,          4        )        
 | |
|         self.modules = [[None,  ""    ,    ""     , "<original>"  ,        None],
 | |
|                         [None,  ""    ,    ""     , "<modified>"  ,        None]]
 | |
|         
 | |
|         # load original module
 | |
|         self.LoadFromFile(modOriginal, GetOriginalFilename(name))
 | |
|         self.SetActive(modOriginal)
 | |
| 
 | |
|         # load modified module (if one exists)
 | |
|         if DoesModifiedExist(name):
 | |
|            self.LoadFromFile(modModified, GetModifiedFilename(name))
 | |
| 
 | |
| 
 | |
|     def LoadFromFile(self, modID, filename):
 | |
|         self.modules[modID][2] = filename
 | |
|         file = open(filename, "rt")
 | |
|         self.LoadFromSource(modID, file.read())
 | |
|         file.close()
 | |
| 
 | |
| 
 | |
|     def LoadFromSource(self, modID, source):
 | |
|         self.modules[modID][1] = source
 | |
|         self.LoadDict(modID)
 | |
| 
 | |
| 
 | |
|     def LoadDict(self, modID):
 | |
|         if self.name != __name__:
 | |
|             source = self.modules[modID][1]
 | |
|             description = self.modules[modID][3]
 | |
| 
 | |
|             try:
 | |
|                 self.modules[modID][0] = {}
 | |
|                 code = compile(source, description, "exec")        
 | |
|                 exec code in self.modules[modID][0]
 | |
|             except:
 | |
|                 self.modules[modID][4] = DemoError(sys.exc_info())
 | |
|                 self.modules[modID][0] = None
 | |
|             else:
 | |
|                 self.modules[modID][4] = None
 | |
| 
 | |
| 
 | |
|     def SetActive(self, modID):
 | |
|         if modID != modOriginal and modID != modModified:
 | |
|             raise LookupError
 | |
|         else:
 | |
|             self.modActive = modID
 | |
| 
 | |
| 
 | |
|     def GetActive(self):
 | |
|         dict = self.modules[self.modActive][0]
 | |
|         if dict is None:
 | |
|             return None
 | |
|         else:
 | |
|             return ModuleDictWrapper(dict)
 | |
| 
 | |
| 
 | |
|     def GetActiveID(self):
 | |
|         return self.modActive
 | |
| 
 | |
|     
 | |
|     def GetSource(self, modID = None):
 | |
|         if modID is None:
 | |
|             modID = self.modActive
 | |
|         return self.modules[modID][1]
 | |
| 
 | |
| 
 | |
|     def GetFilename(self, modID = None):
 | |
|         if modID is None:
 | |
|             modID = self.modActive
 | |
|         return self.modules[self.modActive][2]
 | |
| 
 | |
| 
 | |
|     def GetErrorInfo(self, modID = None):
 | |
|         if modID is None:
 | |
|             modID = self.modActive
 | |
|         return self.modules[self.modActive][4]
 | |
| 
 | |
| 
 | |
|     def Exists(self, modID):
 | |
|         return self.modules[modID][1] != ""
 | |
| 
 | |
| 
 | |
|     def UpdateFile(self, modID = None):
 | |
|         """Updates the file from which a module was loaded
 | |
|         with (possibly updated) source"""
 | |
|         if modID is None:
 | |
|             modID = self.modActive
 | |
| 
 | |
|         source = self.modules[modID][1]
 | |
|         filename = self.modules[modID][2]
 | |
| 
 | |
|         try:        
 | |
|             file = open(filename, "wt")
 | |
|             file.write(source)
 | |
|         finally:
 | |
|             file.close()
 | |
| 
 | |
| 
 | |
|     def Delete(self, modID):
 | |
|         if self.modActive == modID:
 | |
|             self.SetActive(0)
 | |
| 
 | |
|         self.modules[modID][0] = None
 | |
|         self.modules[modID][1] = ""
 | |
|         self.modules[modID][2] = ""
 | |
| 
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| class DemoError:
 | |
|     """Wraps and stores information about the current exception"""
 | |
|     def __init__(self, exc_info):
 | |
|         import copy
 | |
|         
 | |
|         excType, excValue = exc_info[:2]
 | |
|         # traceback list entries: (filename, line number, function name, text)
 | |
|         self.traceback = traceback.extract_tb(exc_info[2])
 | |
| 
 | |
|         # --Based on traceback.py::format_exception_only()--
 | |
|         if type(excType) == types.ClassType:
 | |
|             self.exception_type = excType.__name__
 | |
|         else:
 | |
|             self.exception_type = excType
 | |
| 
 | |
|         # If it's a syntax error, extra information needs
 | |
|         # to be added to the traceback
 | |
|         if excType is SyntaxError:
 | |
|             try:
 | |
|                 msg, (filename, lineno, self.offset, line) = excValue
 | |
|             except:
 | |
|                 pass
 | |
|             else:
 | |
|                 if not filename:
 | |
|                     filename = "<string>"
 | |
|                 line = line.strip()
 | |
|                 self.traceback.append( (filename, lineno, "", line) )
 | |
|                 excValue = msg
 | |
|         try:
 | |
|             self.exception_details = str(excValue)
 | |
|         except:
 | |
|             self.exception_details = "<unprintable %s object>" & type(excValue).__name__
 | |
| 
 | |
|         del exc_info
 | |
|         
 | |
|     def __str__(self):
 | |
|         ret = "Type %s \n \
 | |
|         Traceback: %s \n \
 | |
|         Details  : %s" % ( str(self.exception_type), str(self.traceback), self.exception_details )
 | |
|         return ret
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| class DemoErrorPanel(wx.Panel):
 | |
|     """Panel put into the demo tab when the demo fails to run due  to errors"""
 | |
| 
 | |
|     def __init__(self, parent, codePanel, demoError, log):
 | |
|         wx.Panel.__init__(self, parent, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
 | |
|         self.codePanel = codePanel
 | |
|         self.nb = parent
 | |
|         self.log = log
 | |
| 
 | |
|         self.box = wx.BoxSizer(wx.VERTICAL)
 | |
| 
 | |
|         # Main Label
 | |
|         self.box.Add(wx.StaticText(self, -1, "An error has occured while trying to run the demo")
 | |
|                      , 0, wx.ALIGN_CENTER | wx.TOP, 10)
 | |
| 
 | |
|         # Exception Information
 | |
|         boxInfo      = wx.StaticBox(self, -1, "Exception Info" )
 | |
|         boxInfoSizer = wx.StaticBoxSizer(boxInfo, wx.VERTICAL ) # Used to center the grid within the box
 | |
|         boxInfoGrid  = wx.FlexGridSizer(0, 2, 0, 0)
 | |
|         textFlags    = wx.ALIGN_RIGHT | wx.LEFT | wx.RIGHT | wx.TOP
 | |
|         boxInfoGrid.Add(wx.StaticText(self, -1, "Type: "), 0, textFlags, 5 )
 | |
|         boxInfoGrid.Add(wx.StaticText(self, -1, demoError.exception_type) , 0, textFlags, 5 )
 | |
|         boxInfoGrid.Add(wx.StaticText(self, -1, "Details: ") , 0, textFlags, 5 )
 | |
|         boxInfoGrid.Add(wx.StaticText(self, -1, demoError.exception_details) , 0, textFlags, 5 )
 | |
|         boxInfoSizer.Add(boxInfoGrid, 0, wx.ALIGN_CENTRE | wx.ALL, 5 )
 | |
|         self.box.Add(boxInfoSizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)
 | |
|        
 | |
|         # Set up the traceback list
 | |
|         # This one automatically resizes last column to take up remaining space
 | |
|         from ListCtrl import TestListCtrl
 | |
|         self.list = TestListCtrl(self, -1, style=wx.LC_REPORT  | wx.SUNKEN_BORDER)
 | |
|         self.list.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
 | |
|         self.list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
 | |
|         self.list.InsertColumn(0, "Filename")
 | |
|         self.list.InsertColumn(1, "Line", wx.LIST_FORMAT_RIGHT)
 | |
|         self.list.InsertColumn(2, "Function")
 | |
|         self.list.InsertColumn(3, "Code")
 | |
|         self.InsertTraceback(self.list, demoError.traceback)
 | |
|         self.list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
 | |
|         self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
 | |
|         self.box.Add(wx.StaticText(self, -1, "Traceback:")
 | |
|                      , 0, wx.ALIGN_CENTER | wx.TOP, 5)
 | |
|         self.box.Add(self.list, 1, wx.GROW | wx.ALIGN_CENTER | wx.ALL, 5)
 | |
|         self.box.Add(wx.StaticText(self, -1, "Entries from the demo module are shown in blue\n"
 | |
|                                            + "Double-click on them to go to the offending line")
 | |
|                      , 0, wx.ALIGN_CENTER | wx.BOTTOM, 5)
 | |
| 
 | |
|         self.box.Fit(self)
 | |
|         self.SetSizer(self.box)
 | |
| 
 | |
| 
 | |
|     def InsertTraceback(self, list, traceback):
 | |
|         #Add the traceback data
 | |
|         for x in range(len(traceback)):
 | |
|             data = traceback[x]
 | |
|             list.InsertStringItem(x, os.path.basename(data[0])) # Filename
 | |
|             list.SetStringItem(x, 1, str(data[1]))              # Line
 | |
|             list.SetStringItem(x, 2, str(data[2]))              # Function
 | |
|             list.SetStringItem(x, 3, str(data[3]))              # Code
 | |
|             
 | |
|             # Check whether this entry is from the demo module
 | |
|             if data[0] == "<original>" or data[0] == "<modified>": # FIXME: make more generalised
 | |
|                 self.list.SetItemData(x, int(data[1]))   # Store line number for easy access
 | |
|                 # Give it a blue colour
 | |
|                 item = self.list.GetItem(x)
 | |
|                 item.SetTextColour(wx.BLUE)
 | |
|                 self.list.SetItem(item)
 | |
|             else:
 | |
|                 self.list.SetItemData(x, -1)        # Editor can't jump into this one's code
 | |
|        
 | |
| 
 | |
|     def OnItemSelected(self, event):
 | |
|         # This occurs before OnDoubleClick and can be used to set the
 | |
|         # currentItem. OnDoubleClick doesn't get a wxListEvent....
 | |
|         self.currentItem = event.m_itemIndex
 | |
|         event.Skip()
 | |
| 
 | |
|         
 | |
|     def OnDoubleClick(self, event):
 | |
|         # If double-clicking on a demo's entry, jump to the line number
 | |
|         line = self.list.GetItemData(self.currentItem)
 | |
|         if line != -1:
 | |
|             self.nb.SetSelection(1) # Switch to the code viewer tab
 | |
|             wx.CallAfter(self.codePanel.JumpToLine, line-1, True)
 | |
|         event.Skip()
 | |
|         
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| class DemoTaskBarIcon(wx.TaskBarIcon):
 | |
|     TBMENU_RESTORE = wx.NewId()
 | |
|     TBMENU_CLOSE   = wx.NewId()
 | |
|     TBMENU_CHANGE  = wx.NewId()
 | |
|     TBMENU_REMOVE  = wx.NewId()
 | |
|     
 | |
|     def __init__(self, frame):
 | |
|         wx.TaskBarIcon.__init__(self)
 | |
|         self.frame = frame
 | |
| 
 | |
|         # Set the image
 | |
|         icon = self.MakeIcon(images.getWXPdemoImage())
 | |
|         self.SetIcon(icon, "wxPython Demo")
 | |
|         self.imgidx = 1
 | |
|         
 | |
|         # bind some events
 | |
|         self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
 | |
|         self.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
 | |
|         self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
 | |
|         self.Bind(wx.EVT_MENU, self.OnTaskBarChange, id=self.TBMENU_CHANGE)
 | |
|         self.Bind(wx.EVT_MENU, self.OnTaskBarRemove, id=self.TBMENU_REMOVE)
 | |
| 
 | |
| 
 | |
|     def CreatePopupMenu(self):
 | |
|         """
 | |
|         This method is called by the base class when it needs to popup
 | |
|         the menu for the default EVT_RIGHT_DOWN event.  Just create
 | |
|         the menu how you want it and return it from this function,
 | |
|         the base class takes care of the rest.
 | |
|         """
 | |
|         menu = wx.Menu()
 | |
|         menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
 | |
|         menu.Append(self.TBMENU_CLOSE,   "Close wxPython Demo")
 | |
|         menu.AppendSeparator()
 | |
|         menu.Append(self.TBMENU_CHANGE, "Change the TB Icon")
 | |
|         menu.Append(self.TBMENU_REMOVE, "Remove the TB Icon")
 | |
|         return menu
 | |
| 
 | |
| 
 | |
|     def MakeIcon(self, img):
 | |
|         """
 | |
|         The various platforms have different requirements for the
 | |
|         icon size...
 | |
|         """
 | |
|         if "wxMSW" in wx.PlatformInfo:
 | |
|             img = img.Scale(16, 16)
 | |
|         elif "wxGTK" in wx.PlatformInfo:
 | |
|             img = img.Scale(22, 22)
 | |
|         # wxMac can be any size upto 128x128, so leave the source img alone....
 | |
|         icon = wx.IconFromBitmap(img.ConvertToBitmap() )
 | |
|         return icon
 | |
|     
 | |
| 
 | |
|     def OnTaskBarActivate(self, evt):
 | |
|         if self.frame.IsIconized():
 | |
|             self.frame.Iconize(False)
 | |
|         if not self.frame.IsShown():
 | |
|             self.frame.Show(True)
 | |
|         self.frame.Raise()
 | |
| 
 | |
| 
 | |
|     def OnTaskBarClose(self, evt):
 | |
|         self.frame.Close()
 | |
| 
 | |
| 
 | |
|     def OnTaskBarChange(self, evt):
 | |
|         names = [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]                  
 | |
|         name = names[self.imgidx]
 | |
|         
 | |
|         getFunc = getattr(images, "get%sImage" % name)
 | |
|         self.imgidx += 1
 | |
|         if self.imgidx >= len(names):
 | |
|             self.imgidx = 0
 | |
|             
 | |
|         icon = self.MakeIcon(getFunc())
 | |
|         self.SetIcon(icon, "This is a new icon: " + name)
 | |
| 
 | |
| 
 | |
|     def OnTaskBarRemove(self, evt):
 | |
|         self.RemoveIcon()
 | |
| 
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| class wxPythonDemo(wx.Frame):
 | |
|     overviewText = "wxPython Overview"
 | |
| 
 | |
|     def __init__(self, parent, title):
 | |
|         wx.Frame.__init__(self, parent, -1, title, size = (950, 720),
 | |
|                           style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
 | |
| 
 | |
|         self.SetMinSize((640,480))
 | |
| 
 | |
|         self.loaded = False
 | |
|         self.cwd = os.getcwd()
 | |
|         self.curOverview = ""
 | |
|         self.demoPage = None
 | |
|         self.codePage = None
 | |
|         self.shell = None
 | |
|         self.firstTime = True
 | |
|         self.finddlg = None
 | |
| 
 | |
|         icon = images.getWXPdemoIcon()
 | |
|         self.SetIcon(icon)
 | |
| 
 | |
|         self.tbicon = DemoTaskBarIcon(self)
 | |
| 
 | |
|         wx.CallAfter(self.ShowTip)
 | |
| 
 | |
|         self.otherWin = None
 | |
|         self.Bind(wx.EVT_IDLE, self.OnIdle)
 | |
|         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 | |
|         self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
 | |
|         self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
 | |
| 
 | |
|         self.Centre(wx.BOTH)
 | |
|         self.CreateStatusBar(1, wx.ST_SIZEGRIP)
 | |
| 
 | |
|         splitter = wx.SplitterWindow(self, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
 | |
|         splitter2 = wx.SplitterWindow(splitter, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
 | |
| 
 | |
|         def EmptyHandler(evt): pass
 | |
|         #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
 | |
|         #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
 | |
| 
 | |
|         # Prevent TreeCtrl from displaying all items after destruction when True
 | |
|         self.dying = False
 | |
| 
 | |
|         # Create a Notebook
 | |
|         self.nb = wx.Notebook(splitter2, -1, style=wx.CLIP_CHILDREN)
 | |
| 
 | |
|         # Make a File menu
 | |
|         self.mainmenu = wx.MenuBar()
 | |
|         menu = wx.Menu()
 | |
|         item = menu.Append(-1, '&Redirect Output',
 | |
|                            'Redirect print statements to a window',
 | |
|                            wx.ITEM_CHECK)
 | |
|         self.Bind(wx.EVT_MENU, self.OnToggleRedirect, item)
 | |
|  
 | |
|         item = menu.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
 | |
|         self.Bind(wx.EVT_MENU, self.OnFileExit, item)
 | |
|         wx.App.SetMacExitMenuItemId(item.GetId())
 | |
|         self.mainmenu.Append(menu, '&File')
 | |
| 
 | |
|         # Make a Demo menu
 | |
|         menu = wx.Menu()
 | |
|         for item in _treeList:
 | |
|             submenu = wx.Menu()
 | |
|             for childItem in item[1]:
 | |
|                 mi = submenu.Append(-1, childItem)
 | |
|                 self.Bind(wx.EVT_MENU, self.OnDemoMenu, mi)
 | |
|             menu.AppendMenu(wx.NewId(), item[0], submenu)
 | |
|         self.mainmenu.Append(menu, '&Demo')
 | |
| 
 | |
|         # Make a Demo Code menu
 | |
|         #TODO: Add new menu items
 | |
|         #       Like the option-enabled entries to select the
 | |
|         #       active module
 | |
|         #TODO: should we bother?
 | |
| 
 | |
|         #menu = wx.Menu()
 | |
|         #saveID = wx.NewId()
 | |
|         #restoreID = wx.NewId()
 | |
|        # 
 | |
|         #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
 | |
|         #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
 | |
|         #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
 | |
|         #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
 | |
|         #self.mainmenu.Append(menu, 'Demo &Code')
 | |
|        # 
 | |
| 
 | |
|         # Make a Help menu
 | |
|         menu = wx.Menu()
 | |
|         findItem = menu.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
 | |
|         findnextItem = menu.Append(-1, 'Find &Next\tF3', 'Find Next')
 | |
|         menu.AppendSeparator()
 | |
| 
 | |
|         shellItem = menu.Append(-1, 'Open Py&Shell Window\tF5',
 | |
|                                 'An interactive interpreter window with the demo app and frame objects in the namesapce')
 | |
|         menu.AppendSeparator()
 | |
|         helpItem = menu.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
 | |
|         wx.App.SetMacAboutMenuItemId(helpItem.GetId())
 | |
| 
 | |
|         self.Bind(wx.EVT_MENU, self.OnOpenShellWindow, shellItem)
 | |
|         self.Bind(wx.EVT_MENU, self.OnHelpAbout, helpItem)
 | |
|         self.Bind(wx.EVT_MENU, self.OnHelpFind,  findItem)
 | |
|         self.Bind(wx.EVT_MENU, self.OnFindNext,  findnextItem)
 | |
|         self.Bind(wx.EVT_FIND, self.OnFind)
 | |
|         self.Bind(wx.EVT_FIND_NEXT, self.OnFind)
 | |
|         self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose)
 | |
|         self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateFindItems, findItem)
 | |
|         self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateFindItems, findnextItem)
 | |
|         self.mainmenu.Append(menu, '&Help')
 | |
|         self.SetMenuBar(self.mainmenu)
 | |
| 
 | |
|         self.finddata = wx.FindReplaceData()
 | |
| 
 | |
|         if 0:
 | |
|             # This is another way to set Accelerators, in addition to
 | |
|             # using the '\t<key>' syntax in the menu items.
 | |
|             aTable = wx.AcceleratorTable([(wx.ACCEL_ALT,  ord('X'), exitID),
 | |
|                                           (wx.ACCEL_CTRL, ord('H'), helpID),
 | |
|                                           (wx.ACCEL_CTRL, ord('F'), findID),
 | |
|                                           (wx.ACCEL_NORMAL, WXK_F3, findnextID)
 | |
|                                           ])
 | |
|             self.SetAcceleratorTable(aTable)
 | |
| 
 | |
| 
 | |
|         # Create a TreeCtrl
 | |
|         tID = wx.NewId()
 | |
|         self.treeMap = {}
 | |
|         self.tree = wx.TreeCtrl(splitter, tID, style =
 | |
|                                 wx.TR_DEFAULT_STYLE #| wx.TR_HAS_VARIABLE_ROW_HEIGHT
 | |
|                                )
 | |
| 
 | |
|         root = self.tree.AddRoot("wxPython Overview")
 | |
|         firstChild = None
 | |
|         for item in _treeList:
 | |
|             child = self.tree.AppendItem(root, item[0])
 | |
|             if not firstChild: firstChild = child
 | |
|             for childItem in item[1]:
 | |
|                 theDemo = self.tree.AppendItem(child, childItem)
 | |
|                 self.treeMap[childItem] = theDemo
 | |
| 
 | |
|         self.tree.Expand(root)
 | |
|         self.tree.Expand(firstChild)
 | |
|         self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, id=tID)
 | |
|         self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=tID)
 | |
|         self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=tID)
 | |
|         self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
 | |
| 
 | |
|         # Set up a wx.html.HtmlWindow on the Overview Notebook page
 | |
|         # we put it in a panel first because there seems to be a
 | |
|         # refresh bug of some sort (wxGTK) when it is directly in
 | |
|         # the notebook...
 | |
|         if 0:  # the old way
 | |
|             self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400))
 | |
|             self.nb.AddPage(self.ovr, self.overviewText)
 | |
| 
 | |
|         else:  # hopefully I can remove this hacky code soon, see SF bug #216861
 | |
|             panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN)
 | |
|             self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400))
 | |
|             self.nb.AddPage(panel, self.overviewText)
 | |
| 
 | |
|             def OnOvrSize(evt, ovr=self.ovr):
 | |
|                 ovr.SetSize(evt.GetSize())
 | |
|             panel.Bind(wx.EVT_SIZE, OnOvrSize)
 | |
|             panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
 | |
| 
 | |
|         if "gtk2" in wx.PlatformInfo:
 | |
|             self.ovr.SetStandardFonts()
 | |
|         self.SetOverview(self.overviewText, mainOverview)
 | |
| 
 | |
| 
 | |
|         # Set up a log window
 | |
|         self.log = wx.TextCtrl(splitter2, -1,
 | |
|                               style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
 | |
| 
 | |
|         # Set the wxWindows log target to be this textctrl
 | |
|         #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
 | |
| 
 | |
|         # But instead of the above we want to show how to use our own wx.Log class
 | |
|         wx.Log_SetActiveTarget(MyLog(self.log))
 | |
|         
 | |
|         # for serious debugging
 | |
|         #wx.Log_SetActiveTarget(wx.LogStderr())
 | |
|         #wx.Log_SetTraceMask(wx.TraceMessages)
 | |
| 
 | |
| 
 | |
|         self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
 | |
|         wx.GetApp().Bind(wx.EVT_ACTIVATE_APP, self.OnAppActivate)
 | |
| 
 | |
|         # add the windows to the splitter and split it.
 | |
|         splitter2.SplitHorizontally(self.nb, self.log, -160)
 | |
|         splitter.SplitVertically(self.tree, splitter2, 200)
 | |
| 
 | |
|         splitter.SetMinimumPaneSize(120)
 | |
|         splitter2.SetMinimumPaneSize(60)
 | |
| 
 | |
|         # Make the splitter on the right expand the top window when resized
 | |
|         def SplitterOnSize(evt):
 | |
|             splitter = evt.GetEventObject()
 | |
|             sz = splitter.GetSize()
 | |
|             splitter.SetSashPosition(sz.height - 160, False)
 | |
|             evt.Skip()
 | |
| 
 | |
|         splitter2.Bind(wx.EVT_SIZE, SplitterOnSize)
 | |
| 
 | |
|         # select initial items
 | |
|         self.nb.SetSelection(0)
 | |
|         self.tree.SelectItem(root)
 | |
| 
 | |
|         # Load 'Main' module
 | |
|         self.LoadDemo(self.overviewText)
 | |
|         self.loaded = True
 | |
| 
 | |
|         # select some other initial module?
 | |
|         if len(sys.argv) > 1:
 | |
|             arg = sys.argv[1]
 | |
|             if arg.endswith('.py'):
 | |
|                 arg = arg[:-3]
 | |
|             selectedDemo = self.treeMap.get(arg, None)
 | |
|             if selectedDemo:
 | |
|                 self.tree.SelectItem(selectedDemo)
 | |
|                 self.tree.EnsureVisible(selectedDemo)
 | |
| 
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def WriteText(self, text):
 | |
|         if text[-1:] == '\n':
 | |
|             text = text[:-1]
 | |
|         wx.LogMessage(text)
 | |
| 
 | |
|     def write(self, txt):
 | |
|         self.WriteText(txt)
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnItemExpanded(self, event):
 | |
|         item = event.GetItem()
 | |
|         wx.LogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
 | |
|         event.Skip()
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnItemCollapsed(self, event):
 | |
|         item = event.GetItem()
 | |
|         wx.LogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
 | |
|         event.Skip()
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnTreeLeftDown(self, event):
 | |
|         # reset the overview text if the tree item is clicked on again
 | |
|         pt = event.GetPosition();
 | |
|         item, flags = self.tree.HitTest(pt)
 | |
|         if item == self.tree.GetSelection():
 | |
|             self.SetOverview(self.tree.GetItemText(item)+" Overview", self.curOverview)
 | |
|         event.Skip()
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnSelChanged(self, event):
 | |
|         if self.dying or  not self.loaded:
 | |
|             return
 | |
| 
 | |
|         item = event.GetItem()
 | |
|         itemText = self.tree.GetItemText(item)
 | |
|         self.LoadDemo(itemText)
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def LoadDemo(self, demoName):
 | |
|         try:
 | |
|             wx.BeginBusyCursor()
 | |
|             
 | |
|             os.chdir(self.cwd)
 | |
|             self.ShutdownDemoModule()
 | |
| 
 | |
|             if demoName == self.overviewText:
 | |
|                 # User selected the "wxPython Overview" node
 | |
|                 # ie: _this_ module
 | |
|                 # Changing the main window at runtime not yet supported...
 | |
|                 self.demoModules = DemoModules(__name__)
 | |
|                 self.SetOverview(self.overviewText, mainOverview)
 | |
|                 self.LoadDemoSource()
 | |
|                 self.UpdateNotebook(0)
 | |
|             else:
 | |
|                 if os.path.exists(GetOriginalFilename(demoName)):
 | |
|                     wx.LogMessage("Loading demo %s.py..." % demoName)
 | |
|                     self.demoModules = DemoModules(demoName)
 | |
|                     self.LoadDemoSource()
 | |
|                     self.tree.Refresh()
 | |
|                 else:
 | |
|                     self.SetOverview("wxPython", mainOverview)
 | |
|                     self.codePage = None
 | |
|                     self.UpdateNotebook(0)
 | |
|         finally:
 | |
|             wx.EndBusyCursor()
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def LoadDemoSource(self):
 | |
|         self.codePage = None
 | |
|         self.codePage = DemoCodePanel(self.nb, self)
 | |
|         self.codePage.LoadDemo(self.demoModules)
 | |
|         
 | |
|     #---------------------------------------------
 | |
|     def RunModule(self):
 | |
|         """Runs the active module"""
 | |
| 
 | |
|         module = self.demoModules.GetActive()
 | |
|         self.ShutdownDemoModule()
 | |
|         overviewText = ""
 | |
|         
 | |
|         # o The RunTest() for all samples must now return a window that can
 | |
|         #   be palced in a tab in the main notebook.
 | |
|         # o If an error occurs (or has occured before) an error tab is created.
 | |
|         
 | |
|         if module is not None:
 | |
|             wx.LogMessage("Running demo module...")
 | |
|             if hasattr(module, "overview"):
 | |
|                 overviewText = module.overview
 | |
| 
 | |
|             try:
 | |
|                 self.demoPage = module.runTest(self, self.nb, self)
 | |
|             except:
 | |
|                 self.demoPage = DemoErrorPanel(self.nb, self.codePage,
 | |
|                                                DemoError(sys.exc_info()), self)
 | |
| 
 | |
|             assert self.demoPage is not None, "runTest must return a window!"
 | |
|             
 | |
|         else:
 | |
|             # There was a previous error in compiling or exec-ing
 | |
|             self.demoPage = DemoErrorPanel(self.nb, self.codePage,
 | |
|                                            self.demoModules.GetErrorInfo(), self)
 | |
|             
 | |
|         self.SetOverview(self.demoModules.name + " Overview", overviewText)
 | |
| 
 | |
|         if self.firstTime:
 | |
|             # cahnge to the demo page the first time a module is run
 | |
|             self.UpdateNotebook(2)
 | |
|             self.firstTime = False
 | |
|         else:
 | |
|             # otherwise just stay on the same tab in case the user has changed to another one
 | |
|             self.UpdateNotebook()
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def ShutdownDemoModule(self):
 | |
|         if self.demoPage:
 | |
|             # inform the window that it's time to quit if it cares
 | |
|             if hasattr(self.demoPage, "ShutdownDemo"):
 | |
|                 self.demoPage.ShutdownDemo()
 | |
|             wx.YieldIfNeeded() # in case the page has pending events
 | |
|             self.demoPage = None
 | |
|             
 | |
|     #---------------------------------------------
 | |
|     def UpdateNotebook(self, select = -1):
 | |
|         nb = self.nb
 | |
|         debug = False
 | |
|         
 | |
|         def UpdatePage(page, pageText):
 | |
|             pageExists = False
 | |
|             pagePos = -1
 | |
|             for i in range(nb.GetPageCount()):
 | |
|                 if nb.GetPageText(i) == pageText:
 | |
|                     pageExists = True
 | |
|                     pagePos = i
 | |
|                     break
 | |
|                 
 | |
|             if page:
 | |
|                 if not pageExists:
 | |
|                     # Add a new page
 | |
|                     nb.AddPage(page, pageText)
 | |
|                     if debug: wx.LogMessage("DBG: ADDED %s" % pageText)
 | |
|                 else:
 | |
|                     if nb.GetPage(pagePos) != page:
 | |
|                         # Reload an existing page
 | |
|                         nb.Freeze()
 | |
|                         nb.DeletePage(pagePos)
 | |
|                         nb.InsertPage(pagePos, page, pageText)
 | |
|                         nb.Thaw()
 | |
|                         if debug: wx.LogMessage("DBG: RELOADED %s" % pageText)
 | |
|                     else:
 | |
|                         # Excellent! No redraw/flicker
 | |
|                         if debug: wx.LogMessage("DBG: SAVED from reloading %s" % pageText)
 | |
|             elif pageExists:
 | |
|                 # Delete a page
 | |
|                 nb.DeletePage(pagePos)
 | |
|                 if debug: wx.LogMessage("DBG: DELETED %s" % pageText)
 | |
|             else:
 | |
|                 if debug: wx.LogMessage("DBG: STILL GONE - %s" % pageText)
 | |
|                 
 | |
|         if select == -1:
 | |
|             select = nb.GetSelection()
 | |
| 
 | |
|         UpdatePage(self.codePage, "Demo Code")
 | |
|         UpdatePage(self.demoPage, "Demo")
 | |
| 
 | |
|         if select >= 0 and select < nb.GetPageCount():
 | |
|             nb.SetSelection(select)
 | |
|             
 | |
|     #---------------------------------------------
 | |
|     def SetOverview(self, name, text):
 | |
|         self.curOverview = text
 | |
|         lead = text[:6]
 | |
|         if lead != '<html>' and lead != '<HTML>':
 | |
|             text = '<br>'.join(text.split('\n'))
 | |
|         if wx.USE_UNICODE:
 | |
|             text = text.decode('iso8859_1')  
 | |
|         self.ovr.SetPage(text)
 | |
|         self.nb.SetPageText(0, name)
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     # Menu methods
 | |
|     def OnFileExit(self, *event):
 | |
|         self.Close()
 | |
| 
 | |
|     def OnToggleRedirect(self, event):
 | |
|         app = wx.GetApp()
 | |
|         if event.Checked():
 | |
|             app.RedirectStdio()
 | |
|             print "Print statements and other standard output will now be directed to this window."
 | |
|         else:
 | |
|             app.RestoreStdio()
 | |
|             print "Print statements and other standard output will now be sent to the usual location."
 | |
|  
 | |
|     def OnHelpAbout(self, event):
 | |
|         from About import MyAboutBox
 | |
|         about = MyAboutBox(self)
 | |
|         about.ShowModal()
 | |
|         about.Destroy()
 | |
| 
 | |
|     def OnHelpFind(self, event):
 | |
|         if self.finddlg != None:
 | |
|             return
 | |
|         
 | |
|         self.nb.SetSelection(1)
 | |
|         self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
 | |
|                         wx.FR_NOUPDOWN |
 | |
|                         wx.FR_NOMATCHCASE |
 | |
|                         wx.FR_NOWHOLEWORD)
 | |
|         self.finddlg.Show(True)
 | |
| 
 | |
| 
 | |
|     def OnUpdateFindItems(self, evt):
 | |
|         evt.Enable(self.finddlg == None)
 | |
| 
 | |
| 
 | |
|     def OnFind(self, event):
 | |
|         editor = self.codePage.editor
 | |
|         self.nb.SetSelection(1)
 | |
|         end = editor.GetLastPosition()
 | |
|         textstring = editor.GetRange(0, end).lower()
 | |
|         start = editor.GetSelection()[1]
 | |
|         findstring = self.finddata.GetFindString().lower()
 | |
|         loc = textstring.find(findstring, start)
 | |
|         if loc == -1 and start != 0:
 | |
|             # string not found, start at beginning
 | |
|             start = 0
 | |
|             loc = textstring.find(findstring, start)
 | |
|         if loc == -1:
 | |
|             dlg = wx.MessageDialog(self, 'Find String Not Found',
 | |
|                           'Find String Not Found in Demo File',
 | |
|                           wx.OK | wx.ICON_INFORMATION)
 | |
|             dlg.ShowModal()
 | |
|             dlg.Destroy()
 | |
|         if self.finddlg:
 | |
|             if loc == -1:
 | |
|                 self.finddlg.SetFocus()
 | |
|                 return
 | |
|             else:
 | |
|                 self.finddlg.Destroy()
 | |
|                 self.finddlg = None
 | |
|         editor.ShowPosition(loc)
 | |
|         editor.SetSelection(loc, loc + len(findstring))
 | |
| 
 | |
| 
 | |
| 
 | |
|     def OnFindNext(self, event):
 | |
|         if self.finddata.GetFindString():
 | |
|             self.OnFind(event)
 | |
|         else:
 | |
|             self.OnHelpFind(event)
 | |
| 
 | |
|     def OnFindClose(self, event):
 | |
|         event.GetDialog().Destroy()
 | |
|         self.finddlg = None
 | |
| 
 | |
| 
 | |
|     def OnOpenShellWindow(self, evt):
 | |
|         if self.shell:
 | |
|             # if it already exists then just make sure it's visible
 | |
|             s = self.shell
 | |
|             if s.IsIconized():
 | |
|                 s.Iconize(False)
 | |
|             s.Raise()
 | |
|         else:
 | |
|             # Make a PyShell window
 | |
|             from wx import py
 | |
|             namespace = { 'wx'    : wx,
 | |
|                           'app'   : wx.GetApp(),
 | |
|                           'frame' : self,
 | |
|                           }
 | |
|             self.shell = py.shell.ShellFrame(None, locals=namespace)
 | |
|             self.shell.SetSize((640,480))
 | |
|             self.shell.Show()
 | |
| 
 | |
|             # Hook the close event of the main frame window so that we
 | |
|             # close the shell at the same time if it still exists            
 | |
|             def CloseShell(evt):
 | |
|                 if self.shell:
 | |
|                     self.shell.Close()
 | |
|                 evt.Skip()
 | |
|             self.Bind(wx.EVT_CLOSE, CloseShell)
 | |
| 
 | |
|         
 | |
|     #---------------------------------------------
 | |
|     def OnCloseWindow(self, event):
 | |
|         self.dying = True
 | |
|         self.demoPage = None
 | |
|         self.codePage = None
 | |
|         self.mainmenu = None
 | |
|         self.tbicon.Destroy()
 | |
|         self.Destroy()
 | |
| 
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnIdle(self, event):
 | |
|         if self.otherWin:
 | |
|             self.otherWin.Raise()
 | |
|             self.demoPage = self.otherWin
 | |
|             self.otherWin = None
 | |
| 
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def ShowTip(self):
 | |
|         try:
 | |
|             showTipText = open(opj("data/showTips")).read()
 | |
|             showTip, index = eval(showTipText)
 | |
|         except IOError:
 | |
|             showTip, index = (1, 0)
 | |
|         if showTip:
 | |
|             tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
 | |
|             ##tp = MyTP(0)
 | |
|             showTip = wx.ShowTip(self, tp)
 | |
|             index = tp.GetCurrentTip()
 | |
|             open(opj("data/showTips"), "w").write(str( (showTip, index) ))
 | |
| 
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnDemoMenu(self, event):
 | |
|         try:
 | |
|             selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
 | |
|         except:
 | |
|             selectedDemo = None
 | |
|         if selectedDemo:
 | |
|             self.tree.SelectItem(selectedDemo)
 | |
|             self.tree.EnsureVisible(selectedDemo)
 | |
| 
 | |
| 
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnIconfiy(self, evt):
 | |
|         wx.LogMessage("OnIconfiy: %s" % evt.Iconized())
 | |
|         evt.Skip()
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnMaximize(self, evt):
 | |
|         wx.LogMessage("OnMaximize")
 | |
|         evt.Skip()
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnActivate(self, evt):
 | |
|         wx.LogMessage("OnActivate: %s" % evt.GetActive())
 | |
|         evt.Skip()
 | |
| 
 | |
|     #---------------------------------------------
 | |
|     def OnAppActivate(self, evt):
 | |
|         wx.LogMessage("OnAppActivate: %s" % evt.GetActive())
 | |
|         evt.Skip()
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| class MySplashScreen(wx.SplashScreen):
 | |
|     def __init__(self):
 | |
|         bmp = wx.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
 | |
|         wx.SplashScreen.__init__(self, bmp,
 | |
|                                  wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
 | |
|                                  5000, None, -1)
 | |
|         self.Bind(wx.EVT_CLOSE, self.OnClose)
 | |
|         wx.FutureCall(2000, self.ShowMain)
 | |
| 
 | |
|     def OnClose(self, evt):
 | |
|         self.Hide()
 | |
|         evt.Skip()  # Make sure the default handler runs too...
 | |
| 
 | |
|     def ShowMain(self):
 | |
|         frame = wxPythonDemo(None, "wxPython: (A Demonstration)")
 | |
|         frame.Show()
 | |
|         self.Raise()
 | |
|         
 | |
| 
 | |
| class MyApp(wx.App):
 | |
|     def OnInit(self):
 | |
|         """
 | |
|         Create and show the splash screen.  It will then create and show
 | |
|         the main frame when it is time to do so.
 | |
|         """
 | |
| 
 | |
|         wx.SystemOptions.SetOptionInt("mac.window-plain-transition", 1)
 | |
| 
 | |
|         # For debugging
 | |
|         #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
 | |
| 
 | |
|         # Normally when using a SplashScreen you would create it, show
 | |
|         # it and then continue on with the applicaiton's
 | |
|         # initialization, finally creating and showing the main
 | |
|         # application window(s).  In this case we have nothing else to
 | |
|         # do so we'll delay showing the main frame until later (see
 | |
|         # ShowMain above) so the users can see the SplashScreen effect.        
 | |
|         splash = MySplashScreen()
 | |
|         splash.Show()
 | |
| 
 | |
|         return True
 | |
| 
 | |
| 
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| def main():
 | |
|     try:
 | |
|         demoPath = os.path.dirname(__file__)
 | |
|         os.chdir(demoPath)
 | |
|     except:
 | |
|         pass
 | |
|     app = MyApp(False)
 | |
|     app.MainLoop()
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| mainOverview = """<html><body>
 | |
| <h2>wxPython</h2>
 | |
| 
 | |
| <p> wxPython is a <b>GUI toolkit</b> for the Python programming
 | |
| language.  It allows Python programmers to create programs with a
 | |
| robust, highly functional graphical user interface, simply and easily.
 | |
| It is implemented as a Python extension module (native code) that
 | |
| wraps the popular wxWindows cross platform GUI library, which is
 | |
| written in C++.
 | |
| 
 | |
| <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
 | |
| means that it is free for anyone to use and the source code is
 | |
| available for anyone to look at and modify.  Or anyone can contribute
 | |
| fixes or enhancements to the project.
 | |
| 
 | |
| <p> wxPython is a <b>cross-platform</b> toolkit.  This means that the
 | |
| same program will run on multiple platforms without modification.
 | |
| Currently supported platforms are 32-bit Microsoft Windows, most Unix
 | |
| or unix-like systems, and Macintosh OS X. Since the language is
 | |
| Python, wxPython programs are <b>simple, easy</b> to write and easy to
 | |
| understand.
 | |
| 
 | |
| <p> <b>This demo</b> is not only a collection of test cases for
 | |
| wxPython, but is also designed to help you learn about and how to use
 | |
| wxPython.  Each sample is listed in the tree control on the left.
 | |
| When a sample is selected in the tree then a module is loaded and run
 | |
| (usually in a tab of this notebook,) and the source code of the module
 | |
| is loaded in another tab for you to browse and learn from.
 | |
| 
 | |
| """
 | |
| 
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     __name__ = 'Main'
 | |
|     main()
 | |
| 
 | |
| #----------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |