1 #---------------------------------------------------------------------------- 
   2 # Name:         PythonEditor.py 
   3 # Purpose:      PythonEditor for wx.lib.pydocview tbat uses the Styled Text Control 
   9 # Copyright:    (c) 2004-2005 ActiveGrid, Inc. 
  10 # License:      wxWindows License 
  11 #---------------------------------------------------------------------------- 
  16 import wx
.lib
.pydocview
 
  18 import keyword  
# So it knows what to hilite 
  19 import wx
.py  
# For the Python interpreter 
  20 import wx
.stc 
# For the Python interpreter 
  21 import cStringIO  
# For indent 
  24 import keyword 
# for GetAutoCompleteKeywordList 
  25 import sys 
# for GetAutoCompleteKeywordList 
  26 import MessageService 
# for OnCheckCode 
  28 import FindInDirService
 
  29 from UICommon 
import CaseInsensitiveCompare
 
  31     import checker 
# for pychecker 
  32     _CHECKER_INSTALLED 
= True 
  34     _CHECKER_INSTALLED 
= False 
  35 import os
.path 
# for pychecker 
  38 if wx
.Platform 
== '__WXMSW__': 
  44 VIEW_PYTHON_INTERPRETER_ID 
= wx
.NewId() 
  47 class PythonDocument(CodeEditor
.CodeDocument
): 
  51 class PythonView(CodeEditor
.CodeView
): 
  54     def GetCtrlClass(self
): 
  55         """ Used in split window to instantiate new instances """ 
  59     def ProcessUpdateUIEvent(self
, event
): 
  60         if not self
.GetCtrl(): 
  64         if id == CodeEditor
.CHECK_CODE_ID
: 
  65             hasText 
= self
.GetCtrl().GetTextLength() > 0 
  69         return CodeEditor
.CodeView
.ProcessUpdateUIEvent(self
, event
) 
  72     def OnActivateView(self
, activate
, activeView
, deactiveView
): 
  73         STCTextEditor
.TextView
.OnActivateView(self
, activate
, activeView
, deactiveView
) 
  74         if activate 
and self
.GetCtrl(): 
  75             if self
.GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
  78                 wx
.CallAfter(self
.LoadOutline
)  # need CallAfter because document isn't loaded yet 
  81     def OnClose(self
, deleteWindow 
= True): 
  82         status 
= STCTextEditor
.TextView
.OnClose(self
, deleteWindow
) 
  83         wx
.CallAfter(self
.ClearOutline
)  # need CallAfter because when closing the document, it is Activated and then Close, so need to match OnActivateView's CallAfter 
  87     def GetAutoCompleteKeywordList(self
, context
, hint
): 
  90             if context 
and len(context
): 
  91                 obj 
= eval(context
, globals(), locals()) 
  93             if not hint 
or len(hint
) == 0:  # context isn't valid, maybe it was the hint 
  97             kw 
= keyword
.kwlist
[:] 
 100             kw 
= filter(lambda item
: item
[0] != '_', symTbl
)  # remove local variables and methods 
 102         if hint 
and len(hint
): 
 103             lowerHint 
= hint
.lower() 
 104             filterkw 
= filter(lambda item
: item
.lower().startswith(lowerHint
), kw
)  # remove variables and methods that don't match hint 
 107         kw
.sort(CaseInsensitiveCompare
) 
 110             replaceLen 
= len(hint
) 
 114         return " ".join(kw
), replaceLen
 
 117     def OnCheckCode(self
): 
 118         if not _CHECKER_INSTALLED
:        
 119             wx
.MessageBox(_("pychecker not found.  Please install pychecker."), _("Check Code")) 
 122         filename 
= os
.path
.basename(self
.GetDocument().GetFilename()) 
 124         # pychecker only works on files, doesn't take a stream or string input 
 125         if self
.GetDocument().IsModified(): 
 126             dlg 
= wx
.MessageDialog(self
.GetFrame(), _("'%s' has been modfied and must be saved first.  Save file and check code?") % filename
, _("Check Code")) 
 128             val 
= dlg
.ShowModal() 
 131                 self
.GetDocument().Save() 
 135         messageService 
= wx
.GetApp().GetService(MessageService
.MessageService
) 
 136         messageService
.ShowWindow() 
 137         view 
= messageService
.GetView() 
 142         view
.SetCallback(self
.OnJumpToFoundLine
) 
 144         # Set cursor to Wait cursor 
 145         wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_WAIT
)) 
 148             # This takes a while for involved code 
 149             checker
.checkSyntax(self
.GetDocument().GetFilename(), view
) 
 152             # Set cursor to Default cursor 
 153             wx
.GetApp().GetTopWindow().SetCursor(wx
.StockCursor(wx
.CURSOR_DEFAULT
)) 
 156     def OnJumpToFoundLine(self
, event
): 
 157         messageService 
= wx
.GetApp().GetService(MessageService
.MessageService
) 
 158         lineText
, pos 
= messageService
.GetView().GetCurrLine() 
 160         lineEnd 
= lineText
.find(".py:") 
 164         lineStart 
= lineEnd 
+ len(".py:") 
 165         lineEnd 
= lineText
.find(":", lineStart
) 
 166         lineNum 
= int(lineText
[lineStart
:lineEnd
]) 
 168         filename 
= lineText
[0:lineStart 
- 1] 
 171         openDocs 
= wx
.GetApp().GetDocumentManager().GetDocuments() 
 172         for openDoc 
in openDocs
: 
 173             if openDoc
.GetFilename() == filename
: 
 174                 foundView 
= openDoc
.GetFirstView() 
 178             doc 
= wx
.GetApp().GetDocumentManager().CreateDocument(filename
, wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
) 
 179             foundView 
= doc
.GetFirstView() 
 182             foundView
.GetFrame().SetFocus() 
 184             foundView
.GotoLine(lineNum
) 
 185             startPos 
= foundView
.PositionFromLine(lineNum
) 
 186             endPos 
= foundView
.GetLineEndPosition(lineNum
) 
 187             # wxBug:  Need to select in reverse order, (end, start) to put cursor at head of line so positioning is correct 
 188             #         Also, if we use the correct positioning order (start, end), somehow, when we open a edit window for the first 
 189             #         time, we don't see the selection, it is scrolled off screen 
 190             foundView
.SetSelection(endPos
, startPos
) 
 191             wx
.GetApp().GetService(OutlineService
.OutlineService
).LoadOutline(foundView
, position
=startPos
) 
 195 class PythonInterpreterView(wx
.lib
.docview
.View
): 
 198     def OnCreate(self
, doc
, flags
): 
 199         frame 
= wx
.GetApp().CreateDocumentFrame(self
, doc
, flags
) 
 200         sizer 
= wx
.BoxSizer()         
 201         self
._pyCrust 
= wx
.py
.crust
.Crust(frame
) 
 202         sizer
.Add(self
._pyCrust
, 1, wx
.EXPAND
, 0) 
 203         frame
.SetSizer(sizer
) 
 210     def ProcessEvent(self
, event
): 
 211         if not hasattr(self
, "_pyCrust") or not self
._pyCrust
: 
 212             return wx
.lib
.docview
.View
.ProcessEvent(self
, event
) 
 213         stcControl 
= wx
.Window_FindFocus() 
 214         if not isinstance(stcControl
, wx
.stc
.StyledTextCtrl
): 
 215             return wx
.lib
.docview
.View
.ProcessEvent(self
, event
) 
 220         elif id == wx
.ID_REDO
: 
 223         elif id == wx
.ID_CUT
: 
 226         elif id == wx
.ID_COPY
: 
 229         elif id == wx
.ID_PASTE
: 
 232         elif id == wx
.ID_CLEAR
: 
 235         elif id == wx
.ID_SELECTALL
: 
 236             stcControl
.SetSelection(0, -1) 
 239             return wx
.lib
.docview
.View
.ProcessEvent(self
, event
) 
 242     def ProcessUpdateUIEvent(self
, event
): 
 243         if not hasattr(self
, "_pyCrust") or not self
._pyCrust
: 
 244             return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
) 
 245         stcControl 
= wx
.Window_FindFocus() 
 246         if not isinstance(stcControl
, wx
.stc
.StyledTextCtrl
): 
 247             return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
) 
 250             event
.Enable(stcControl
.CanUndo()) 
 252         elif id == wx
.ID_REDO
: 
 253             event
.Enable(stcControl
.CanRedo()) 
 255         elif id == wx
.ID_CUT
: 
 256             event
.Enable(stcControl
.CanCut()) 
 258         elif id == wx
.ID_COPY
: 
 259             event
.Enable(stcControl
.CanCopy()) 
 261         elif id == wx
.ID_PASTE
: 
 262             event
.Enable(stcControl
.CanPaste()) 
 264         elif id == wx
.ID_CLEAR
: 
 265             event
.Enable(True)  # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected 
 267         elif id == wx
.ID_SELECTALL
: 
 268             event
.Enable(stcControl
.GetTextLength() > 0) 
 271             return wx
.lib
.docview
.View
.ProcessUpdateUIEvent(self
, event
) 
 274     def OnClose(self
, deleteWindow
=True): 
 275         if deleteWindow 
and self
.GetFrame(): 
 276             self
.GetFrame().Destroy() 
 280 class PythonInterpreterDocument(wx
.lib
.docview
.Document
): 
 281     """ Generate Unique Doc Type """ 
 285 class PythonService(CodeEditor
.CodeService
): 
 289         CodeEditor
.CodeService
.__init
__(self
) 
 290         docManager 
= wx
.GetApp().GetDocumentManager() 
 291         pythonInterpreterTemplate 
= wx
.lib
.docview
.DocTemplate(docManager
, 
 292                                           _("Python Interpreter"), 
 296                                           _("Python Interpreter Document"), 
 297                                           _("Python Interpreter View"), 
 298                                           PythonInterpreterDocument
, 
 299                                           PythonInterpreterView
, 
 300                                           flags 
= wx
.lib
.docview
.TEMPLATE_INVISIBLE
, 
 301                                           icon 
= getPythonIcon()) 
 302         docManager
.AssociateTemplate(pythonInterpreterTemplate
) 
 305     def InstallControls(self
, frame
, menuBar 
= None, toolBar 
= None, statusBar 
= None, document 
= None): 
 306         CodeEditor
.CodeService
.InstallControls(self
, frame
, menuBar
, toolBar
, statusBar
, document
) 
 308         if document 
and document
.GetDocumentTemplate().GetDocumentType() != PythonDocument
: 
 310         if not document 
and wx
.GetApp().GetDocumentManager().GetFlags() & wx
.lib
.docview
.DOC_SDI
: 
 313         viewMenu 
= menuBar
.GetMenu(menuBar
.FindMenu(_("&View"))) 
 315         viewStatusBarItemPos 
= self
.GetMenuItemPos(viewMenu
, wx
.lib
.pydocview
.VIEW_STATUSBAR_ID
) 
 316         viewMenu
.InsertCheckItem(viewStatusBarItemPos 
+ 1, VIEW_PYTHON_INTERPRETER_ID
, _("Python &Interpreter"), _("Shows or hides the Python interactive window")) 
 317         wx
.EVT_MENU(frame
, VIEW_PYTHON_INTERPRETER_ID
, frame
.ProcessEvent
) 
 318         wx
.EVT_UPDATE_UI(frame
, VIEW_PYTHON_INTERPRETER_ID
, frame
.ProcessUpdateUIEvent
) 
 321     def ProcessEvent(self
, event
): 
 323         if id == VIEW_PYTHON_INTERPRETER_ID
: 
 324             self
.OnViewPythonInterpreter(event
) 
 327             return CodeEditor
.CodeService
.ProcessEvent(self
, event
) 
 330     def ProcessUpdateUIEvent(self
, event
): 
 332         if id == VIEW_PYTHON_INTERPRETER_ID
: 
 334             docManager 
= wx
.GetApp().GetDocumentManager() 
 336             for doc 
in docManager
.GetDocuments(): 
 337                 if isinstance(doc
, PythonInterpreterDocument
): 
 342             return CodeEditor
.CodeService
.ProcessUpdateUIEvent(self
, event
) 
 345     def OnViewPythonInterpreter(self
, event
): 
 346         for doc 
in wx
.GetApp().GetDocumentManager().GetDocuments(): 
 347             if isinstance(doc
, PythonInterpreterDocument
): 
 351         for template 
in self
.GetDocumentManager().GetTemplates(): 
 352             if template
.GetDocumentType() == PythonInterpreterDocument
: 
 353                 newDoc 
= template
.CreateDocument('', wx
.lib
.docview
.DOC_SILENT|wx
.lib
.docview
.DOC_OPEN_ONCE
) 
 355                     newDoc
.SetDocumentName(template
.GetDocumentName()) 
 356                     newDoc
.SetDocumentTemplate(template
) 
 357                     newDoc
.OnNewDocument() 
 358                     newDoc
.SetWriteable(False) 
 359                     newDoc
.GetFirstView().GetFrame().SetTitle(_("Python Interpreter")) 
 363 class PythonCtrl(CodeEditor
.CodeCtrl
): 
 366     def __init__(self
, parent
, id=-1, style
=wx
.NO_FULL_REPAINT_ON_RESIZE
): 
 367         CodeEditor
.CodeCtrl
.__init
__(self
, parent
, id, style
) 
 368         self
.SetProperty("tab.timmy.whinge.level", "1") 
 369         self
.SetProperty("fold.comment.python", "1") 
 370         self
.SetProperty("fold.quotes.python", "1") 
 371         self
.SetLexer(wx
.stc
.STC_LEX_PYTHON
) 
 372         self
.SetKeyWords(0, string
.join(keyword
.kwlist
)) 
 375     def CreatePopupMenu(self
): 
 376         FINDCLASS_ID 
= wx
.NewId() 
 377         FINDDEF_ID 
= wx
.NewId() 
 379         menu 
= CodeEditor
.CodeCtrl
.CreatePopupMenu(self
) 
 381         self
.Bind(wx
.EVT_MENU
, self
.OnPopFindDefinition
, id=FINDDEF_ID
) 
 382         menu
.Insert(1, FINDDEF_ID
, _("Find 'def'")) 
 384         self
.Bind(wx
.EVT_MENU
, self
.OnPopFindClass
, id=FINDCLASS_ID
) 
 385         menu
.Insert(2, FINDCLASS_ID
, _("Find 'class'")) 
 390     def OnPopFindDefinition(self
, event
): 
 391         view 
= wx
.GetApp().GetDocumentManager().GetCurrentView() 
 392         if hasattr(view
, "GetCtrl") and view
.GetCtrl() and hasattr(view
.GetCtrl(), "GetSelectedText"): 
 393             pattern 
= view
.GetCtrl().GetSelectedText().strip() 
 395                 searchPattern 
= "def\s+%s" % pattern
 
 396                 wx
.GetApp().GetService(FindInDirService
.FindInDirService
).FindInProject(searchPattern
) 
 399     def OnPopFindClass(self
, event
): 
 400         view 
= wx
.GetApp().GetDocumentManager().GetCurrentView() 
 401         if hasattr(view
, "GetCtrl") and view
.GetCtrl() and hasattr(view
.GetCtrl(), "GetSelectedText"): 
 402             definition 
= "class\s+%s" 
 403             pattern 
= view
.GetCtrl().GetSelectedText().strip() 
 405                 searchPattern 
= definition 
% pattern
 
 406                 wx
.GetApp().GetService(FindInDirService
.FindInDirService
).FindInProject(searchPattern
) 
 409     def SetViewDefaults(self
): 
 410         CodeEditor
.CodeCtrl
.SetViewDefaults(self
, configPrefix
="Python", hasWordWrap
=True, hasTabs
=True, hasFolding
=True) 
 413     def GetFontAndColorFromConfig(self
): 
 414         return CodeEditor
.CodeCtrl
.GetFontAndColorFromConfig(self
, configPrefix 
= "Python") 
 417     def UpdateStyles(self
): 
 418         CodeEditor
.CodeCtrl
.UpdateStyles(self
) 
 420         if not self
.GetFont(): 
 423         faces 
= { 'font' : self
.GetFont().GetFaceName(), 
 424                   'size' : self
.GetFont().GetPointSize(), 
 425                   'size2': self
.GetFont().GetPointSize() - 2, 
 426                   'color' : "%02x%02x%02x" % (self
.GetFontColor().Red(), self
.GetFontColor().Green(), self
.GetFontColor().Blue()) 
 431         self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, "face:%(font)s,fore:#000000,face:%(font)s,size:%(size)d" % faces
) 
 433         self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, "face:%(font)s,fore:#007F00,italic,face:%(font)s,size:%(size)d" % faces
) 
 435         self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, "face:%(font)s,fore:#007F7F,size:%(size)d" % faces
) 
 437         self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces
) 
 438         # Single quoted string 
 439         self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces
) 
 441         self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces
) 
 443         self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, "face:%(font)s,fore:#7F0000,size:%(size)d" % faces
) 
 444         # Triple double quotes 
 445         self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, "face:%(font)s,fore:#7F0000,size:%(size)d" % faces
) 
 446         # Class name definition 
 447         self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, "face:%(font)s,fore:#0000FF,bold,size:%(size)d" % faces
) 
 448         # Function or method name definition 
 449         self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, "face:%(font)s,fore:#007F7F,bold,size:%(size)d" % faces
) 
 451         self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, "face:%(font)s,size:%(size)d" % faces
) 
 453         self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, "face:%(font)s,fore:#%(color)s,face:%(font)s,size:%(size)d" % faces
) 
 455         self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, "face:%(font)s,fore:#7F7F7F,size:%(size)d" % faces
) 
 456         # End of line where string is not closed 
 457         self
.StyleSetSpec(wx
.stc
.STC_P_STRINGEOL
, "face:%(font)s,fore:#000000,face:%(font)s,back:#E0C0E0,eol,size:%(size)d" % faces
) 
 460     def OnUpdateUI(self
, evt
): 
 461         braces 
= self
.GetMatchingBraces() 
 463         # check for matching braces 
 467         caretPos 
= self
.GetCurrentPos() 
 469             charBefore 
= self
.GetCharAt(caretPos 
- 1) 
 470             styleBefore 
= self
.GetStyleAt(caretPos 
- 1) 
 473         if charBefore 
and chr(charBefore
) in braces 
and styleBefore 
== wx
.stc
.STC_P_OPERATOR
: 
 474             braceAtCaret 
= caretPos 
- 1 
 478             charAfter 
= self
.GetCharAt(caretPos
) 
 479             styleAfter 
= self
.GetStyleAt(caretPos
) 
 480             if charAfter 
and chr(charAfter
) in braces 
and styleAfter 
== wx
.stc
.STC_P_OPERATOR
: 
 481                 braceAtCaret 
= caretPos
 
 483         if braceAtCaret 
>= 0: 
 484             braceOpposite 
= self
.BraceMatch(braceAtCaret
) 
 486         if braceAtCaret 
!= -1  and braceOpposite 
== -1: 
 487             self
.BraceBadLight(braceAtCaret
) 
 489             self
.BraceHighlight(braceAtCaret
, braceOpposite
) 
 495         (text
, caretPos
) = self
.GetCurLine() 
 497         self
._tokenizerChars 
= {}  # This is really too much, need to find something more like a C array 
 498         for i 
in range(len(text
)): 
 499             self
._tokenizerChars
[i
] = 0 
 501         ctext 
= cStringIO
.StringIO(text
) 
 503             tokenize
.tokenize(ctext
.readline
, self
) 
 507         # Left in for debugging purposes: 
 508         #for i in range(len(text)): 
 509         #    print i, text[i], self._tokenizerChars[i] 
 511         if caretPos 
== 0 or len(string
.strip(text
)) == 0:  # At beginning of line or within an empty line 
 514             doExtraIndent 
= False 
 520                 startSquareBracketCount 
= 0 
 521                 endSquareBracketCount 
= 0 
 522                 startCurlyBracketCount 
= 0 
 523                 endCurlyBracketCount 
= 0 
 526                 for i 
in range(caretPos 
- 1, -1, -1): # Go through each character before the caret 
 527                     if i 
>= len(text
): # Sometimes the caret is at the end of the text if there is no LF 
 529                     if self
._tokenizerChars
[i
] == 1: 
 531                     elif self
._tokenizerChars
[i
] == 2: 
 532                         startQuoteCount 
= startQuoteCount 
+ 1 
 533                     elif self
._tokenizerChars
[i
] == 3: 
 534                         endQuoteCount 
= endQuoteCount 
+ 1 
 535                     elif text
[i
] == '(': # Would be nice to use a dict for this, but the code is much more readable this way 
 536                         startParenCount 
= startParenCount 
+ 1 
 538                         endParenCount 
= endParenCount 
+ 1 
 540                         startSquareBracketCount 
= startSquareBracketCount 
+ 1 
 542                         endSquareBracketCount 
= endSquareBracketCount 
+ 1 
 544                         startCurlyBracketCount 
= startCurlyBracketCount 
+ 1 
 546                         endCurlyBracketCount 
= endCurlyBracketCount 
+ 1 
 550                     if startQuoteCount 
> endQuoteCount 
or startParenCount 
> endParenCount 
or startSquareBracketCount 
> endSquareBracketCount 
or startCurlyBracketCount 
> endCurlyBracketCount
: 
 551                         if i 
+ 1 >= caretPos
:  # Caret is right at the open paren, so just do indent as if colon was there 
 555                             spaces 
= " " * (i 
+ 1) 
 559                 spaces 
= text
[0:len(text
) - len(string
.lstrip(text
))] 
 560                 if caretPos 
< len(spaces
):  # If within the opening spaces of a line 
 561                     spaces 
= spaces
[:caretPos
] 
 564                 if commentStart 
!= -1: 
 565                     text 
= text
[0:commentStart
] 
 567                 textNoTrailingSpaces 
= text
[0:caretPos
].rstrip() 
 568                 if doExtraIndent 
or len(textNoTrailingSpaces
) and textNoTrailingSpaces
[-1] == ':': 
 569                     spaces 
= spaces 
+ ' ' * self
.GetIndent() 
 570             self
.AddText('\n' + spaces
) 
 571         self
.EnsureCaretVisible() 
 574     # Callback for tokenizer in self.DoIndent 
 575     def __call__(self
, toktype
, toktext
, (srow
,scol
), (erow
,ecol
), line
): 
 576         if toktype 
== tokenize
.COMMENT
: 
 577             for i 
in range(scol
, ecol 
+ 1): 
 578                 self
._validChars
[i
] = False 
 579         elif toktype 
== token
.STRING
: 
 580             self
._tokenizerChars
[scol
] = 2 # Open quote 
 581             self
._tokenizerChars
[ecol 
- 1] = 3 # Close quote 
 582             for i 
in range(scol 
+ 1, ecol 
- 2): 
 583                 self
._tokenizerChars
[i
] = 1 # Part of string, 1 == ignore the char 
 586 class PythonOptionsPanel(wx
.Panel
): 
 588     def __init__(self
, parent
, id): 
 589         wx
.Panel
.__init
__(self
, parent
, id) 
 590         pathLabel 
= wx
.StaticText(self
, -1, _("python.exe Path:")) 
 591         config 
= wx
.ConfigBase_Get() 
 592         path 
= config
.Read("ActiveGridPythonLocation") 
 593         self
._pathTextCtrl 
= wx
.TextCtrl(self
, -1, path
, size 
= (150, -1)) 
 594         self
._pathTextCtrl
.SetToolTipString(self
._pathTextCtrl
.GetValue()) 
 595         self
._pathTextCtrl
.SetInsertionPointEnd() 
 596         choosePathButton 
= wx
.Button(self
, -1, _("Browse...")) 
 597         pathSizer 
= wx
.BoxSizer(wx
.HORIZONTAL
) 
 600         pathSizer
.Add(pathLabel
, 0, wx
.ALIGN_CENTER_VERTICAL|wx
.LEFT|wx
.TOP
, HALF_SPACE
) 
 601         pathSizer
.Add(self
._pathTextCtrl
, 1, wx
.EXPAND|wx
.LEFT|wx
.TOP
, HALF_SPACE
) 
 602         pathSizer
.Add(choosePathButton
, 0, wx
.ALIGN_RIGHT|wx
.LEFT|wx
.RIGHT|wx
.TOP
, HALF_SPACE
) 
 603         wx
.EVT_BUTTON(self
, choosePathButton
.GetId(), self
.OnChoosePath
) 
 604         mainSizer 
= wx
.BoxSizer(wx
.VERTICAL
)                 
 605         mainSizer
.Add(pathSizer
, 0, wx
.EXPAND|wx
.LEFT|wx
.RIGHT|wx
.TOP
, SPACE
) 
 607         self
._otherOptions 
= STCTextEditor
.TextOptionsPanel(self
, -1, configPrefix 
= "Python", label 
= "Python", hasWordWrap 
= True, hasTabs 
= True, addPage
=False, hasFolding
=True) 
 608         mainSizer
.Add(self
._otherOptions
, 0, wx
.EXPAND|wx
.BOTTOM
, SPACE
) 
 609         self
.SetSizer(mainSizer
) 
 610         parent
.AddPage(self
, _("Python")) 
 613     def OnChoosePath(self
, event
): 
 614         defaultDir 
= os
.path
.dirname(self
._pathTextCtrl
.GetValue().strip()) 
 615         defaultFile 
= os
.path
.basename(self
._pathTextCtrl
.GetValue().strip()) 
 617             wildcard 
= _("Executable (*.exe)|*.exe|All|*.*") 
 619                 defaultFile 
= "python.exe" 
 622         dlg 
= wx
.FileDialog(wx
.GetApp().GetTopWindow(), 
 624                                defaultDir
=defaultDir
, 
 625                                defaultFile
=defaultFile
, 
 627                                style
=wx
.OPEN|wx
.FILE_MUST_EXIST|wx
.HIDE_READONLY
) 
 628         # dlg.CenterOnParent()  # wxBug: caused crash with wx.FileDialog 
 629         if dlg
.ShowModal() == wx
.ID_OK
: 
 632                 self
._pathTextCtrl
.SetValue(path
) 
 633                 self
._pathTextCtrl
.SetToolTipString(self
._pathTextCtrl
.GetValue()) 
 634                 self
._pathTextCtrl
.SetInsertionPointEnd() 
 638     def OnOK(self
, optionsDialog
): 
 639         config 
= wx
.ConfigBase_Get() 
 640         config
.Write("ActiveGridPythonLocation", self
._pathTextCtrl
.GetValue().strip()) 
 642         self
._otherOptions
.OnOK(optionsDialog
) 
 646         return getPythonIcon() 
 649 #---------------------------------------------------------------------------- 
 650 # Icon Bitmaps - generated by encode_bitmaps.py 
 651 #---------------------------------------------------------------------------- 
 652 from wx 
import ImageFromStream
, BitmapFromImage
 
 658 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ 
 659 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ 
 660 \x00\x01\xe7IDAT8\x8d}\x921h\x13Q\x18\xc7\x7fw\xb9\x0ei\x9d*\xbd\xeb\x10\x8f\ 
 661 ,\x99\x1c*A[\xaa\x19B\xe8\xd0\xb1\x0e%K\x87\x88T2\x88Cqp\tD\x14i\xe9\xe0V\ 
 662 \xdaQ\xb7\xe0P\xa1\x8b\xa0(\x95$z\xd5Q1\x90\xa2\xd7\x9a4^\x87\xa0`\x92!w9\ 
 663 \x87\xf8.\xb9\xa6\xc97\xbd\xef{\xef\xfb\xbd\xff\xfb\xbfO*~;v\xf9\x1f\xad\xba\ 
 664 \x05@\xf9\xd4\x06\xc0::$\xbb\x96\x92\x18\x11\n@(4\xdd\xcdB\xd3\xd4\x1d\x85\ 
 665 \x8b\x97\xe1\xe3;\x83\x99\xe5\x15\xb2\xe0\x8e\x82\xc8\xa3\xe8\x003\xcb+\xac\ 
 666 \xaee\xdda\xfb\xb2\x90\rPw\x14\x00\x9a\xb5\n\xbf\xfflSz\x9d\xa2Y\xdc"zca\xe8\ 
 667 \x05\xb2h\x14\xcd\xd0\xf3B\x9f\x98\xe5\xf9\xde\x13"\xaaB\xc7\xb1\xcfU!\x0b\ 
 668 \xc3D4k\x15\xac\x93\x03\xf4\x89Y\xaf\x96\xffT\x028\x17\xa2\xf4\'\xcdZ\x85\ 
 669 \xf7F\x06{\xaa\x80ev\xc1\x91\xb91>\x18\x0f\xb8\xb7\x95a\xe9\xca\x0b:\x8e\xed\ 
 670 \xca\x01E\x1a\x00\x98\r\x89\x92\x91\xa1\xda\xd8\x87\x06ha\x1f\x1b\x80\xcd\ 
 671 \x9d%\xe0\xa5\x0f"[G\x87\x98\x8d\xde/ia\x05-\xac`\x996\xf9\\\x0b\xcb\xb4)\ 
 672 \x1bmOMn\xf7\xd5\xf0\'\\\x8b\xdces\xe7\x8d\xef\x80h\xd6\xc2\n\xf9\\\x0b]\xf5\ 
 673 \xab\xf2\xcdApR#\xf1kp4b\xc9 \xf9\\\x0b\x80\xe4\xcdE\xaf\xdeqlW\xaeVL\xaf`~\ 
 674 \xd9\x03@W\xd3\x00\xc4\x13\x0b\xc4\x92A\xcf\xd0\xf9\xe8:\x89\xebW\x01(|\xfd\ 
 675 \xe1\xbe-~F\xbas\xff\x91\xf75\x82n\x9d\x1c\xf0}\xfciw\xdd\xe7A<\xd1\x1b\xa8j\ 
 676 c\x9f\xb2\xd1F\x92\xe4\x80O\x12\xc0\xc6\xb3\x14\xf6Ta\xe0)g\x81\xba\x9a\xf6\ 
 677 \x9b(\x07\x14I@\x84lq\xb8?\xe6\xa3\xeb\x00\xdc\xba\x9d\xf4+\x10*~\xfem\xf3\ 
 678 \xf8\xe1\x06\xc7\xa7\xdb\xe8j\x9a\xf8\xdc\xa4\xb7\x1f[\\\xe5\xd2\x851/\xff\ 
 679 \x07\xac\x9b\xd1e\x12\x96\x0f\xfd\x00\x00\x00\x00IEND\xaeB`\x82'  
 682 def getPythonBitmap(): 
 683     return BitmapFromImage(getPythonImage()) 
 685 def getPythonImage(): 
 686     stream 
= cStringIO
.StringIO(getPythonData()) 
 687     return ImageFromStream(stream
) 
 690     return wx
.IconFromBitmap(getPythonBitmap())