]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/ide/activegrid/tool/PythonEditor.py
Docview and IDE patch from Morag Hua with fix for bug #1217890
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / PythonEditor.py
1 #----------------------------------------------------------------------------
2 # Name: PythonEditor.py
3 # Purpose: PythonEditor for wx.lib.pydocview tbat uses the Styled Text Control
4 #
5 # Author: Peter Yared
6 #
7 # Created: 8/15/03
8 # CVS-ID: $Id$
9 # Copyright: (c) 2004-2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
12
13 import CodeEditor
14 import wx
15 import wx.lib.docview
16 import wx.lib.pydocview
17 import string
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
22 import OutlineService
23 import STCTextEditor
24 import keyword # for GetAutoCompleteKeywordList
25 import sys # for GetAutoCompleteKeywordList
26 import MessageService # for OnCheckCode
27 import OutlineService
28 try:
29 import checker # for pychecker
30 _CHECKER_INSTALLED = True
31 except ImportError:
32 _CHECKER_INSTALLED = False
33 import os.path # for pychecker
34 _ = wx.GetTranslation
35
36 if wx.Platform == '__WXMSW__':
37 _WINDOWS = True
38 else:
39 _WINDOWS = False
40
41
42 VIEW_PYTHON_INTERPRETER_ID = wx.NewId()
43
44
45 class PythonDocument(CodeEditor.CodeDocument):
46 pass
47
48
49 class PythonView(CodeEditor.CodeView):
50
51
52 def GetCtrlClass(self):
53 """ Used in split window to instantiate new instances """
54 return PythonCtrl
55
56
57 def ProcessUpdateUIEvent(self, event):
58 if not self.GetCtrl():
59 return False
60
61 id = event.GetId()
62 if id == CodeEditor.CHECK_CODE_ID:
63 hasText = self.GetCtrl().GetTextLength() > 0
64 event.Enable(hasText)
65 return True
66
67 return CodeEditor.CodeView.ProcessUpdateUIEvent(self, event)
68
69
70 def OnActivateView(self, activate, activeView, deactiveView):
71 STCTextEditor.TextView.OnActivateView(self, activate, activeView, deactiveView)
72 if activate:
73 wx.CallAfter(self.LoadOutline) # need CallAfter because document isn't loaded yet
74
75
76 def OnClose(self, deleteWindow = True):
77 status = STCTextEditor.TextView.OnClose(self, deleteWindow)
78 wx.CallAfter(self.ClearOutline) # need CallAfter because when closing the document, it is Activated and then Close, so need to match OnActivateView's CallAfter
79 return status
80
81
82 def GetAutoCompleteKeywordList(self, context, hint):
83 obj = None
84 try:
85 if context and len(context):
86 obj = eval(context, globals(), locals())
87 except:
88 if not hint or len(hint) == 0: # context isn't valid, maybe it was the hint
89 hint = context
90
91 if obj is None:
92 kw = keyword.kwlist[:]
93 else:
94 symTbl = dir(obj)
95 kw = filter(lambda item: item[0] != '_', symTbl) # remove local variables and methods
96
97 if hint and len(hint):
98 lowerHint = hint.lower()
99 filterkw = filter(lambda item: item.lower().startswith(lowerHint), kw) # remove variables and methods that don't match hint
100 kw = filterkw
101
102 kw.sort(self.CaseInsensitiveCompare)
103
104 if hint:
105 replaceLen = len(hint)
106 else:
107 replaceLen = 0
108
109 return " ".join(kw), replaceLen
110
111
112 def OnCheckCode(self):
113 if not _CHECKER_INSTALLED:
114 wx.MessageBox(_("pychecker not found. Please install pychecker."), _("Check Code"))
115 return
116
117 filename = os.path.basename(self.GetDocument().GetFilename())
118
119 # pychecker only works on files, doesn't take a stream or string input
120 if self.GetDocument().IsModified():
121 dlg = wx.MessageDialog(self.GetFrame(), _("'%s' has been modfied and must be saved first. Save file and check code?") % filename, _("Check Code"))
122 val = dlg.ShowModal()
123 dlg.Destroy()
124 if val == wx.ID_OK:
125 self.GetDocument().Save()
126 else:
127 return
128
129 messageService = wx.GetApp().GetService(MessageService.MessageService)
130 messageService.ShowWindow()
131 view = messageService.GetView()
132 if not view:
133 return
134
135 view.ClearLines()
136 view.SetCallback(self.OnJumpToFoundLine)
137
138 # Set cursor to Wait cursor
139 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
140
141 # This takes a while for involved code
142 checker.checkSyntax(self.GetDocument().GetFilename(), view)
143
144 # Set cursor to Default cursor
145 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
146
147
148 def OnJumpToFoundLine(self, event):
149 messageService = wx.GetApp().GetService(MessageService.MessageService)
150 lineText, pos = messageService.GetView().GetCurrLine()
151
152 lineEnd = lineText.find(".py:")
153 if lineEnd == -1:
154 return
155
156 lineStart = lineEnd + len(".py:")
157 lineEnd = lineText.find(":", lineStart)
158 lineNum = int(lineText[lineStart:lineEnd])
159
160 filename = lineText[0:lineStart - 1]
161
162 foundView = None
163 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
164 for openDoc in openDocs:
165 if openDoc.GetFilename() == filename:
166 foundView = openDoc.GetFirstView()
167 break
168
169 if not foundView:
170 doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
171 foundView = doc.GetFirstView()
172
173 if foundView:
174 foundView.GetFrame().SetFocus()
175 foundView.Activate()
176 foundView.GotoLine(lineNum)
177 startPos = foundView.PositionFromLine(lineNum)
178 endPos = foundView.GetLineEndPosition(lineNum)
179 # wxBug: Need to select in reverse order, (end, start) to put cursor at head of line so positioning is correct
180 # Also, if we use the correct positioning order (start, end), somehow, when we open a edit window for the first
181 # time, we don't see the selection, it is scrolled off screen
182 foundView.SetSelection(endPos, startPos)
183 wx.GetApp().GetService(OutlineService.OutlineService).LoadOutline(foundView, position=startPos)
184
185
186
187 class PythonInterpreterView(wx.lib.docview.View):
188
189
190 def OnCreate(self, doc, flags):
191 frame = wx.GetApp().CreateDocumentFrame(self, doc, flags)
192 sizer = wx.BoxSizer()
193 self._pyCrust = wx.py.crust.Crust(frame)
194 sizer.Add(self._pyCrust, 1, wx.EXPAND, 0)
195 frame.SetSizer(sizer)
196 frame.Layout()
197 self.Activate()
198 frame.Show()
199 return True
200
201
202 def ProcessEvent(self, event):
203 if not hasattr(self, "_pyCrust") or not self._pyCrust:
204 return wx.lib.docview.View.ProcessEvent(self, event)
205 stcControl = wx.Window_FindFocus()
206 if not isinstance(stcControl, wx.stc.StyledTextCtrl):
207 return wx.lib.docview.View.ProcessEvent(self, event)
208 id = event.GetId()
209 if id == wx.ID_UNDO:
210 stcControl.Undo()
211 return True
212 elif id == wx.ID_REDO:
213 stcControl.Redo()
214 return True
215 elif id == wx.ID_CUT:
216 stcControl.Cut()
217 return True
218 elif id == wx.ID_COPY:
219 stcControl.Copy()
220 return True
221 elif id == wx.ID_PASTE:
222 stcControl.Paste()
223 return True
224 elif id == wx.ID_CLEAR:
225 stcControl.Clear()
226 return True
227 elif id == wx.ID_SELECTALL:
228 stcControl.SetSelection(0, -1)
229 return True
230 else:
231 return wx.lib.docview.View.ProcessEvent(self, event)
232
233
234 def ProcessUpdateUIEvent(self, event):
235 if not hasattr(self, "_pyCrust") or not self._pyCrust:
236 return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
237 stcControl = wx.Window_FindFocus()
238 if not isinstance(stcControl, wx.stc.StyledTextCtrl):
239 return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
240 id = event.GetId()
241 if id == wx.ID_UNDO:
242 event.Enable(stcControl.CanUndo())
243 return True
244 elif id == wx.ID_REDO:
245 event.Enable(stcControl.CanRedo())
246 return True
247 elif id == wx.ID_CUT:
248 event.Enable(stcControl.CanCut())
249 return True
250 elif id == wx.ID_COPY:
251 event.Enable(stcControl.CanCopy())
252 return True
253 elif id == wx.ID_PASTE:
254 event.Enable(stcControl.CanPaste())
255 return True
256 elif id == wx.ID_CLEAR:
257 event.Enable(True) # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected
258 return True
259 elif id == wx.ID_SELECTALL:
260 event.Enable(stcControl.GetTextLength() > 0)
261 return True
262 else:
263 return wx.lib.docview.View.ProcessUpdateUIEvent(self, event)
264
265
266 def OnClose(self, deleteWindow=True):
267 if deleteWindow and self.GetFrame():
268 self.GetFrame().Destroy()
269 return True
270
271
272 class PythonService(CodeEditor.CodeService):
273
274
275 def __init__(self):
276 CodeEditor.CodeService.__init__(self)
277
278
279 def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
280 CodeEditor.CodeService.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
281
282 if document and document.GetDocumentTemplate().GetDocumentType() != PythonDocument:
283 return
284 if not document and wx.GetApp().GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
285 return
286
287 viewMenu = menuBar.GetMenu(menuBar.FindMenu(_("&View")))
288
289 viewStatusBarItemPos = self.GetMenuItemPos(viewMenu, wx.lib.pydocview.VIEW_STATUSBAR_ID)
290 viewMenu.InsertCheckItem(viewStatusBarItemPos + 1, VIEW_PYTHON_INTERPRETER_ID, _("Python &Interpreter"), _("Shows or hides the Python interactive window"))
291 wx.EVT_MENU(frame, VIEW_PYTHON_INTERPRETER_ID, frame.ProcessEvent)
292 wx.EVT_UPDATE_UI(frame, VIEW_PYTHON_INTERPRETER_ID, frame.ProcessUpdateUIEvent)
293
294
295 def ProcessEvent(self, event):
296 id = event.GetId()
297 if id == VIEW_PYTHON_INTERPRETER_ID:
298 self.OnViewPythonInterpreter(event)
299 return True
300 else:
301 return CodeEditor.CodeService.ProcessEvent(self, event)
302
303
304 def ProcessUpdateUIEvent(self, event):
305 id = event.GetId()
306 if id == VIEW_PYTHON_INTERPRETER_ID:
307 event.Enable(True)
308 docManager = wx.GetApp().GetDocumentManager()
309 event.Check(False)
310 for doc in docManager.GetDocuments():
311 if isinstance(doc.GetFirstView(), PythonInterpreterView):
312 event.Check(True)
313 break
314 return True
315 else:
316 return CodeEditor.CodeService.ProcessUpdateUIEvent(self, event)
317
318
319 def OnViewPythonInterpreter(self, event):
320 for doc in wx.GetApp().GetDocumentManager().GetDocuments():
321 if isinstance(doc.GetFirstView(), PythonInterpreterView):
322 doc.GetFirstView().GetDocument().DeleteAllViews()
323 return
324
325 docManager = self.GetDocumentManager()
326 template = wx.lib.docview.DocTemplate(docManager,
327 _("Python Interpreter"),
328 "*.Foobar",
329 "Foobar",
330 ".Foobar",
331 _("Python Interpreter Document"),
332 _("Python Interpreter View"),
333 wx.lib.docview.Document,
334 PythonInterpreterView,
335 flags = wx.lib.docview.TEMPLATE_INVISIBLE)
336 newDoc = template.CreateDocument('', wx.lib.docview.DOC_SILENT)
337 if newDoc:
338 newDoc.SetDocumentName(template.GetDocumentName())
339 newDoc.SetDocumentTemplate(template)
340 newDoc.OnNewDocument()
341 newDoc.SetWriteable(False)
342 newDoc.GetFirstView().GetFrame().SetTitle(_("Python Interpreter"))
343
344
345 class PythonCtrl(CodeEditor.CodeCtrl):
346
347
348 def __init__(self, parent, id=-1, style=wx.NO_FULL_REPAINT_ON_RESIZE):
349 CodeEditor.CodeCtrl.__init__(self, parent, id, style)
350 self.SetProperty("tab.timmy.whinge.level", "1")
351 self.SetProperty("fold.comment.python", "1")
352 self.SetProperty("fold.quotes.python", "1")
353 self.SetLexer(wx.stc.STC_LEX_PYTHON)
354 self.SetKeyWords(0, string.join(keyword.kwlist))
355
356
357 def SetViewDefaults(self):
358 CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Python", hasWordWrap = False, hasTabs = True)
359
360
361 def GetFontAndColorFromConfig(self):
362 return CodeEditor.CodeCtrl.GetFontAndColorFromConfig(self, configPrefix = "Python")
363
364
365 def UpdateStyles(self):
366 CodeEditor.CodeCtrl.UpdateStyles(self)
367
368 if not self.GetFont():
369 return
370
371 faces = { 'font' : self.GetFont().GetFaceName(),
372 'size' : self.GetFont().GetPointSize(),
373 'size2': self.GetFont().GetPointSize() - 2,
374 'color' : "%02x%02x%02x" % (self.GetFontColor().Red(), self.GetFontColor().Green(), self.GetFontColor().Blue())
375 }
376
377 # Python styles
378 # White space
379 self.StyleSetSpec(wx.stc.STC_P_DEFAULT, "face:%(font)s,fore:#000000,face:%(font)s,size:%(size)d" % faces)
380 # Comment
381 self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, "face:%(font)s,fore:#007F00,italic,face:%(font)s,size:%(size)d" % faces)
382 # Number
383 self.StyleSetSpec(wx.stc.STC_P_NUMBER, "face:%(font)s,fore:#007F7F,size:%(size)d" % faces)
384 # String
385 self.StyleSetSpec(wx.stc.STC_P_STRING, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces)
386 # Single quoted string
387 self.StyleSetSpec(wx.stc.STC_P_CHARACTER, "face:%(font)s,fore:#7F007F,face:%(font)s,size:%(size)d" % faces)
388 # Keyword
389 self.StyleSetSpec(wx.stc.STC_P_WORD, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces)
390 # Triple quotes
391 self.StyleSetSpec(wx.stc.STC_P_TRIPLE, "face:%(font)s,fore:#7F0000,size:%(size)d" % faces)
392 # Triple double quotes
393 self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, "face:%(font)s,fore:#7F0000,size:%(size)d" % faces)
394 # Class name definition
395 self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, "face:%(font)s,fore:#0000FF,bold,size:%(size)d" % faces)
396 # Function or method name definition
397 self.StyleSetSpec(wx.stc.STC_P_DEFNAME, "face:%(font)s,fore:#007F7F,bold,size:%(size)d" % faces)
398 # Operators
399 self.StyleSetSpec(wx.stc.STC_P_OPERATOR, "face:%(font)s,size:%(size)d" % faces)
400 # Identifiers
401 self.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, "face:%(font)s,fore:#%(color)s,face:%(font)s,size:%(size)d" % faces)
402 # Comment-blocks
403 self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, "face:%(font)s,fore:#7F7F7F,size:%(size)d" % faces)
404 # End of line where string is not closed
405 self.StyleSetSpec(wx.stc.STC_P_STRINGEOL, "face:%(font)s,fore:#000000,face:%(font)s,back:#E0C0E0,eol,size:%(size)d" % faces)
406
407
408 def OnUpdateUI(self, evt):
409 braces = self.GetMatchingBraces()
410
411 # check for matching braces
412 braceAtCaret = -1
413 braceOpposite = -1
414 charBefore = None
415 caretPos = self.GetCurrentPos()
416 if caretPos > 0:
417 charBefore = self.GetCharAt(caretPos - 1)
418 styleBefore = self.GetStyleAt(caretPos - 1)
419
420 # check before
421 if charBefore and chr(charBefore) in braces and styleBefore == wx.stc.STC_P_OPERATOR:
422 braceAtCaret = caretPos - 1
423
424 # check after
425 if braceAtCaret < 0:
426 charAfter = self.GetCharAt(caretPos)
427 styleAfter = self.GetStyleAt(caretPos)
428 if charAfter and chr(charAfter) in braces and styleAfter == wx.stc.STC_P_OPERATOR:
429 braceAtCaret = caretPos
430
431 if braceAtCaret >= 0:
432 braceOpposite = self.BraceMatch(braceAtCaret)
433
434 if braceAtCaret != -1 and braceOpposite == -1:
435 self.BraceBadLight(braceAtCaret)
436 else:
437 self.BraceHighlight(braceAtCaret, braceOpposite)
438
439 evt.Skip()
440
441
442 def DoIndent(self):
443 (text, caretPos) = self.GetCurLine()
444
445 self._tokenizerChars = {} # This is really too much, need to find something more like a C array
446 for i in range(len(text)):
447 self._tokenizerChars[i] = 0
448
449 ctext = cStringIO.StringIO(text)
450 try:
451 tokenize.tokenize(ctext.readline, self)
452 except:
453 pass
454
455 # Left in for debugging purposes:
456 #for i in range(len(text)):
457 # print i, text[i], self._tokenizerChars[i]
458
459 if caretPos == 0 or len(string.strip(text)) == 0: # At beginning of line or within an empty line
460 self.AddText('\n')
461 else:
462 doExtraIndent = False
463 brackets = False
464 commentStart = -1
465 if caretPos > 1:
466 startParenCount = 0
467 endParenCount = 0
468 startSquareBracketCount = 0
469 endSquareBracketCount = 0
470 startCurlyBracketCount = 0
471 endCurlyBracketCount = 0
472 startQuoteCount = 0
473 endQuoteCount = 0
474 for i in range(caretPos - 1, -1, -1): # Go through each character before the caret
475 if i >= len(text): # Sometimes the caret is at the end of the text if there is no LF
476 continue
477 if self._tokenizerChars[i] == 1:
478 continue
479 elif self._tokenizerChars[i] == 2:
480 startQuoteCount = startQuoteCount + 1
481 elif self._tokenizerChars[i] == 3:
482 endQuoteCount = endQuoteCount + 1
483 elif text[i] == '(': # Would be nice to use a dict for this, but the code is much more readable this way
484 startParenCount = startParenCount + 1
485 elif text[i] == ')':
486 endParenCount = endParenCount + 1
487 elif text[i] == "[":
488 startSquareBracketCount = startSquareBracketCount + 1
489 elif text[i] == "]":
490 endSquareBracketCount = endSquareBracketCount + 1
491 elif text[i] == "{":
492 startCurlyBracketCount = startCurlyBracketCount + 1
493 elif text[i] == "}":
494 endCurlyBracketCount = endCurlyBracketCount + 1
495 elif text[i] == "#":
496 commentStart = i
497 break
498 if startQuoteCount > endQuoteCount or startParenCount > endParenCount or startSquareBracketCount > endSquareBracketCount or startCurlyBracketCount > endCurlyBracketCount:
499 if i + 1 >= caretPos: # Caret is right at the open paren, so just do indent as if colon was there
500 doExtraIndent = True
501 break
502 else:
503 spaces = " " * (i + 1)
504 brackets = True
505 break
506 if not brackets:
507 spaces = text[0:len(text) - len(string.lstrip(text))]
508 if caretPos < len(spaces): # If within the opening spaces of a line
509 spaces = spaces[:caretPos]
510
511 # strip comment off
512 if commentStart != -1:
513 text = text[0:commentStart]
514
515 textNoTrailingSpaces = text[0:caretPos].rstrip()
516 if doExtraIndent or len(textNoTrailingSpaces) and textNoTrailingSpaces[-1] == ':':
517 spaces = spaces + ' ' * self.GetIndent()
518 self.AddText('\n' + spaces)
519 self.EnsureCaretVisible()
520
521
522 # Callback for tokenizer in self.DoIndent
523 def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
524 if toktype == tokenize.COMMENT:
525 for i in range(scol, ecol + 1):
526 self._validChars[i] = False
527 elif toktype == token.STRING:
528 self._tokenizerChars[scol] = 2 # Open quote
529 self._tokenizerChars[ecol - 1] = 3 # Close quote
530 for i in range(scol + 1, ecol - 2):
531 self._tokenizerChars[i] = 1 # Part of string, 1 == ignore the char
532
533
534 class PythonOptionsPanel(wx.Panel):
535
536 def __init__(self, parent, id):
537 wx.Panel.__init__(self, parent, id)
538 pathLabel = wx.StaticText(self, -1, _("python.exe Path:"))
539 config = wx.ConfigBase_Get()
540 path = config.Read("ActiveGridPythonLocation")
541 self._pathTextCtrl = wx.TextCtrl(self, -1, path, size = (150, -1))
542 self._pathTextCtrl.SetToolTipString(self._pathTextCtrl.GetValue())
543 self._pathTextCtrl.SetInsertionPointEnd()
544 choosePathButton = wx.Button(self, -1, _("Browse..."))
545 pathSizer = wx.BoxSizer(wx.HORIZONTAL)
546 HALF_SPACE = 5
547 pathSizer.Add(pathLabel, 0, wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, HALF_SPACE)
548 pathSizer.Add(self._pathTextCtrl, 0, wx.ALIGN_LEFT | wx.EXPAND | wx.RIGHT, HALF_SPACE)
549 pathSizer.Add(choosePathButton, 0, wx.ALIGN_RIGHT | wx.LEFT, HALF_SPACE)
550 wx.EVT_BUTTON(self, choosePathButton.GetId(), self.OnChoosePath)
551 mainSizer = wx.BoxSizer(wx.VERTICAL)
552 mainSizer.Add(pathSizer, 0, wx.LEFT | wx.RIGHT | wx.TOP, 10)
553
554 self._otherOptions = STCTextEditor.TextOptionsPanel(self, -1, configPrefix = "Python", label = "Python", hasWordWrap = False, hasTabs = True, addPage=False)
555 mainSizer.Add(self._otherOptions)
556 self.SetSizer(mainSizer)
557 parent.AddPage(self, _("Python"))
558
559 def OnChoosePath(self, event):
560 if _WINDOWS:
561 wildcard = _("*.exe")
562 else:
563 wildcard = _("*")
564 path = wx.FileSelector(_("Select a File"),
565 _(""),
566 _(""),
567 wildcard = wildcard ,
568 flags = wx.HIDE_READONLY,
569 parent = wx.GetApp().GetTopWindow())
570 if path:
571 self._pathTextCtrl.SetValue(path)
572 self._pathTextCtrl.SetToolTipString(self._pathTextCtrl.GetValue())
573 self._pathTextCtrl.SetInsertionPointEnd()
574
575 def OnOK(self, optionsDialog):
576 if len(self._pathTextCtrl.GetValue()) > 0:
577 config = wx.ConfigBase_Get()
578 config.Write("ActiveGridPythonLocation", self._pathTextCtrl.GetValue())
579
580 self._otherOptions.OnOK(optionsDialog)
581 #----------------------------------------------------------------------------
582 # Icon Bitmaps - generated by encode_bitmaps.py
583 #----------------------------------------------------------------------------
584 from wx import ImageFromStream, BitmapFromImage
585 import cStringIO
586
587
588 def getPythonData():
589 return \
590 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
591 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
592 \x00\x00\xd5IDAT8\x8d\x8d\x93Y\x0e\xc3 \x0cD\x9fM\xcf\xddNr2.\x96\xb8\x1f\
593 \x05\n\x84.#Y\x10\xa3\x19o\xb1\x99'*\xe2<\x82\x0e\xe6\xc9\xf8\x01\xef?\xa4\
594 \xf7)]\x05\x970O\xcdr\xce!\x119\xe7\x00\x02\x88\xfe}i\xb5\x848\x8f\xa8\x19\
595 \xcc\x19}+\xc5\xcc\xd3\x92<CZ\x0b\x99\xc4\xb2N\x01<\x80\xad\xdc?\x88\xf8\x1c\
596 X\x8f7\xe1\x1f\xdc*\xa9a+\xe1\xa3\xdc\xe7\xb4\xf6\xd1\xe5\xb6'\xc3@\xc5\xa0#\
597 \xab\x94\xd1\x0bL\xf0\xe6\x17\xa8v\xc3\x8aS\xa0.\x8be\x13\xe3\x15\x8f\xe1\
598 \xa5D\xee\xc9\xdb~%\xc7y\x84\xbb'sO\xd6\xd4\x17\xe4~\xc4\xf5\xef\xac\xa7\r\
599 \xbbp?b&\x0f\x89i\x14\x93\xca\x14z\xc5oh\x02E\xc4<\xd92\x03\xe0:B^\xc4K#\xe7\
600 \xe5\x00\x02\xfd\xb9H\x9ex\x02\x9a\x05a\xd2\xd3c\xc0\xcc\x00\x00\x00\x00IEND\
601 \xaeB`\x82"
602
603
604 def getPythonBitmap():
605 return BitmapFromImage(getPythonImage())
606
607 def getPythonImage():
608 stream = cStringIO.StringIO(getPythonData())
609 return ImageFromStream(stream)
610
611 def getPythonIcon():
612 return wx.IconFromBitmap(getPythonBitmap())