]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/ide/activegrid/tool/DebuggerService.py
Tweaks for demos on MacOSX
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / DebuggerService.py
1 #----------------------------------------------------------------------------
2 # Name: DebuggerService.py
3 # Purpose: Debugger Service for Python.
4 #
5 # Author: Matt Fryer
6 #
7 # Created: 12/9/04
8 # CVS-ID: $Id$
9 # Copyright: (c) 2004-2005 ActiveGrid, Inc.
10 # License: wxWindows License
11 #----------------------------------------------------------------------------
12
13 import wx
14 import wx.lib.intctrl
15 import wx.lib.docview
16 import wx.lib.dialogs
17 import wx.gizmos
18 import wx._core
19 import wx.lib.pydocview
20 import Service
21 import STCTextEditor
22 import CodeEditor
23 import PythonEditor
24 from IDE import ACTIVEGRID_BASE_IDE
25 if not ACTIVEGRID_BASE_IDE:
26 import ProcessModelEditor
27 import wx.lib.scrolledpanel as scrolled
28 import sys
29 import time
30 import SimpleXMLRPCServer
31 import xmlrpclib
32 import os
33 import threading
34 import Queue
35 import SocketServer
36 import ProjectEditor
37 import types
38 from xml.dom.minidom import parse, parseString
39 import bz2
40 import pickle
41 import DebuggerHarness
42 import traceback
43 import StringIO
44 import UICommon
45 if wx.Platform == '__WXMSW__':
46 try:
47 import win32api
48 _PYWIN32_INSTALLED = True
49 except ImportError:
50 _PYWIN32_INSTALLED = False
51 _WINDOWS = True
52 else:
53 _WINDOWS = False
54
55 if not _WINDOWS or _PYWIN32_INSTALLED:
56 import process
57
58 _ = wx.GetTranslation
59
60 _VERBOSE = False
61 _WATCHES_ON = False
62
63 # Class to read from stdout or stderr and write the result to a text control.
64 # Args: file=file-like object
65 # callback_function= function that takes a single argument, the line of text
66 # read.
67 class OutputReaderThread(threading.Thread):
68 def __init__(self, file, callback_function, callbackOnExit=None, accumulate=True):
69 threading.Thread.__init__(self)
70 self._file = file
71 self._callback_function = callback_function
72 self._keepGoing = True
73 self._lineCount = 0
74 self._accumulate = accumulate
75 self._callbackOnExit = callbackOnExit
76 self.setDaemon(True)
77
78 def __del__(self):
79 # See comment on DebugCommandUI.StopExecution
80 self._keepGoing = False
81
82 def run(self):
83 file = self._file
84 start = time.time()
85 output = ""
86 while self._keepGoing:
87 try:
88 # This could block--how to handle that?
89 text = file.readline()
90 if text == '' or text == None:
91 self._keepGoing = False
92 elif not self._accumulate and self._keepGoing:
93 self._callback_function(text)
94 else:
95 # Should use a buffer? StringIO?
96 output += text
97 # Seems as though the read blocks if we got an error, so, to be
98 # sure that at least some of the exception gets printed, always
99 # send the first hundred lines back as they come in.
100 if self._lineCount < 100 and self._keepGoing:
101 self._callback_function(output)
102 self._lineCount += 1
103 output = ""
104 elif time.time() - start > 0.25 and self._keepGoing:
105 try:
106 self._callback_function(output)
107 except wx._core.PyDeadObjectError:
108 # GUI was killed while we were blocked.
109 self._keepGoing = False
110 start = time.time()
111 output = ""
112 #except TypeError:
113 # pass
114 except:
115 tp, val, tb = sys.exc_info()
116 print "Exception in OutputReaderThread.run():", tp, val
117 self._keepGoing = False
118 if self._callbackOnExit:
119 try:
120 self._callbackOnExit()
121 except wx._core.PyDeadObjectError:
122 pass
123 if _VERBOSE: print "Exiting OutputReaderThread"
124
125 def AskToStop(self):
126 self._keepGoing = False
127
128 import wx.lib.newevent
129 (UpdateTextEvent, EVT_UPDATE_STDTEXT) = wx.lib.newevent.NewEvent()
130 (UpdateErrorEvent, EVT_UPDATE_ERRTEXT) = wx.lib.newevent.NewEvent()
131
132 class Executor:
133
134 def GetPythonExecutablePath():
135 path = UICommon.GetPythonExecPath()
136 if path:
137 return path
138 wx.MessageBox(_("To proceed I need to know the location of the python.exe you would like to use.\nTo set this, go to Tools-->Options and use the 'Python' tab to enter a value.\n"), _("Python Executable Location Unknown"))
139 return None
140 GetPythonExecutablePath = staticmethod(GetPythonExecutablePath)
141
142 def __init__(self, fileName, wxComponent, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None, arg6=None, arg7=None, arg8=None, arg9=None, callbackOnExit=None):
143 self._fileName = fileName
144 self._stdOutCallback = self.OutCall
145 self._stdErrCallback = self.ErrCall
146 self._callbackOnExit = callbackOnExit
147 self._wxComponent = wxComponent
148 path = Executor.GetPythonExecutablePath()
149 self._cmd = '"' + path + '" -u \"' + fileName + '\"'
150 #Better way to do this? Quotes needed for windows file paths.
151 def spaceAndQuote(text):
152 if text.startswith("\"") and text.endswith("\""):
153 return ' ' + text
154 else:
155 return ' \"' + text + '\"'
156 if(arg1 != None):
157 self._cmd += spaceAndQuote(arg1)
158 if(arg2 != None):
159 self._cmd += spaceAndQuote(arg2)
160 if(arg3 != None):
161 self._cmd += spaceAndQuote(arg3)
162 if(arg4 != None):
163 self._cmd += spaceAndQuote(arg4)
164 if(arg5 != None):
165 self._cmd += spaceAndQuote(arg5)
166 if(arg6 != None):
167 self._cmd += spaceAndQuote(arg6)
168 if(arg7 != None):
169 self._cmd += spaceAndQuote(arg7)
170 if(arg8 != None):
171 self._cmd += spaceAndQuote(arg8)
172 if(arg9 != None):
173 self._cmd += spaceAndQuote(arg9)
174
175 self._stdOutReader = None
176 self._stdErrReader = None
177 self._process = None
178
179 def OutCall(self, text):
180 evt = UpdateTextEvent(value = text)
181 wx.PostEvent(self._wxComponent, evt)
182
183 def ErrCall(self, text):
184 evt = UpdateErrorEvent(value = text)
185 wx.PostEvent(self._wxComponent, evt)
186
187 def Execute(self, arguments, startIn=None, environment=None):
188 if not startIn:
189 startIn = str(os.getcwd())
190 startIn = os.path.abspath(startIn)
191 command = self._cmd + ' ' + arguments
192 self._process = process.ProcessOpen(command, mode='b', cwd=startIn, env=environment)
193 # Kick off threads to read stdout and stderr and write them
194 # to our text control.
195 self._stdOutReader = OutputReaderThread(self._process.stdout, self._stdOutCallback, callbackOnExit=self._callbackOnExit)
196 self._stdOutReader.start()
197 self._stdErrReader = OutputReaderThread(self._process.stderr, self._stdErrCallback, accumulate=False)
198 self._stdErrReader.start()
199
200 def DoStopExecution(self):
201 # See comment on DebugCommandUI.StopExecution
202 if(self._process != None):
203 self._stdOutReader.AskToStop()
204 self._stdErrReader.AskToStop()
205 try:
206 self._process.kill(gracePeriod=2.0)
207 except:
208 pass
209 self._process = None
210
211 class RunCommandUI(wx.Panel):
212 runners = []
213
214 def ShutdownAllRunners():
215 # See comment on DebugCommandUI.StopExecution
216 for runner in RunCommandUI.runners:
217 try:
218 runner.StopExecution(None)
219 except wx._core.PyDeadObjectError:
220 pass
221 RunCommandUI.runners = []
222 ShutdownAllRunners = staticmethod(ShutdownAllRunners)
223
224 def __init__(self, parent, id, fileName):
225 wx.Panel.__init__(self, parent, id)
226 self._noteBook = parent
227
228 threading._VERBOSE = _VERBOSE
229
230 self.KILL_PROCESS_ID = wx.NewId()
231 self.CLOSE_TAB_ID = wx.NewId()
232
233
234 # GUI Initialization follows
235 sizer = wx.BoxSizer(wx.HORIZONTAL)
236 self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (30,1000), wx.TB_VERTICAL| wx.TB_FLAT, "Runner" )
237 tb.SetToolBitmapSize((16,16))
238 sizer.Add(tb, 0, wx.EXPAND|wx.ALIGN_LEFT|wx.ALL, 1)
239
240 close_bmp = getCloseBitmap()
241 tb.AddSimpleTool( self.CLOSE_TAB_ID, close_bmp, _('Close Window'))
242 wx.EVT_TOOL(self, self.CLOSE_TAB_ID, self.OnToolClicked)
243
244 stop_bmp = getStopBitmap()
245 tb.AddSimpleTool(self.KILL_PROCESS_ID, stop_bmp, _("Stop the Run."))
246 wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.OnToolClicked)
247
248 tb.Realize()
249 self._textCtrl = STCTextEditor.TextCtrl(self, wx.NewId()) #id)
250 sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
251 self._textCtrl.SetViewLineNumbers(False)
252 self._textCtrl.SetReadOnly(True)
253 if wx.Platform == '__WXMSW__':
254 font = "Courier New"
255 else:
256 font = "Courier"
257 self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
258 self._textCtrl.SetFontColor(wx.BLACK)
259 self._textCtrl.StyleClearAll()
260
261 #Disabling for now...may interfere with file open. wx.stc.EVT_STC_DOUBLECLICK(self._textCtrl, self._textCtrl.GetId(), self.OnDoubleClick)
262
263 self.SetSizer(sizer)
264 sizer.Fit(self)
265
266 self._stopped = False
267 # Executor initialization
268 self._executor = Executor(fileName, self, callbackOnExit=self.ExecutorFinished)
269 self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
270 self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
271
272 RunCommandUI.runners.append(self)
273
274 def __del__(self):
275 # See comment on DebugCommandUI.StopExecution
276 self._executor.DoStopExecution()
277
278 def Execute(self, initialArgs, startIn, environment):
279 self._executor.Execute(initialArgs, startIn, environment)
280
281 def ExecutorFinished(self):
282 self._tb.EnableTool(self.KILL_PROCESS_ID, False)
283 nb = self.GetParent()
284 for i in range(0,nb.GetPageCount()):
285 if self == nb.GetPage(i):
286 text = nb.GetPageText(i)
287 newText = text.replace("Running", "Finished")
288 nb.SetPageText(i, newText)
289 break
290
291 def StopExecution(self):
292 if not self._stopped:
293 self._stopped = True
294 self.Unbind(EVT_UPDATE_STDTEXT)
295 self.Unbind(EVT_UPDATE_ERRTEXT)
296 self._executor.DoStopExecution()
297
298 def AppendText(self, event):
299 self._textCtrl.SetReadOnly(False)
300 self._textCtrl.AddText(event.value)
301 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
302 self._textCtrl.SetReadOnly(True)
303
304 def AppendErrorText(self, event):
305 self._textCtrl.SetReadOnly(False)
306 self._textCtrl.SetFontColor(wx.RED)
307 self._textCtrl.StyleClearAll()
308 self._textCtrl.AddText(event.value)
309 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
310 self._textCtrl.SetFontColor(wx.BLACK)
311 self._textCtrl.StyleClearAll()
312 self._textCtrl.SetReadOnly(True)
313
314 def StopAndRemoveUI(self, event):
315 self.StopExecution()
316 self.StopExecution()
317 index = self._noteBook.GetSelection()
318 self._noteBook.GetPage(index).Show(False)
319 self._noteBook.RemovePage(index)
320
321 #------------------------------------------------------------------------------
322 # Event handling
323 #-----------------------------------------------------------------------------
324
325 def OnToolClicked(self, event):
326 id = event.GetId()
327
328 if id == self.KILL_PROCESS_ID:
329 self.StopExecution()
330
331 elif id == self.CLOSE_TAB_ID:
332 self.StopAndRemoveUI(event)
333
334 def OnDoubleClick(self, event):
335 # Looking for a stack trace line.
336 lineText, pos = self._textCtrl.GetCurLine()
337 fileBegin = lineText.find("File \"")
338 fileEnd = lineText.find("\", line ")
339 lineEnd = lineText.find(", in ")
340 if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
341 # Check the line before the one that was clicked on
342 lineNumber = self._textCtrl.GetCurrentLine()
343 if(lineNumber == 0):
344 return
345 lineText = self._textCtrl.GetLine(lineNumber - 1)
346 fileBegin = lineText.find("File \"")
347 fileEnd = lineText.find("\", line ")
348 lineEnd = lineText.find(", in ")
349 if lineText == "\n" or fileBegin == -1 or fileEnd == -1 or lineEnd == -1:
350 return
351
352 filename = lineText[fileBegin + 6:fileEnd]
353 lineNum = int(lineText[fileEnd + 8:lineEnd])
354
355 foundView = None
356 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
357 for openDoc in openDocs:
358 if openDoc.GetFilename() == filename:
359 foundView = openDoc.GetFirstView()
360 break
361
362 if not foundView:
363 doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT)
364 foundView = doc.GetFirstView()
365
366 if foundView:
367 foundView.GetFrame().SetFocus()
368 foundView.Activate()
369 foundView.GotoLine(lineNum)
370 startPos = foundView.PositionFromLine(lineNum)
371
372 # FACTOR THIS INTO DocManager
373 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
374 for openDoc in openDocs:
375 if(isinstance(openDoc, CodeEditor.CodeDocument)):
376 openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
377
378 foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
379
380
381 DEFAULT_PORT = 32032
382 DEFAULT_HOST = 'localhost'
383 PORT_COUNT = 21
384
385 class DebugCommandUI(wx.Panel):
386 debuggerPortList = None
387 debuggers = []
388
389 def NotifyDebuggersOfBreakpointChange():
390 for debugger in DebugCommandUI.debuggers:
391 debugger.BreakPointChange()
392
393 NotifyDebuggersOfBreakpointChange = staticmethod(NotifyDebuggersOfBreakpointChange)
394
395 def DebuggerRunning():
396 for debugger in DebugCommandUI.debuggers:
397 if debugger._executor:
398 return True
399 return False
400 DebuggerRunning = staticmethod(DebuggerRunning)
401
402 def ShutdownAllDebuggers():
403 # See comment on DebugCommandUI.StopExecution
404 for debugger in DebugCommandUI.debuggers:
405 try:
406 debugger.StopExecution(None)
407 except wx._core.PyDeadObjectError:
408 pass
409 DebugCommandUI.debuggers = []
410 ShutdownAllDebuggers = staticmethod(ShutdownAllDebuggers)
411
412 def GetAvailablePort():
413 for index in range( 0, len(DebugCommandUI.debuggerPortList)):
414 port = DebugCommandUI.debuggerPortList[index]
415 if DebugCommandUI.PortAvailable(port):
416 DebugCommandUI.debuggerPortList.pop(index)
417 return port
418 wx.MessageBox(_("Out of ports for debugging! Please restart the application builder.\nIf that does not work, check for and remove running instances of python."), _("Out of Ports"))
419 assert False, "Out of ports for debugger."
420
421 GetAvailablePort = staticmethod(GetAvailablePort)
422
423 def ReturnPortToPool(port):
424 config = wx.ConfigBase_Get()
425 startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
426 val = int(startingPort) + int(PORT_COUNT)
427 if int(port) >= startingPort and (int(port) <= val):
428 DebugCommandUI.debuggerPortList.append(int(port))
429
430 ReturnPortToPool = staticmethod(ReturnPortToPool)
431
432 def PortAvailable(port):
433 config = wx.ConfigBase_Get()
434 hostname = config.Read("DebuggerHostName", DEFAULT_HOST)
435 try:
436 server = AGXMLRPCServer((hostname, port))
437 server.server_close()
438 if _VERBOSE: print "Port ", str(port), " available."
439 return True
440 except:
441 tp,val,tb = sys.exc_info()
442 if _VERBOSE: traceback.print_exception(tp, val, tb)
443 if _VERBOSE: print "Port ", str(port), " unavailable."
444 return False
445
446 PortAvailable = staticmethod(PortAvailable)
447
448 def NewPortRange():
449 config = wx.ConfigBase_Get()
450 startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
451 DebugCommandUI.debuggerPortList = range(startingPort, startingPort + PORT_COUNT)
452 NewPortRange = staticmethod(NewPortRange)
453
454 def __init__(self, parent, id, command, service):
455 # Check for ports before creating the panel.
456 if not DebugCommandUI.debuggerPortList:
457 DebugCommandUI.NewPortRange()
458 self._debuggerPort = str(DebugCommandUI.GetAvailablePort())
459 self._guiPort = str(DebugCommandUI.GetAvailablePort())
460 self._debuggerBreakPort = str(DebugCommandUI.GetAvailablePort())
461
462 wx.Panel.__init__(self, parent, id)
463
464 self._parentNoteBook = parent
465 self._command = command
466 self._service = service
467 self._executor = None
468 self.STEP_ID = wx.NewId()
469 self.CONTINUE_ID = wx.NewId()
470 self.STEP_OUT_ID = wx.NewId()
471 self.NEXT_ID = wx.NewId()
472 self.KILL_PROCESS_ID = wx.NewId()
473 self.CLOSE_WINDOW_ID = wx.NewId()
474 self.BREAK_INTO_DEBUGGER_ID = wx.NewId()
475 self.CLEAR_ID = wx.NewId()
476 self.ADD_WATCH_ID = wx.NewId()
477 sizer = wx.BoxSizer(wx.VERTICAL)
478 self._tb = tb = wx.ToolBar(self, -1, wx.DefaultPosition, (1000,30), wx.TB_HORIZONTAL| wx.NO_BORDER| wx.TB_FLAT| wx.TB_TEXT, "Debugger" )
479 sizer.Add(tb, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
480 tb.SetToolBitmapSize((16,16))
481
482 close_bmp = getCloseBitmap()
483 tb.AddSimpleTool( self.CLOSE_WINDOW_ID, close_bmp, _('Close Window'))
484 wx.EVT_TOOL(self, self.CLOSE_WINDOW_ID, self.StopAndRemoveUI)
485
486 stop_bmp = getStopBitmap()
487 tb.AddSimpleTool( self.KILL_PROCESS_ID, stop_bmp, _("Stop Debugging"))
488 wx.EVT_TOOL(self, self.KILL_PROCESS_ID, self.StopExecution)
489
490 tb.AddSeparator()
491
492 break_bmp = getBreakBitmap()
493 tb.AddSimpleTool( self.BREAK_INTO_DEBUGGER_ID, break_bmp, _("Break into Debugger"))
494 wx.EVT_TOOL(self, self.BREAK_INTO_DEBUGGER_ID, self.BreakExecution)
495
496 tb.AddSeparator()
497
498 continue_bmp = getContinueBitmap()
499 tb.AddSimpleTool( self.CONTINUE_ID, continue_bmp, _("Continue Execution"))
500 wx.EVT_TOOL(self, self.CONTINUE_ID, self.OnContinue)
501
502 tb.AddSeparator()
503
504 next_bmp = getNextBitmap()
505 tb.AddSimpleTool( self.NEXT_ID, next_bmp, _("Step to next line"))
506 wx.EVT_TOOL(self, self.NEXT_ID, self.OnNext)
507
508 step_bmp = getStepInBitmap()
509 tb.AddSimpleTool( self.STEP_ID, step_bmp, _("Step in"))
510 wx.EVT_TOOL(self, self.STEP_ID, self.OnSingleStep)
511
512 stepOut_bmp = getStepReturnBitmap()
513 tb.AddSimpleTool(self.STEP_OUT_ID, stepOut_bmp, _("Stop at function return"))
514 wx.EVT_TOOL(self, self.STEP_OUT_ID, self.OnStepOut)
515
516 tb.AddSeparator()
517 if _WATCHES_ON:
518 watch_bmp = getAddWatchBitmap()
519 tb.AddSimpleTool(self.ADD_WATCH_ID, watch_bmp, _("Add a watch"))
520 wx.EVT_TOOL(self, self.ADD_WATCH_ID, self.OnAddWatch)
521 tb.AddSeparator()
522
523 clear_bmp = getClearOutputBitmap()
524 tb.AddSimpleTool(self.CLEAR_ID, clear_bmp, _("Clear output pane"))
525 wx.EVT_TOOL(self, self.CLEAR_ID, self.OnClearOutput)
526
527 self.framesTab = None
528 self.DisableWhileDebuggerRunning()
529 self.framesTab = self.MakeFramesUI(self, wx.NewId(), None)
530 sizer.Add(self.framesTab, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
531 self._statusBar = wx.StatusBar( self, -1)
532 self._statusBar.SetFieldsCount(1)
533 sizer.Add(self._statusBar, 0, wx.EXPAND |wx.ALIGN_LEFT|wx.ALL, 1)
534
535 self.SetStatusText("Starting debug...")
536
537 self.SetSizer(sizer)
538 tb.Realize()
539 sizer.Fit(self)
540 config = wx.ConfigBase_Get()
541 self._debuggerHost = self._guiHost = config.Read("DebuggerHostName", DEFAULT_HOST)
542 url = 'http://' + self._debuggerHost + ':' + self._debuggerPort + '/'
543 self._breakURL = 'http://' + self._debuggerHost + ':' + self._debuggerBreakPort + '/'
544 self._callback = DebuggerCallback(self._guiHost, self._guiPort, url, self._breakURL, self)
545 if DebuggerHarness.__file__.find('library.zip') > 0:
546 try:
547 fname = DebuggerHarness.__file__
548 parts = fname.split('library.zip')
549 path = os.path.join(parts[0],'activegrid', 'tool', 'DebuggerHarness.py')
550 except:
551 tp, val, tb = sys.exc_info()
552 traceback.print_exception(tp, val, tb)
553
554 else:
555 print "Starting debugger on these ports: %s, %s, %s" % (str(self._debuggerPort) , str(self._guiPort) , str(self._debuggerBreakPort))
556 path = DebuggerService.ExpandPath(DebuggerHarness.__file__)
557 self._executor = Executor(path, self, self._debuggerHost, \
558 self._debuggerPort, self._debuggerBreakPort, self._guiHost, self._guiPort, self._command, callbackOnExit=self.ExecutorFinished)
559
560 self.Bind(EVT_UPDATE_STDTEXT, self.AppendText)
561 self.Bind(EVT_UPDATE_ERRTEXT, self.AppendErrorText)
562 DebugCommandUI.debuggers.append(self)
563 self._stopped = False
564
565 def OnSingleStep(self, event):
566 self._callback.SingleStep()
567
568 def OnContinue(self, event):
569 self._callback.Continue()
570
571 def OnStepOut(self, event):
572 self._callback.Return()
573
574 def OnNext(self, event):
575 self._callback.Next()
576
577 def BreakPointChange(self):
578 if not self._stopped:
579 self._callback.pushBreakpoints()
580 self.framesTab.PopulateBPList()
581
582 def __del__(self):
583 # See comment on DebugCommandUI.StopExecution
584 self.StopExecution(None)
585
586 def DisableWhileDebuggerRunning(self):
587 self._tb.EnableTool(self.STEP_ID, False)
588 self._tb.EnableTool(self.CONTINUE_ID, False)
589 self._tb.EnableTool(self.STEP_OUT_ID, False)
590 self._tb.EnableTool(self.NEXT_ID, False)
591 self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, True)
592 if _WATCHES_ON:
593 self._tb.EnableTool(self.ADD_WATCH_ID, False)
594 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
595 for openDoc in openDocs:
596 if(isinstance(openDoc, CodeEditor.CodeDocument)):
597 openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
598 if self.framesTab:
599 self.framesTab.ClearWhileRunning()
600
601 def EnableWhileDebuggerStopped(self):
602 self._tb.EnableTool(self.STEP_ID, True)
603 self._tb.EnableTool(self.CONTINUE_ID, True)
604 self._tb.EnableTool(self.STEP_OUT_ID, True)
605 self._tb.EnableTool(self.NEXT_ID, True)
606 if _WATCHES_ON:
607 self._tb.EnableTool(self.ADD_WATCH_ID, True)
608 self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
609
610 def ExecutorFinished(self):
611 if _VERBOSE: print "In ExectorFinished"
612 try:
613 self.DisableAfterStop()
614 except wx._core.PyDeadObjectError:
615 pass
616 try:
617 nb = self.GetParent()
618 for i in range(0, nb.GetPageCount()):
619 if self == nb.GetPage(i):
620 text = nb.GetPageText(i)
621 newText = text.replace("Debugging", "Finished")
622 nb.SetPageText(i, newText)
623 if _VERBOSE: print "In ExectorFinished, changed tab title."
624 break
625 except:
626 if _VERBOSE: print "In ExectorFinished, got exception"
627
628 def DisableAfterStop(self):
629 self.DisableWhileDebuggerRunning()
630 self._tb.EnableTool(self.BREAK_INTO_DEBUGGER_ID, False)
631 self._tb.EnableTool(self.KILL_PROCESS_ID, False)
632
633 def SynchCurrentLine(self, filename, lineNum, noArrow=False):
634 # FACTOR THIS INTO DocManager
635 self.DeleteCurrentLineMarkers()
636
637 # Filename will be <string> if we're in a bit of code that was executed from
638 # a string (rather than a file). I haven't been able to get the original string
639 # for display.
640 if filename == '<string>':
641 return
642 foundView = None
643 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
644 for openDoc in openDocs:
645 # This ugliness to prevent comparison failing because the drive letter
646 # gets lowercased occasionally. Don't know why that happens or why it
647 # only happens occasionally.
648 if DebuggerService.ComparePaths(openDoc.GetFilename(),filename):
649 foundView = openDoc.GetFirstView()
650 break
651
652 if not foundView:
653 if _VERBOSE:
654 print "filename=", filename
655 doc = wx.GetApp().GetDocumentManager().CreateDocument(DebuggerService.ExpandPath(filename), wx.lib.docview.DOC_SILENT)
656 foundView = doc.GetFirstView()
657
658 if foundView:
659 foundView.GetFrame().SetFocus()
660 foundView.Activate()
661 foundView.GotoLine(lineNum)
662 startPos = foundView.PositionFromLine(lineNum)
663
664 if not noArrow:
665 foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM)
666
667 def DeleteCurrentLineMarkers(self):
668 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
669 for openDoc in openDocs:
670 if(isinstance(openDoc, CodeEditor.CodeDocument)):
671 openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers()
672
673 def LoadFramesListXML(self, framesXML):
674 self.framesTab.LoadFramesListXML(framesXML)
675
676 def SetStatusText(self, text):
677 self._statusBar.SetStatusText(text,0)
678
679 def Execute(self, initialArgs, startIn, environment):
680 self._callback.start()
681 self._executor.Execute(initialArgs, startIn, environment)
682 self._callback.waitForRPC()
683
684 def BreakExecution(self, event):
685 self._callback.BreakExecution()
686
687
688 def StopExecution(self, event):
689 # This is a general comment on shutdown for the running and debugged processes. Basically, the
690 # current state of this is the result of trial and error coding. The common problems were memory
691 # access violations and threads that would not exit. Making the OutputReaderThreads daemons seems
692 # to have side-stepped the hung thread issue. Being very careful not to touch things after calling
693 # process.py:ProcessOpen.kill() also seems to have fixed the memory access violations, but if there
694 # were more ugliness discovered I would not be surprised. If anyone has any help/advice, please send
695 # it on to mfryer@activegrid.com.
696 if not self._stopped:
697 self._stopped = True
698 try:
699 self.DisableAfterStop()
700 except wx._core.PyDeadObjectError:
701 pass
702 try:
703 self._callback.ShutdownServer()
704 except:
705 tp,val,tb = sys.exc_info()
706 traceback.print_exception(tp, val, tb)
707
708 try:
709 self.DeleteCurrentLineMarkers()
710 except:
711 pass
712 try:
713 DebugCommandUI.ReturnPortToPool(self._debuggerPort)
714 DebugCommandUI.ReturnPortToPool(self._guiPort)
715 DebugCommandUI.ReturnPortToPool(self._debuggerBreakPort)
716 except:
717 pass
718 try:
719 if self._executor:
720 self._executor.DoStopExecution()
721 self._executor = None
722 except:
723 tp,val,tb = sys.exc_info()
724 traceback.print_exception(tp, val, tb)
725 def StopAndRemoveUI(self, event):
726 self.StopExecution(None)
727 if self in DebugCommandUI.debuggers:
728 DebugCommandUI.debuggers.remove(self)
729 index = self._parentNoteBook.GetSelection()
730 self._parentNoteBook.GetPage(index).Show(False)
731 self._parentNoteBook.RemovePage(index)
732
733 def OnAddWatch(self, event):
734 if self.framesTab:
735 self.framesTab.OnWatch(event)
736
737 def MakeFramesUI(self, parent, id, debugger):
738 panel = FramesUI(parent, id, self)
739 return panel
740
741 def AppendText(self, event):
742 self.framesTab.AppendText(event.value)
743
744 def AppendErrorText(self, event):
745 self.framesTab.AppendErrorText(event.value)
746
747 def OnClearOutput(self, event):
748 self.framesTab.ClearOutput(None)
749
750 def SwitchToOutputTab(self):
751 self.framesTab.SwitchToOutputTab()
752
753 class BreakpointsUI(wx.Panel):
754 def __init__(self, parent, id, ui):
755 wx.Panel.__init__(self, parent, id)
756 self._ui = ui
757 self.currentItem = None
758 self.clearBPID = wx.NewId()
759 self.Bind(wx.EVT_MENU, self.ClearBreakPoint, id=self.clearBPID)
760 self.syncLineID = wx.NewId()
761 self.Bind(wx.EVT_MENU, self.SyncBPLine, id=self.syncLineID)
762 sizer = wx.BoxSizer(wx.VERTICAL)
763 p1 = self
764 self._bpListCtrl = wx.ListCtrl(p1, -1, pos=wx.DefaultPosition, size=(1000,1000), style=wx.LC_REPORT)
765 sizer.Add(self._bpListCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
766 self._bpListCtrl.InsertColumn(0, "File")
767 self._bpListCtrl.InsertColumn(1, "Line")
768 self._bpListCtrl.InsertColumn(2, "Path")
769 self._bpListCtrl.SetColumnWidth(0, 150)
770 self._bpListCtrl.SetColumnWidth(1, 50)
771 self._bpListCtrl.SetColumnWidth(2, 450)
772 self._bpListCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
773 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.ListItemSelected, self._bpListCtrl)
774 self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.ListItemDeselected, self._bpListCtrl)
775
776 def OnLeftDoubleClick(event):
777 self.SyncBPLine(event)
778
779 wx.EVT_LEFT_DCLICK(self._bpListCtrl, OnLeftDoubleClick)
780
781 self.PopulateBPList()
782
783 p1.SetSizer(sizer)
784 sizer.Fit(p1)
785 p1.Layout()
786
787 def PopulateBPList(self):
788 list = self._bpListCtrl
789 list.DeleteAllItems()
790
791 bps = wx.GetApp().GetService(DebuggerService).GetMasterBreakpointDict()
792 index = 0
793 for fileName in bps.keys():
794 shortFile = os.path.basename(fileName)
795 lines = bps[fileName]
796 if lines:
797 for line in lines:
798 list.InsertStringItem(index, shortFile)
799 list.SetStringItem(index, 1, str(line))
800 list.SetStringItem(index, 2, fileName)
801
802 def OnListRightClick(self, event):
803 menu = wx.Menu()
804 item = wx.MenuItem(menu, self.clearBPID, "Clear Breakpoint")
805 menu.AppendItem(item)
806 item = wx.MenuItem(menu, self.syncLineID, "Goto Source Line")
807 menu.AppendItem(item)
808 self.PopupMenu(menu, event.GetPosition())
809 menu.Destroy()
810
811 def SyncBPLine(self, event):
812 if self.currentItem != -1:
813 list = self._bpListCtrl
814 fileName = list.GetItem(self.currentItem, 2).GetText()
815 lineNumber = list.GetItem(self.currentItem, 1).GetText()
816 self._ui.SynchCurrentLine( fileName, int(lineNumber) , noArrow=True)
817
818 def ClearBreakPoint(self, event):
819 if self.currentItem >= 0:
820 list = self._bpListCtrl
821 fileName = list.GetItem(self.currentItem, 2).GetText()
822 lineNumber = list.GetItem(self.currentItem, 1).GetText()
823 wx.GetApp().GetService(DebuggerService).OnToggleBreakpoint(None, line=int(lineNumber) -1, fileName=fileName )
824
825 def ListItemSelected(self, event):
826 self.currentItem = event.m_itemIndex
827
828 def ListItemDeselected(self, event):
829 self.currentItem = -1
830
831 class Watch:
832 CODE_ALL_FRAMES = 1
833 CODE_THIS_BLOCK = 2
834 CODE_THIS_LINE = 4
835 CODE_RUN_ONCE = 8
836
837 def __init__(self, name, command, show_code=CODE_ALL_FRAMES):
838 self._name = name
839 self._command = command
840 self._show_code = show_code
841
842 class WatchDialog(wx.Dialog):
843 WATCH_ALL_FRAMES = "Watch in all frames"
844 WATCH_THIS_FRAME = "Watch in this frame only"
845 WATCH_ONCE = "Watch once and delete"
846 def __init__(self, parent, title, chain):
847 wx.Dialog.__init__(self, parent, -1, title, style=wx.DEFAULT_DIALOG_STYLE)
848 self._chain = chain
849 self.label_2 = wx.StaticText(self, -1, "Watch Name:")
850 self._watchNameTextCtrl = wx.TextCtrl(self, -1, "")
851 self.label_3 = wx.StaticText(self, -1, "eval(", style=wx.ALIGN_RIGHT)
852 self._watchValueTextCtrl = wx.TextCtrl(self, -1, "")
853 self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)")
854 self.radio_box_1 = wx.RadioBox(self, -1, "Watch Information", choices=[WatchDialog.WATCH_ALL_FRAMES, WatchDialog.WATCH_THIS_FRAME, WatchDialog.WATCH_ONCE], majorDimension=0, style=wx.RA_SPECIFY_ROWS)
855
856 self._okButton = wx.Button(self, wx.ID_OK, "OK")
857 self._okButton.SetDefault()
858 self._okButton.SetHelpText(_("The OK button completes the dialog"))
859 def OnOkClick(event):
860 if self._watchNameTextCtrl.GetValue() == "":
861 wx.MessageBox(_("You must enter a name for the watch."), _("Add Watch"))
862 return
863 if self._watchValueTextCtrl.GetValue() == "":
864 wx.MessageBox(_("You must enter some code to run for the watch."), _("Add Watch"))
865 return
866 self.EndModal(wx.ID_OK)
867 self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton)
868
869 self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
870 self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog."))
871
872 self.__set_properties()
873 self.__do_layout()
874
875 def GetSettings(self):
876 return self._watchNameTextCtrl.GetValue(), self._watchValueTextCtrl.GetValue(), self.GetSendFrame(), self.GetRunOnce()
877
878 def GetSendFrame(self):
879 return (WatchDialog.WATCH_ALL_FRAMES != self.radio_box_1.GetStringSelection())
880
881 def GetRunOnce(self):
882 return (WatchDialog.WATCH_ONCE == self.radio_box_1.GetStringSelection())
883
884 def __set_properties(self):
885 self.SetTitle("Add a Watch")
886 #self.SetSize((400, 250))
887 self.radio_box_1.SetSelection(0)
888
889 def __do_layout(self):
890 sizer_1 = wx.BoxSizer(wx.VERTICAL)
891 grid_sizer_4 = wx.FlexGridSizer(1, 3, 5, 5)
892 grid_sizer_2 = wx.FlexGridSizer(1, 2, 5, 5)
893 grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
894 grid_sizer_2.Add(self._watchNameTextCtrl, 0, wx.EXPAND, 0)
895 grid_sizer_2.AddGrowableCol(1)
896 sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0)
897 grid_sizer_4.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
898 grid_sizer_4.Add(self._watchValueTextCtrl, 0, wx.EXPAND, 0)
899 grid_sizer_4.AddGrowableCol(1)
900 grid_sizer_4.Add(self.label_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0)
901 sizer_1.Add(grid_sizer_4, 0, wx.EXPAND, 0)
902 sizer_1.Add(self.radio_box_1, 0, wx.EXPAND, 0)
903
904 box = wx.BoxSizer(wx.HORIZONTAL)
905 box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
906 box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
907 sizer_1.Add(box, 1, wx.EXPAND, 0)
908 self.SetSizer(sizer_1)
909 self.Layout()
910
911 class FramesUI(wx.SplitterWindow):
912 def __init__(self, parent, id, ui):
913 wx.SplitterWindow.__init__(self, parent, id, style = wx.SP_3D)
914 self._ui = ui
915 self._p1 = p1 = wx.ScrolledWindow(self, -1)
916
917 sizer = wx.BoxSizer(wx.HORIZONTAL)
918 framesLabel = wx.StaticText(self, -1, "Stack Frame:")
919 sizer.Add(framesLabel, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.LEFT, border=2)
920
921 self._framesChoiceCtrl = wx.Choice(p1, -1, choices=[" "])
922 sizer.Add(self._framesChoiceCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
923 self._framesChoiceCtrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnListRightClick)
924 self.Bind(wx.EVT_CHOICE, self.ListItemSelected, self._framesChoiceCtrl)
925
926 sizer2 = wx.BoxSizer(wx.VERTICAL)
927 p1.SetSizer(sizer2)
928
929 self._treeCtrl = wx.gizmos.TreeListCtrl(p1, -1, style=wx.TR_DEFAULT_STYLE| wx.TR_FULL_ROW_HIGHLIGHT)
930 self._treeCtrl.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
931 sizer2.Add(sizer, 0, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
932 sizer2.Add(self._treeCtrl,1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
933 tree = self._treeCtrl
934 tree.AddColumn("Thing")
935 tree.AddColumn("Value")
936 tree.SetMainColumn(0) # the one with the tree in it...
937 tree.SetColumnWidth(0, 175)
938 tree.SetColumnWidth(1, 355)
939 self._root = tree.AddRoot("Frame")
940 tree.SetItemText(self._root, "", 1)
941 tree.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.IntrospectCallback)
942
943 self._p2 = p2 = wx.Window(self, -1)
944 sizer3 = wx.BoxSizer(wx.HORIZONTAL)
945 p2.SetSizer(sizer3)
946 p2.Bind(wx.EVT_SIZE, self.OnSize)
947 self._notebook = wx.Notebook(p2, -1, size=(20,20))
948 self._notebook.Hide()
949 sizer3.Add(self._notebook, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 1)
950 self.consoleTab = self.MakeConsoleTab(self._notebook, wx.NewId())
951 self.inspectConsoleTab = self.MakeInspectConsoleTab(self._notebook, wx.NewId())
952 self.breakPointsTab = self.MakeBreakPointsTab(self._notebook, wx.NewId())
953 self._notebook.AddPage(self.consoleTab, "Output")
954 self._notebook.AddPage(self.inspectConsoleTab, "Interact")
955 self._notebook.AddPage(self.breakPointsTab, "Break Points")
956
957 self.SetMinimumPaneSize(20)
958 self.SplitVertically(p1, p2, 550)
959 self.currentItem = None
960 self._notebook.Show(True)
961
962 def PopulateBPList(self):
963 self.breakPointsTab.PopulateBPList()
964
965 def OnSize(self, event):
966 self._notebook.SetSize(self._p2.GetSize())
967
968 def MakeConsoleTab(self, parent, id):
969 panel = wx.Panel(parent, id)
970 sizer = wx.BoxSizer(wx.HORIZONTAL)
971 self._textCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
972 sizer.Add(self._textCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2)
973 self._textCtrl.SetViewLineNumbers(False)
974 self._textCtrl.SetReadOnly(True)
975 if wx.Platform == '__WXMSW__':
976 font = "Courier New"
977 else:
978 font = "Courier"
979 self._textCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
980 self._textCtrl.SetFontColor(wx.BLACK)
981 self._textCtrl.StyleClearAll()
982 panel.SetSizer(sizer)
983 #sizer.Fit(panel)
984
985 return panel
986
987 def ReplaceLastLine(self, command):
988 line = self._interCtrl.GetLineCount() - 1
989 self._interCtrl.GotoLine(line)
990 start = self._interCtrl.GetCurrentPos()
991 self._interCtrl.SetTargetStart(start)
992 end = self._interCtrl.GetLineEndPosition(line)
993 self._interCtrl.SetTargetEnd(end)
994 self._interCtrl.ReplaceTarget(">>> " + command)
995 self._interCtrl.GotoLine(line)
996 self._interCtrl.SetSelectionStart(self._interCtrl.GetLineEndPosition(line))
997
998 def ExecuteCommand(self, command):
999 if not len(self.command_list) or not command == self.command_list[len(self.command_list) -1]:
1000 self.command_list.append(command)
1001 self.command_index = len(self.command_list) - 1
1002 retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command)
1003 self._interCtrl.AddText("\n" + str(retval))
1004 self._interCtrl.ScrollToLine(self._interCtrl.GetLineCount())
1005 # Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items.
1006 self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection())
1007
1008 def MakeInspectConsoleTab(self, parent, id):
1009 self.command_list = []
1010 self.command_index = 0
1011
1012 def OnKeyPressed(event):
1013 key = event.KeyCode()
1014 if key == wx.WXK_DELETE or key == wx.WXK_BACK:
1015 if self._interCtrl.GetLine(self._interCtrl.GetCurrentLine()) == ">>> ":
1016 return
1017 elif key == wx.WXK_RETURN:
1018 command = self._interCtrl.GetLine(self._interCtrl.GetCurrentLine())[4:]
1019 self.ExecuteCommand(command)
1020 self._interCtrl.AddText("\n>>> ")
1021 return
1022 elif key == wx.WXK_UP:
1023 if not len(self.command_list):
1024 return
1025 self.ReplaceLastLine(self.command_list[self.command_index])
1026 if self.command_index == 0:
1027 self.command_index = len(self.command_list) - 1
1028 else:
1029 self.command_index = self.command_index - 1
1030 return
1031 elif key == wx.WXK_DOWN:
1032 if not len(self.command_list):
1033 return
1034 if self.command_index < len(self.command_list) - 1:
1035 self.command_index = self.command_index + 1
1036 else:
1037 self.command_index = 0
1038 self.ReplaceLastLine(self.command_list[self.command_index])
1039 return
1040 event.Skip()
1041
1042 try:
1043 panel = wx.Panel(parent, id)
1044 sizer = wx.BoxSizer(wx.HORIZONTAL)
1045 self._interCtrl = STCTextEditor.TextCtrl(panel, wx.NewId())
1046 sizer.Add(self._interCtrl, 1, wx.ALIGN_LEFT|wx.ALL|wx.EXPAND, 2)
1047 self._interCtrl.SetViewLineNumbers(False)
1048 if wx.Platform == '__WXMSW__':
1049 font = "Courier New"
1050 else:
1051 font = "Courier"
1052 self._interCtrl.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = font))
1053 self._interCtrl.SetFontColor(wx.BLACK)
1054 self._interCtrl.StyleClearAll()
1055 wx.EVT_KEY_DOWN(self._interCtrl, OnKeyPressed)
1056 self._interCtrl.AddText(">>> ")
1057 panel.SetSizer(sizer)
1058 except:
1059 tp, val, tb = sys.exc_info()
1060 traceback.print_exception(tp, val, tb)
1061
1062 return panel
1063
1064 def MakeBreakPointsTab(self, parent, id):
1065 panel = BreakpointsUI(parent, id, self._ui)
1066 return panel
1067
1068 def OnRightClick(self, event):
1069 #Refactor this...
1070 self._introspectItem = event.GetItem()
1071 self._parentChain = self.GetItemChain(event.GetItem())
1072 watchOnly = len(self._parentChain) < 1
1073 if not _WATCHES_ON and watchOnly:
1074 return
1075 menu = wx.Menu()
1076 if _WATCHES_ON:
1077 if not hasattr(self, "watchID"):
1078 self.watchID = wx.NewId()
1079 self.Bind(wx.EVT_MENU, self.OnWatch, id=self.watchID)
1080 item = wx.MenuItem(menu, self.watchID, "Create a Watch")
1081 menu.AppendItem(item)
1082 menu.AppendSeparator()
1083 if not watchOnly:
1084 if not hasattr(self, "viewID"):
1085 self.viewID = wx.NewId()
1086 self.Bind(wx.EVT_MENU, self.OnView, id=self.viewID)
1087 item = wx.MenuItem(menu, self.viewID, "View in Dialog")
1088 menu.AppendItem(item)
1089 if not hasattr(self, "toInteractID"):
1090 self.toInteractID = wx.NewId()
1091 self.Bind(wx.EVT_MENU, self.OnSendToInteract, id=self.toInteractID)
1092 item = wx.MenuItem(menu, self.toInteractID, "Send to Interact")
1093 menu.AppendItem(item)
1094
1095 offset = wx.Point(x=0, y=20)
1096 menuSpot = event.GetPoint() + offset
1097 self._treeCtrl.PopupMenu(menu, menuSpot)
1098 menu.Destroy()
1099 self._parentChain = None
1100 self._introspectItem = None
1101
1102 def GetItemChain(self, item):
1103 parentChain = []
1104 if item:
1105 if _VERBOSE: print 'Exploding: %s' % self._treeCtrl.GetItemText(item, 0)
1106 while item != self._root:
1107 text = self._treeCtrl.GetItemText(item, 0)
1108 if _VERBOSE: print "Appending ", text
1109 parentChain.append(text)
1110 item = self._treeCtrl.GetItemParent(item)
1111 parentChain.reverse()
1112 return parentChain
1113
1114 def OnView(self, event):
1115 title = self._treeCtrl.GetItemText(self._introspectItem,0)
1116 value = self._treeCtrl.GetItemText(self._introspectItem,1)
1117 dlg = wx.lib.dialogs.ScrolledMessageDialog(self, value, title, style=wx.DD_DEFAULT_STYLE | wx.RESIZE_BORDER)
1118 dlg.Show()
1119
1120 def OnSendToInteract(self, event):
1121 value = ""
1122 prevItem = ""
1123 for item in self._parentChain:
1124
1125 if item.find(prevItem + '[') != -1:
1126 value += item[item.find('['):]
1127 continue
1128 if value != "":
1129 value = value + '.'
1130 if item == 'globals':
1131 item = 'globals()'
1132 if item != 'locals':
1133 value += item
1134 prevItem = item
1135 print value
1136 self.ReplaceLastLine(value)
1137 self.ExecuteCommand(value)
1138
1139 def OnWatch(self, event):
1140 try:
1141 if hasattr(self, '_parentChain'):
1142 wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", self._parentChain)
1143 else:
1144 wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", None)
1145 wd.CenterOnParent()
1146 if wd.ShowModal() == wx.ID_OK:
1147 name, text, send_frame, run_once = wd.GetSettings()
1148 if send_frame:
1149 frameNode = self._stack[int(self.currentItem)]
1150 message = frameNode.getAttribute("message")
1151 else:
1152 message = ""
1153 binType = self._ui._callback._debuggerServer.add_watch(name, text, message, run_once)
1154 xmldoc = bz2.decompress(binType.data)
1155 domDoc = parseString(xmldoc)
1156 nodeList = domDoc.getElementsByTagName('watch')
1157 if len(nodeList) == 1:
1158 watchValue = nodeList.item(0).getAttribute("message")
1159 wd.Destroy()
1160 except:
1161 tp, val, tb = sys.exc_info()
1162 traceback.print_exception(tp, val, tb)
1163
1164 def OnIntrospect(self, event):
1165 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
1166
1167 try:
1168 list = self._framesChoiceCtrl
1169 frameNode = self._stack[int(self.currentItem)]
1170 message = frameNode.getAttribute("message")
1171 binType = self._ui._callback._debuggerServer.attempt_introspection(message, self._parentChain)
1172 xmldoc = bz2.decompress(binType.data)
1173 domDoc = parseString(xmldoc)
1174 #wx.MessageBox(xmldoc, "result of introspection")
1175 nodeList = domDoc.getElementsByTagName('replacement')
1176 replacementNode = nodeList.item(0)
1177 if len(replacementNode.childNodes):
1178 thingToWalk = replacementNode.childNodes.item(0)
1179 tree = self._treeCtrl
1180 parent = tree.GetItemParent(self._introspectItem)
1181 treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem)
1182 if thingToWalk.getAttribute('name').find('[') == -1:
1183 self._treeCtrl.SortChildren(treeNode)
1184 self._treeCtrl.Expand(treeNode)
1185 tree.Delete(self._introspectItem)
1186 except:
1187 tp,val,tb = sys.exc_info()
1188 traceback.print_exception(tp, val, tb)
1189
1190 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
1191
1192 def ClearWhileRunning(self):
1193 list = self._framesChoiceCtrl
1194 list.Clear()
1195 list.Enable(False)
1196 tree = self._treeCtrl
1197 root = self._root
1198 tree.DeleteChildren(root)
1199 self._interCtrl.Enable(False)
1200
1201 #tree.Hide()
1202
1203 def OnListRightClick(self, event):
1204 if not hasattr(self, "syncFrameID"):
1205 self.syncFrameID = wx.NewId()
1206 self.Bind(wx.EVT_MENU, self.OnSyncFrame, id=self.syncFrameID)
1207 menu = wx.Menu()
1208 item = wx.MenuItem(menu, self.syncFrameID, "Goto Source Line")
1209 menu.AppendItem(item)
1210 self.PopupMenu(menu, event.GetPosition())
1211 menu.Destroy()
1212
1213 def OnSyncFrame(self, event):
1214 list = self._framesChoiceCtrl
1215 frameNode = self._stack[int(self.currentItem)]
1216 file = frameNode.getAttribute("file")
1217 line = frameNode.getAttribute("line")
1218 self._ui.SynchCurrentLine( file, int(line) )
1219
1220 def LoadFramesListXML(self, framesXML):
1221 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
1222 self._interCtrl.Enable(True)
1223
1224 try:
1225 domDoc = parseString(framesXML)
1226 list = self._framesChoiceCtrl
1227 list.Clear()
1228 self._stack = []
1229 nodeList = domDoc.getElementsByTagName('frame')
1230 frame_count = -1
1231 for index in range(0, nodeList.length):
1232 frameNode = nodeList.item(index)
1233 message = frameNode.getAttribute("message")
1234 list.Append(message)
1235 self._stack.append(frameNode)
1236 frame_count += 1
1237 index = len(self._stack) - 1
1238 list.SetSelection(index)
1239
1240 node = self._stack[index]
1241 self.currentItem = index
1242 self.PopulateTreeFromFrameNode(node)
1243 self.OnSyncFrame(None)
1244
1245 self._p1.FitInside()
1246 frameNode = nodeList.item(index)
1247 file = frameNode.getAttribute("file")
1248 line = frameNode.getAttribute("line")
1249 self._ui.SynchCurrentLine( file, int(line) )
1250 except:
1251 tp,val,tb=sys.exc_info()
1252 traceback.print_exception(tp, val, tb)
1253
1254 wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
1255
1256
1257 def ListItemSelected(self, event):
1258 self.PopulateTreeFromFrameMessage(event.GetString())
1259 self.OnSyncFrame(None)
1260
1261 def PopulateTreeFromFrameMessage(self, message):
1262 index = 0
1263 for node in self._stack:
1264 if node.getAttribute("message") == message:
1265 binType = self._ui._callback._debuggerServer.request_frame_document(message)
1266 xmldoc = bz2.decompress(binType.data)
1267 domDoc = parseString(xmldoc)
1268 nodeList = domDoc.getElementsByTagName('frame')
1269 self.currentItem = index
1270 if len(nodeList):
1271 self.PopulateTreeFromFrameNode(nodeList[0])
1272 return
1273 index = index + 1
1274
1275 def PopulateTreeFromFrameNode(self, frameNode):
1276 list = self._framesChoiceCtrl
1277 list.Enable(True)
1278 tree = self._treeCtrl
1279 #tree.Show(True)
1280 root = self._root
1281 tree.DeleteChildren(root)
1282 children = frameNode.childNodes
1283 firstChild = None
1284 for index in range(0, children.length):
1285 subNode = children.item(index)
1286 treeNode = self.AppendSubTreeFromNode(subNode, subNode.getAttribute('name'), root)
1287 if not firstChild:
1288 firstChild = treeNode
1289 tree.Expand(root)
1290 if firstChild:
1291 tree.Expand(firstChild)
1292 self._p2.FitInside()
1293
1294 def IntrospectCallback(self, event):
1295 tree = self._treeCtrl
1296 item = event.GetItem()
1297 if _VERBOSE:
1298 print "In introspectCallback item is %s, pydata is %s" % (event.GetItem(), tree.GetPyData(item))
1299 if tree.GetPyData(item) != "Introspect":
1300 event.Skip()
1301 return
1302 self._introspectItem = item
1303 self._parentChain = self.GetItemChain(item)
1304 self.OnIntrospect(event)
1305 event.Skip()
1306
1307 def AppendSubTreeFromNode(self, node, name, parent, insertBefore=None):
1308 tree = self._treeCtrl
1309 if insertBefore != None:
1310 treeNode = tree.InsertItem(parent, insertBefore, name)
1311 else:
1312 treeNode = tree.AppendItem(parent, name)
1313 children = node.childNodes
1314 intro = node.getAttribute('intro')
1315
1316 if intro == "True":
1317 tree.SetItemHasChildren(treeNode, True)
1318 tree.SetPyData(treeNode, "Introspect")
1319 if node.getAttribute("value"):
1320 tree.SetItemText(treeNode, self.StripOuterSingleQuotes(node.getAttribute("value")), 1)
1321 for index in range(0, children.length):
1322 subNode = children.item(index)
1323 if self.HasChildren(subNode):
1324 self.AppendSubTreeFromNode(subNode, subNode.getAttribute("name"), treeNode)
1325 else:
1326 name = subNode.getAttribute("name")
1327 value = self.StripOuterSingleQuotes(subNode.getAttribute("value"))
1328 n = tree.AppendItem(treeNode, name)
1329 tree.SetItemText(n, value, 1)
1330 intro = subNode.getAttribute('intro')
1331 if intro == "True":
1332 tree.SetItemHasChildren(n, True)
1333 tree.SetPyData(n, "Introspect")
1334 if name.find('[') == -1:
1335 self._treeCtrl.SortChildren(treeNode)
1336 return treeNode
1337
1338 def StripOuterSingleQuotes(self, string):
1339 if string.startswith("'") and string.endswith("'"):
1340 retval = string[1:-1]
1341 elif string.startswith("\"") and string.endswith("\""):
1342 retval = string[1:-1]
1343 else:
1344 retval = string
1345 if retval.startswith("u'") and retval.endswith("'"):
1346 retval = retval[1:]
1347 return retval
1348
1349 def HasChildren(self, node):
1350 try:
1351 return node.childNodes.length > 0
1352 except:
1353 tp,val,tb=sys.exc_info()
1354 return False
1355
1356 def AppendText(self, text):
1357 self._textCtrl.SetReadOnly(False)
1358 self._textCtrl.AddText(text)
1359 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
1360 self._textCtrl.SetReadOnly(True)
1361
1362 def AppendErrorText(self, text):
1363 self._textCtrl.SetReadOnly(False)
1364 self._textCtrl.SetFontColor(wx.RED)
1365 self._textCtrl.StyleClearAll()
1366 self._textCtrl.AddText(text)
1367 self._textCtrl.ScrollToLine(self._textCtrl.GetLineCount())
1368 self._textCtrl.SetFontColor(wx.BLACK)
1369 self._textCtrl.StyleClearAll()
1370 self._textCtrl.SetReadOnly(True)
1371
1372 def ClearOutput(self, event):
1373 self._textCtrl.SetReadOnly(False)
1374 self._textCtrl.ClearAll()
1375 self._textCtrl.SetReadOnly(True)
1376
1377 def SwitchToOutputTab(self):
1378 self._notebook.SetSelection(0)
1379
1380 class DebuggerView(Service.ServiceView):
1381
1382 #----------------------------------------------------------------------------
1383 # Overridden methods
1384 #----------------------------------------------------------------------------
1385
1386 def __init__(self, service):
1387 Service.ServiceView.__init__(self, service)
1388
1389 def _CreateControl(self, parent, id):
1390 return None
1391
1392 #------------------------------------------------------------------------------
1393 # Event handling
1394 #-----------------------------------------------------------------------------
1395
1396 def OnToolClicked(self, event):
1397 self.GetFrame().ProcessEvent(event)
1398
1399 def ProcessUpdateUIEvent(self, event):
1400 return False
1401
1402 def ProcessEvent(self, event):
1403 return False
1404
1405 #------------------------------------------------------------------------------
1406 # Class methods
1407 #-----------------------------------------------------------------------------
1408
1409 class Interaction:
1410 def __init__(self, message, framesXML, info=None, quit=False):
1411 self._framesXML = framesXML
1412 self._message = message
1413 self._info = info
1414 self._quit = quit
1415
1416 def getFramesXML(self):
1417 return self._framesXML
1418
1419 def getMessage(self):
1420 return self._message
1421
1422 def getInfo(self):
1423 return self._info
1424
1425 def getQuit(self):
1426 return self._quit
1427
1428 class AGXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
1429 def __init__(self, address, logRequests=0):
1430 SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, address, logRequests=logRequests)
1431
1432 class RequestHandlerThread(threading.Thread):
1433 def __init__(self, queue, address):
1434 threading.Thread.__init__(self)
1435 self._keepGoing = True
1436 self._queue = queue
1437 self._address = address
1438 self._server = AGXMLRPCServer(self._address,logRequests=0)
1439 self._server.register_function(self.interaction)
1440 self._server.register_function(self.quit)
1441 self._server.register_function(self.dummyOperation)
1442 if _VERBOSE: print "RequestHandlerThread on fileno %s" % str(self._server.fileno())
1443
1444 def run(self):
1445 while self._keepGoing:
1446 try:
1447 self._server.handle_request()
1448 except:
1449 tp, val, tb = sys.exc_info()
1450 traceback.print_exception(tp, val, tb)
1451 self._keepGoing = False
1452 if _VERBOSE: print "Exiting Request Handler Thread."
1453
1454 def interaction(self, message, frameXML, info):
1455 if _VERBOSE: print "In RequestHandlerThread.interaction -- adding to queue"
1456 interaction = Interaction(message, frameXML, info)
1457 self._queue.put(interaction)
1458 return ""
1459
1460 def quit(self):
1461 interaction = Interaction(None, None, info=None, quit=True)
1462 self._queue.put(interaction)
1463 return ""
1464
1465 def dummyOperation(self):
1466 return ""
1467
1468 def AskToStop(self):
1469 self._keepGoing = False
1470 if type(self._server) is not types.NoneType:
1471 try:
1472 # This is a really ugly way to make sure this thread isn't blocked in
1473 # handle_request.
1474 url = 'http://' + self._address[0] + ':' + str(self._address[1]) + '/'
1475 tempServer = xmlrpclib.ServerProxy(url, allow_none=1)
1476 tempServer.dummyOperation()
1477 except:
1478 tp, val, tb = sys.exc_info()
1479 traceback.print_exception(tp, val, tb)
1480 self._server.server_close()
1481
1482
1483 class RequestBreakThread(threading.Thread):
1484 def __init__(self, server, interrupt=False, pushBreakpoints=False, breakDict=None, kill=False):
1485 threading.Thread.__init__(self)
1486 self._server = server
1487
1488 self._interrupt = interrupt
1489 self._pushBreakpoints = pushBreakpoints
1490 self._breakDict = breakDict
1491 self._kill = kill
1492
1493 def run(self):
1494 try:
1495 if _VERBOSE: print "RequestBreakThread, before call"
1496 if self._interrupt:
1497 self._server.break_requested()
1498 if self._pushBreakpoints:
1499 self._server.update_breakpoints(xmlrpclib.Binary(pickle.dumps(self._breakDict)))
1500 if self._kill:
1501 try:
1502 self._server.die()
1503 except:
1504 pass
1505 if _VERBOSE: print "RequestBreakThread, after call"
1506 except:
1507 tp,val,tb = sys.exc_info()
1508 traceback.print_exception(tp, val, tb)
1509
1510 class DebuggerOperationThread(threading.Thread):
1511 def __init__(self, function):
1512 threading.Thread.__init__(self)
1513 self._function = function
1514
1515 def run(self):
1516 if _VERBOSE: print "In DOT, before call"
1517 try:
1518 self._function()
1519 except:
1520 tp,val,tb = sys.exc_info()
1521 traceback.print_exception(tp, val, tb)
1522 if _VERBOSE: print "In DOT, after call"
1523
1524 class DebuggerCallback:
1525
1526 def __init__(self, host, port, debugger_url, break_url, debuggerUI):
1527 if _VERBOSE: print "+++++++ Creating server on port, ", str(port)
1528
1529 self._queue = Queue.Queue(50)
1530 self._host = host
1531 self._port = int(port)
1532 threading._VERBOSE = _VERBOSE
1533 self._serverHandlerThread = RequestHandlerThread(self._queue, (self._host, self._port))
1534
1535 self._debugger_url = debugger_url
1536 self._debuggerServer = None
1537 self._waiting = False
1538 self._service = wx.GetApp().GetService(DebuggerService)
1539 self._debuggerUI = debuggerUI
1540 self._break_url = break_url
1541 self._breakServer = None
1542 self._firstInteraction = True
1543 self._pendingBreak = False
1544
1545 def start(self):
1546 self._serverHandlerThread.start()
1547
1548 def ShutdownServer(self):
1549 #rbt = RequestBreakThread(self._breakServer, kill=True)
1550 #rbt.start()
1551 self.setWaiting(False)
1552 if self._serverHandlerThread:
1553 self._serverHandlerThread.AskToStop()
1554 self._serverHandlerThread = None
1555
1556 def BreakExecution(self):
1557 rbt = RequestBreakThread(self._breakServer, interrupt=True)
1558 rbt.start()
1559
1560 def SingleStep(self):
1561 self._debuggerUI.DisableWhileDebuggerRunning()
1562 self._debuggerServer.set_step() # Figure out where to set allowNone
1563 self.waitForRPC()
1564
1565 def Next(self):
1566 self._debuggerUI.DisableWhileDebuggerRunning()
1567 self._debuggerServer.set_next()
1568 self.waitForRPC()
1569
1570 def Continue(self):
1571 self._debuggerUI.DisableWhileDebuggerRunning()
1572 self._debuggerServer.set_continue()
1573 self.waitForRPC()
1574
1575 def Return(self):
1576 self._debuggerUI.DisableWhileDebuggerRunning()
1577 self._debuggerServer.set_return()
1578 self.waitForRPC()
1579
1580 def setWaiting(self, value):
1581 self._waiting = value
1582
1583 def getWaiting(self):
1584 return self._waiting
1585
1586 def readQueue(self):
1587 if self._queue.qsize():
1588 try:
1589 item = self._queue.get_nowait()
1590 if item.getQuit():
1591 self.interaction(None, None, None, True)
1592 else:
1593 data = bz2.decompress(item.getFramesXML().data)
1594 self.interaction(item.getMessage().data, data, item.getInfo(), False)
1595 except Queue.Empty:
1596 pass
1597
1598 def pushBreakpoints(self):
1599 rbt = RequestBreakThread(self._breakServer, pushBreakpoints=True, breakDict=self._service.GetMasterBreakpointDict())
1600 rbt.start()
1601
1602
1603 def waitForRPC(self):
1604 self.setWaiting(True)
1605 while self.getWaiting():
1606 try:
1607 self.readQueue()
1608 import time
1609 time.sleep(0.02)
1610 except:
1611 tp, val, tb = sys.exc_info()
1612 traceback.print_exception(tp, val, tb)
1613 wx.GetApp().Yield(True)
1614 if _VERBOSE: print "Exiting waitForRPC."
1615
1616 def interaction(self, message, frameXML, info, quit):
1617
1618 #This method should be hit as the debugger starts.
1619 if self._firstInteraction:
1620 self._firstInteraction = False
1621 self._debuggerServer = xmlrpclib.ServerProxy(self._debugger_url, allow_none=1)
1622 self._breakServer = xmlrpclib.ServerProxy(self._break_url, allow_none=1)
1623 self.pushBreakpoints()
1624 self.setWaiting(False)
1625 if _VERBOSE: print "+"*40
1626 if(quit):
1627 self._debuggerUI.StopExecution(None)
1628 return ""
1629 if(info != ""):
1630 if _VERBOSE: print "Hit interaction with exception"
1631 #self._debuggerUI.StopExecution(None)
1632 #self._debuggerUI.SetStatusText("Got exception: " + str(info))
1633 self._debuggerUI.SwitchToOutputTab()
1634 else:
1635 if _VERBOSE: print "Hit interaction no exception"
1636 self._debuggerUI.SetStatusText(message)
1637 self._debuggerUI.LoadFramesListXML(frameXML)
1638 self._debuggerUI.EnableWhileDebuggerStopped()
1639 if _VERBOSE: print "+"*40
1640
1641 class DebuggerService(Service.Service):
1642
1643 #----------------------------------------------------------------------------
1644 # Constants
1645 #----------------------------------------------------------------------------
1646 TOGGLE_BREAKPOINT_ID = wx.NewId()
1647 CLEAR_ALL_BREAKPOINTS = wx.NewId()
1648 RUN_ID = wx.NewId()
1649 DEBUG_ID = wx.NewId()
1650 DEBUG_WEBSERVER_ID = wx.NewId()
1651 RUN_WEBSERVER_ID = wx.NewId()
1652
1653 def ComparePaths(first, second):
1654 one = DebuggerService.ExpandPath(first)
1655 two = DebuggerService.ExpandPath(second)
1656 if _WINDOWS:
1657 return one.lower() == two.lower()
1658 else:
1659 return one == two
1660 ComparePaths = staticmethod(ComparePaths)
1661
1662 # Make sure we're using an expanded path on windows.
1663 def ExpandPath(path):
1664 if _WINDOWS:
1665 try:
1666 return win32api.GetLongPathName(path)
1667 except:
1668 if _VERBOSE:
1669 print "Cannot get long path for %s" % path
1670
1671 return path
1672
1673 ExpandPath = staticmethod(ExpandPath)
1674
1675 #----------------------------------------------------------------------------
1676 # Overridden methods
1677 #----------------------------------------------------------------------------
1678
1679 def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT):
1680 Service.Service.__init__(self, serviceName, embeddedWindowLocation)
1681 self.BREAKPOINT_DICT_STRING = "MasterBreakpointDict"
1682 config = wx.ConfigBase_Get()
1683 pickledbps = config.Read(self.BREAKPOINT_DICT_STRING)
1684 if pickledbps:
1685 try:
1686 self._masterBPDict = pickle.loads(pickledbps.encode('ascii'))
1687 except:
1688 tp, val, tb = sys.exc_info()
1689 traceback.print_exception(tp,val,tb)
1690 self._masterBPDict = {}
1691 else:
1692 self._masterBPDict = {}
1693
1694 def OnCloseFrame(self, event):
1695 # IS THIS THE RIGHT PLACE?
1696 try:
1697 config = wx.ConfigBase_Get()
1698 config.Write(self.BREAKPOINT_DICT_STRING, pickle.dumps(self._masterBPDict))
1699 except:
1700 tp,val,tb = sys.exc_info()
1701 traceback.print_exception(tp, val, tb)
1702 return True
1703
1704 def _CreateView(self):
1705 return DebuggerView(self)
1706
1707
1708 #----------------------------------------------------------------------------
1709 # Service specific methods
1710 #----------------------------------------------------------------------------
1711
1712 def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
1713 #Service.Service.InstallControls(self, frame, menuBar, toolBar, statusBar, document)
1714
1715 config = wx.ConfigBase_Get()
1716
1717 debuggerMenu = wx.Menu()
1718 if not menuBar.FindItemById(DebuggerService.CLEAR_ALL_BREAKPOINTS):
1719
1720 debuggerMenu.Append(DebuggerService.RUN_ID, _("&Run...\tCtrl+R"), _("Runs a file"))
1721 wx.EVT_MENU(frame, DebuggerService.RUN_ID, frame.ProcessEvent)
1722 wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_ID, frame.ProcessUpdateUIEvent)
1723
1724 debuggerMenu.Append(DebuggerService.DEBUG_ID, _("&Debug...\tCtrl+D"), _("Debugs a file"))
1725 wx.EVT_MENU(frame, DebuggerService.DEBUG_ID, frame.ProcessEvent)
1726 wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_ID, frame.ProcessUpdateUIEvent)
1727
1728 if not ACTIVEGRID_BASE_IDE:
1729 debuggerMenu.AppendSeparator()
1730 debuggerMenu.Append(DebuggerService.DEBUG_WEBSERVER_ID, _("Debug Internal Web Server"), _("Debugs the internal webservier"))
1731 wx.EVT_MENU(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessEvent)
1732 wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessUpdateUIEvent)
1733 debuggerMenu.Append(DebuggerService.RUN_WEBSERVER_ID, _("Restart Internal Web Server"), _("Restarts the internal webservier"))
1734 wx.EVT_MENU(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessEvent)
1735 wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessUpdateUIEvent)
1736
1737 debuggerMenu.AppendSeparator()
1738
1739 debuggerMenu.Append(DebuggerService.TOGGLE_BREAKPOINT_ID, _("&Toggle Breakpoint...\tCtrl+B"), _("Toggle a breakpoint"))
1740 wx.EVT_MENU(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessEvent)
1741 wx.EVT_UPDATE_UI(frame, DebuggerService.TOGGLE_BREAKPOINT_ID, self.ProcessUpdateUIEvent)
1742
1743 debuggerMenu.Append(DebuggerService.CLEAR_ALL_BREAKPOINTS, _("&Clear All Breakpoints"), _("Clear All Breakpoints"))
1744 wx.EVT_MENU(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessEvent)
1745 wx.EVT_UPDATE_UI(frame, DebuggerService.CLEAR_ALL_BREAKPOINTS, self.ProcessUpdateUIEvent)
1746
1747
1748 viewMenuIndex = menuBar.FindMenu(_("&Project"))
1749 menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run"))
1750
1751 toolBar.AddSeparator()
1752 toolBar.AddTool(DebuggerService.RUN_ID, getRunningManBitmap(), shortHelpString = _("Run"), longHelpString = _("Run"))
1753 toolBar.AddTool(DebuggerService.DEBUG_ID, getDebuggingManBitmap(), shortHelpString = _("Debug"), longHelpString = _("Debug"))
1754 toolBar.Realize()
1755
1756 return True
1757
1758
1759
1760 #----------------------------------------------------------------------------
1761 # Event Processing Methods
1762 #----------------------------------------------------------------------------
1763
1764 def ProcessEventBeforeWindows(self, event):
1765 return False
1766
1767
1768 def ProcessEvent(self, event):
1769 if Service.Service.ProcessEvent(self, event):
1770 return True
1771
1772 an_id = event.GetId()
1773 if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID:
1774 self.OnToggleBreakpoint(event)
1775 return True
1776 elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS:
1777 self.ClearAllBreakpoints()
1778 return True
1779 elif an_id == DebuggerService.RUN_ID:
1780 self.OnRunProject(event)
1781 return True
1782 elif an_id == DebuggerService.DEBUG_ID:
1783 self.OnDebugProject(event)
1784 return True
1785 elif an_id == DebuggerService.DEBUG_WEBSERVER_ID:
1786 self.OnDebugWebServer(event)
1787 return True
1788 elif an_id == DebuggerService.RUN_WEBSERVER_ID:
1789 self.OnRunWebServer(event)
1790 return True
1791 return False
1792
1793 def ProcessUpdateUIEvent(self, event):
1794 if Service.Service.ProcessUpdateUIEvent(self, event):
1795 return True
1796
1797 an_id = event.GetId()
1798 if an_id == DebuggerService.TOGGLE_BREAKPOINT_ID:
1799 currentView = self.GetDocumentManager().GetCurrentView()
1800 event.Enable(isinstance(currentView, PythonEditor.PythonView))
1801 return True
1802 elif an_id == DebuggerService.CLEAR_ALL_BREAKPOINTS:
1803 event.Enable(self.HasBreakpointsSet())
1804 return True
1805 elif (an_id == DebuggerService.RUN_ID
1806 or an_id == DebuggerService.DEBUG_ID):
1807 event.Enable(self.HasAnyFiles())
1808 return True
1809 else:
1810 return False
1811
1812 #----------------------------------------------------------------------------
1813 # Class Methods
1814 #----------------------------------------------------------------------------
1815
1816 def OnDebugProject(self, event):
1817 if _WINDOWS and not _PYWIN32_INSTALLED:
1818 wx.MessageBox(_("Python for Windows extensions (pywin32) is required to debug on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32."))
1819 return
1820 if not Executor.GetPythonExecutablePath():
1821 return
1822 if DebugCommandUI.DebuggerRunning():
1823 wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
1824 return
1825 self.ShowWindow(True)
1826 projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
1827 try:
1828 dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug Python File', projectService, None, pythonOnly=True, okButtonName="Debug", debugging=True)
1829 except:
1830 return
1831 dlg.CenterOnParent()
1832 if dlg.ShowModal() == wx.ID_OK:
1833 projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings()
1834 dlg.Destroy()
1835 else:
1836 dlg.Destroy()
1837 return
1838 self.PromptToSaveFiles()
1839
1840 shortFile = os.path.basename(fileToDebug)
1841 fileToDebug = DebuggerService.ExpandPath(fileToDebug)
1842 try:
1843 page = DebugCommandUI(Service.ServiceView.bottomTab, -1, str(fileToDebug), self)
1844 count = Service.ServiceView.bottomTab.GetPageCount()
1845 Service.ServiceView.bottomTab.AddPage(page, _("Debugging: ") + shortFile)
1846 Service.ServiceView.bottomTab.SetSelection(count)
1847 page.Execute(initialArgs, startIn, environment)
1848 except:
1849 pass
1850
1851 def OnDebugWebServer(self, event):
1852 if _WINDOWS and not _PYWIN32_INSTALLED:
1853 wx.MessageBox(_("Python for Windows extensions (pywin32) is required to debug on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32."))
1854 return
1855 if not Executor.GetPythonExecutablePath():
1856 return
1857 if DebugCommandUI.DebuggerRunning():
1858 wx.MessageBox(_("A debugger is already running. Please shut down the other debugger first."), _("Debugger Running"))
1859 return
1860 import WebServerService
1861 wsService = wx.GetApp().GetService(WebServerService.WebServerService)
1862 fileName, args = wsService.StopAndPrepareToDebug()
1863 try:
1864 page = DebugCommandUI(Service.ServiceView.bottomTab, -1, fileName, self)
1865 count = Service.ServiceView.bottomTab.GetPageCount()
1866 Service.ServiceView.bottomTab.AddPage(page, _("Debugging: Internal WebServer"))
1867 Service.ServiceView.bottomTab.SetSelection(count)
1868 page.Execute(args, startIn=os.getcwd(), environment=os.environ)
1869 except:
1870 pass
1871
1872 def OnRunWebServer(self, event):
1873 if not Executor.GetPythonExecutablePath():
1874 return
1875 import WebServerService
1876 wsService = wx.GetApp().GetService(WebServerService.WebServerService)
1877 wsService.ShutDownAndRestart()
1878
1879 def HasAnyFiles(self):
1880 docs = wx.GetApp().GetDocumentManager().GetDocuments()
1881 return len(docs) > 0
1882
1883 def PromptToSaveFiles(self, running=True):
1884 filesModified = False
1885 docs = wx.GetApp().GetDocumentManager().GetDocuments()
1886 for doc in docs:
1887 if doc.IsModified():
1888 filesModified = True
1889 break
1890 if filesModified:
1891 frame = self.GetView().GetFrame()
1892 if running:
1893 yesNoMsg = wx.MessageDialog(frame,
1894 _("Files have been modified.\nWould you like to save all files before running?"),
1895 _("Run"),
1896 wx.YES_NO|wx.ICON_QUESTION
1897 )
1898 else:
1899 yesNoMsg = wx.MessageDialog(frame,
1900 _("Files have been modified.\nWould you like to save all files before debugging?"),
1901 _("Debug"),
1902 wx.YES_NO|wx.ICON_QUESTION
1903 )
1904 yesNoMsg.CenterOnParent()
1905 if yesNoMsg.ShowModal() == wx.ID_YES:
1906 docs = wx.GetApp().GetDocumentManager().GetDocuments()
1907 for doc in docs:
1908 doc.Save()
1909 yesNoMsg.Destroy()
1910
1911 def OnExit(self):
1912 DebugCommandUI.ShutdownAllDebuggers()
1913 RunCommandUI.ShutdownAllRunners()
1914
1915 def OnRunProject(self, event):
1916 if _WINDOWS and not _PYWIN32_INSTALLED:
1917 wx.MessageBox(_("Python for Windows extensions (pywin32) is required to run on Windows machines. Please go to http://sourceforge.net/projects/pywin32/, download and install pywin32."))
1918 return
1919 if not Executor.GetPythonExecutablePath():
1920 return
1921 projectService = wx.GetApp().GetService(ProjectEditor.ProjectService)
1922 try:
1923 dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None)
1924 except:
1925 return
1926 dlg.CenterOnParent()
1927 if dlg.ShowModal() == wx.ID_OK:
1928 projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings()
1929 dlg.Destroy()
1930 else:
1931 dlg.Destroy()
1932 return
1933 self.PromptToSaveFiles()
1934 # This will need to change when we can run more than .py and .bpel files.
1935 if not isPython:
1936 projects = projectService.FindProjectByFile(projectPath)
1937 if not projects:
1938 return
1939 project = projects[0]
1940 deployFilePath = project.GenerateDeployment()
1941 projectService.RunProcessModel(fileToRun, project.GetAppInfo().language, deployFilePath)
1942 return
1943
1944 self.ShowWindow(True)
1945 shortFile = os.path.basename(fileToRun)
1946 page = RunCommandUI(Service.ServiceView.bottomTab, -1, str(fileToRun))
1947 count = Service.ServiceView.bottomTab.GetPageCount()
1948 Service.ServiceView.bottomTab.AddPage(page, "Running: " + shortFile)
1949 Service.ServiceView.bottomTab.SetSelection(count)
1950 page.Execute(initialArgs, startIn, environment)
1951
1952 def OnToggleBreakpoint(self, event, line=-1, fileName=None):
1953 if not fileName:
1954 view = wx.GetApp().GetDocumentManager().GetCurrentView()
1955 # Test to make sure we aren't the project view.
1956 if not hasattr(view, 'MarkerExists'):
1957 return
1958 fileName = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
1959 if line < 0:
1960 line = view.GetCtrl().GetCurrentLine()
1961 else:
1962 view = None
1963 if self.BreakpointSet(fileName, line + 1):
1964 self.ClearBreak(fileName, line + 1)
1965 if view:
1966 view.GetCtrl().Refresh()
1967 else:
1968 self.SetBreak(fileName, line + 1)
1969 if view:
1970 view.GetCtrl().Refresh()
1971 # Now refresh all the markers icons in all the open views.
1972 self.ClearAllBreakpointMarkers()
1973 self.SetAllBreakpointMarkers()
1974
1975 def SilentToggleBreakpoint(self, fileName, line):
1976 found = False
1977 for lineNumber in self.GetBreakpointList(fileName):
1978 if int(lineNumber) == int(line):
1979 found = True
1980 break
1981 if found:
1982 self.SetBreak(fileName, line)
1983 else:
1984 self.ClearBreak(fileName, line)
1985
1986 def SetBreak(self, fileName, line):
1987 expandedName = DebuggerService.ExpandPath(fileName)
1988 if not self._masterBPDict.has_key(expandedName):
1989 self._masterBPDict[expandedName] = [line]
1990 else:
1991 self._masterBPDict[expandedName] += [line]
1992 # If we're already debugging, pass this bp off to the DebuggerCallback
1993 self.NotifyDebuggersOfBreakpointChange()
1994
1995 def NotifyDebuggersOfBreakpointChange(self):
1996 DebugCommandUI.NotifyDebuggersOfBreakpointChange()
1997
1998 def GetBreakpointList(self, fileName):
1999 expandedName = DebuggerService.ExpandPath(fileName)
2000 if not self._masterBPDict.has_key(expandedName):
2001 return []
2002 else:
2003 return self._masterBPDict[expandedName]
2004
2005 def SetBreakpointList(self, fileName, bplist):
2006 expandedName = DebuggerService.ExpandPath(fileName)
2007 self._masterBPDict[expandedName] = bplist
2008
2009 def BreakpointSet(self, fileName, line):
2010 expandedName = DebuggerService.ExpandPath(fileName)
2011 if not self._masterBPDict.has_key(expandedName):
2012 return False
2013 else:
2014 newList = []
2015 for number in self._masterBPDict[expandedName]:
2016 if(int(number) == int(line)):
2017 return True
2018 return False
2019
2020 def ClearBreak(self, fileName, line):
2021 expandedName = DebuggerService.ExpandPath(fileName)
2022 if not self._masterBPDict.has_key(expandedName):
2023 print "In ClearBreak: no key"
2024 return
2025 else:
2026 newList = []
2027 for number in self._masterBPDict[expandedName]:
2028 if(int(number) != int(line)):
2029 newList.append(number)
2030 self._masterBPDict[expandedName] = newList
2031 self.NotifyDebuggersOfBreakpointChange()
2032
2033 def HasBreakpointsSet(self):
2034 for key, value in self._masterBPDict.items():
2035 if len(value) > 0:
2036 return True
2037 return False
2038
2039 def ClearAllBreakpoints(self):
2040 self._masterBPDict = {}
2041 self.NotifyDebuggersOfBreakpointChange()
2042 self.ClearAllBreakpointMarkers()
2043
2044 def ClearAllBreakpointMarkers(self):
2045 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
2046 for openDoc in openDocs:
2047 if isinstance(openDoc, CodeEditor.CodeDocument):
2048 openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2049
2050 def UpdateBreakpointsFromMarkers(self, view, fileName):
2051 newbpLines = view.GetMarkerLines(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2052 self.SetBreakpointList(fileName, newbpLines)
2053
2054 def GetMasterBreakpointDict(self):
2055 return self._masterBPDict
2056
2057 def SetAllBreakpointMarkers(self):
2058 openDocs = wx.GetApp().GetDocumentManager().GetDocuments()
2059 for openDoc in openDocs:
2060 if(isinstance(openDoc, CodeEditor.CodeDocument)):
2061 self.SetCurrentBreakpointMarkers(openDoc.GetFirstView())
2062
2063 def SetCurrentBreakpointMarkers(self, view):
2064 if isinstance(view, CodeEditor.CodeView) and hasattr(view, 'GetDocument'):
2065 view.MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2066 for linenum in self.GetBreakpointList(view.GetDocument().GetFilename()):
2067 view.MarkerAdd(lineNum=int(linenum) - 1, marker_index=CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM)
2068
2069 class DebuggerOptionsPanel(wx.Panel):
2070
2071
2072 def __init__(self, parent, id):
2073 wx.Panel.__init__(self, parent, id)
2074 SPACE = 10
2075 config = wx.ConfigBase_Get()
2076 localHostStaticText = wx.StaticText(self, -1, _("Local Host Name:"))
2077 self._LocalHostTextCtrl = wx.TextCtrl(self, -1, config.Read("DebuggerHostName", DEFAULT_HOST), size = (150, -1))
2078 portNumberStaticText = wx.StaticText(self, -1, _("Port Range:"))
2079 dashStaticText = wx.StaticText(self, -1, _("through to"))
2080 startingPort=config.ReadInt("DebuggerStartingPort", DEFAULT_PORT)
2081 self._PortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort, size = (50, -1))
2082 self._PortNumberTextCtrl.SetMin(1)#What are real values?
2083 self._PortNumberTextCtrl.SetMax(65514) #What are real values?
2084 self.Bind(wx.lib.intctrl.EVT_INT, self.MinPortChange, self._PortNumberTextCtrl)
2085
2086 self._EndPortNumberTextCtrl = wx.lib.intctrl.IntCtrl(self, -1, startingPort + PORT_COUNT, size = (50, -1))
2087 self._EndPortNumberTextCtrl.SetMin(22)#What are real values?
2088 self._EndPortNumberTextCtrl.SetMax(65535)#What are real values?
2089 self._EndPortNumberTextCtrl.Enable( False )
2090 debuggerPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
2091 debuggerPanelSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
2092 debuggerPanelSizer.Add( localHostStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2093 debuggerPanelSizer.Add( self._LocalHostTextCtrl, (0,1), (1,3), flag=wx.EXPAND|wx.ALIGN_CENTER)
2094 debuggerPanelSizer.Add( portNumberStaticText, (1,0), flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)
2095 debuggerPanelSizer.Add( self._PortNumberTextCtrl, (1,1), flag=wx.ALIGN_CENTER)
2096 debuggerPanelSizer.Add( dashStaticText, (1,2), flag=wx.ALIGN_CENTER)
2097 debuggerPanelSizer.Add( self._EndPortNumberTextCtrl, (1,3), flag=wx.ALIGN_CENTER)
2098 FLUSH_PORTS_ID = wx.NewId()
2099 self._flushPortsButton = wx.Button(self, FLUSH_PORTS_ID, "Reset Port List")
2100 wx.EVT_BUTTON(parent, FLUSH_PORTS_ID, self.FlushPorts)
2101 debuggerPanelSizer.Add(self._flushPortsButton, (2,2), (1,2), flag=wx.ALIGN_RIGHT)
2102
2103 debuggerPanelBorderSizer.Add(debuggerPanelSizer, 0, wx.ALL, SPACE)
2104 self.SetSizer(debuggerPanelBorderSizer)
2105 self.Layout()
2106 parent.AddPage(self, _("Debugger"))
2107
2108 def FlushPorts(self, event):
2109 if self._PortNumberTextCtrl.IsInBounds():
2110 config = wx.ConfigBase_Get()
2111 config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
2112 DebugCommandUI.NewPortRange()
2113 else:
2114 wx.MessageBox(_("The starting port is not valid. Please change the value and try again.", "Invalid Starting Port Number"))
2115
2116 def MinPortChange(self, event):
2117 self._EndPortNumberTextCtrl.Enable( True )
2118 self._EndPortNumberTextCtrl.SetValue( self._PortNumberTextCtrl.GetValue() + PORT_COUNT)
2119 self._EndPortNumberTextCtrl.Enable( False )
2120
2121 def OnOK(self, optionsDialog):
2122 config = wx.ConfigBase_Get()
2123 config.Write("DebuggerHostName", self._LocalHostTextCtrl.GetValue())
2124 if self._PortNumberTextCtrl.IsInBounds():
2125 config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue())
2126
2127
2128 def GetIcon(self):
2129 return getContinueIcon()
2130
2131
2132 class CommandPropertiesDialog(wx.Dialog):
2133
2134 def __init__(self, parent, title, projectService, currentProjectDocument, pythonOnly=False, okButtonName="Run", debugging=False):
2135 self._projService = projectService
2136 self._pmext = None
2137 self._pyext = None
2138 for template in self._projService.GetDocumentManager().GetTemplates():
2139 if not ACTIVEGRID_BASE_IDE and template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument:
2140 self._pmext = template.GetDefaultExtension()
2141 if template.GetDocumentType() == PythonEditor.PythonDocument:
2142 self._pyext = template.GetDefaultExtension()
2143 self._pythonOnly = pythonOnly
2144 self._currentProj = currentProjectDocument
2145 self._projectNameList, self._projectDocumentList, selectedIndex = self.GetProjectList()
2146 if not self._projectNameList:
2147 wx.MessageBox(_("To run or debug you must have an open runnable file or project containing runnable files. Use File->Open to open the file you wish to run or debug."), _("Nothing to Run"))
2148 raise BadBadBad
2149
2150 wx.Dialog.__init__(self, parent, -1, title)
2151
2152 projStaticText = wx.StaticText(self, -1, _("Project:"))
2153 fileStaticText = wx.StaticText(self, -1, _("File:"))
2154 argsStaticText = wx.StaticText(self, -1, _("Arguments:"))
2155 startInStaticText = wx.StaticText(self, -1, _("Start in:"))
2156 pythonPathStaticText = wx.StaticText(self, -1, _("PYTHONPATH:"))
2157 postpendStaticText = _("Postpend win32api path")
2158 cpPanelBorderSizer = wx.BoxSizer(wx.VERTICAL)
2159 self._projList = wx.Choice(self, -1, choices=self._projectNameList)
2160 self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList)
2161 HALF_SPACE = 5
2162 GAP = HALF_SPACE
2163 if wx.Platform == "__WXMAC__":
2164 GAP = 10
2165 flexGridSizer = wx.GridBagSizer(GAP, GAP)
2166
2167 flexGridSizer.Add(projStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2168 flexGridSizer.Add(self._projList, (0,1), (1,2), flag=wx.EXPAND)
2169
2170 flexGridSizer.Add(fileStaticText, (1,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2171 self._fileList = wx.Choice(self, -1)
2172 self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList)
2173 flexGridSizer.Add(self._fileList, (1,1), (1,2), flag=wx.EXPAND)
2174
2175 config = wx.ConfigBase_Get()
2176 self._lastArguments = config.Read("LastRunArguments")
2177 self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments))
2178 self._argsEntry.SetToolTipString(str(self._lastArguments))
2179
2180 flexGridSizer.Add(argsStaticText, (2,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2181 flexGridSizer.Add(self._argsEntry, (2,1), (1,2), flag=wx.EXPAND)
2182
2183 flexGridSizer.Add(startInStaticText, (3,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2184 self._lastStartIn = config.Read("LastRunStartIn")
2185 if not self._lastStartIn:
2186 self._lastStartIn = str(os.getcwd())
2187 self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn)
2188 self._startEntry.SetToolTipString(self._lastStartIn)
2189
2190 flexGridSizer.Add(self._startEntry, (3,1), flag=wx.EXPAND)
2191 self._findDir = wx.Button(self, -1, _("Browse..."))
2192 self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir)
2193 flexGridSizer.Add(self._findDir, (3,2))
2194
2195 flexGridSizer.Add(pythonPathStaticText, (4,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT)
2196 if os.environ.has_key('PYTHONPATH'):
2197 startval = os.environ['PYTHONPATH']
2198 else:
2199 startval = ""
2200 self._lastPythonPath = config.Read("LastPythonPath", startval)
2201 self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath)
2202 self._pythonPathEntry.SetToolTipString(self._lastPythonPath)
2203 flexGridSizer.Add(self._pythonPathEntry, (4,1), (1,2), flag=wx.EXPAND)
2204
2205 if debugging and _WINDOWS:
2206 self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText)
2207 checked = bool(config.ReadInt("PythonPathPostpend", 1))
2208 self._postpendCheckBox.SetValue(checked)
2209 flexGridSizer.Add(self._postpendCheckBox, (5,1), flag=wx.EXPAND)
2210 cpPanelBorderSizer.Add(flexGridSizer, 0, flag=wx.ALL, border=10)
2211
2212 box = wx.StdDialogButtonSizer()
2213 self._okButton = wx.Button(self, wx.ID_OK, okButtonName)
2214 self._okButton.SetDefault()
2215 self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog"))
2216 box.AddButton(self._okButton)
2217 self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton)
2218 btn = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
2219 btn.SetHelpText(_("The Cancel button cancels the dialog."))
2220 box.AddButton(btn)
2221 box.Realize()
2222 cpPanelBorderSizer.Add(box, 0, flag=wx.ALIGN_RIGHT|wx.ALL, border=5)
2223
2224 self.SetSizer(cpPanelBorderSizer)
2225
2226 # Set up selections based on last values used.
2227 self._fileNameList = None
2228 self._selectedFileIndex = 0
2229 lastProject = config.Read("LastRunProject")
2230 lastFile = config.Read("LastRunFile")
2231
2232 if lastProject in self._projectNameList:
2233 selectedIndex = self._projectNameList.index(lastProject)
2234 elif selectedIndex < 0:
2235 selectedIndex = 0
2236 self._projList.Select(selectedIndex)
2237 self._selectedProjectIndex = selectedIndex
2238 self._selectedProjectDocument = self._projectDocumentList[selectedIndex]
2239 self.PopulateFileList(self._selectedProjectDocument, lastFile)
2240
2241 cpPanelBorderSizer.Fit(self)
2242
2243
2244 def OnOKClick(self, event):
2245 startIn = self._startEntry.GetValue()
2246 fileToRun = self._fileList.GetStringSelection()
2247 if not fileToRun:
2248 wx.MessageBox(_("You must select a file to proceed. Note that not all projects have files that can be run or debugged."))
2249 return
2250 isPython = fileToRun.endswith(self._pyext)
2251 if isPython and not os.path.exists(startIn):
2252 wx.MessageBox(_("Starting directory does not exist. Please change this value."))
2253 return
2254 config = wx.ConfigBase_Get()
2255 config.Write("LastRunProject", self._projectNameList[self._selectedProjectIndex])
2256 config.Write("LastRunFile", fileToRun)
2257 # Don't update the arguments or starting directory unless we're runing python.
2258 if isPython:
2259 config.Write("LastRunArguments", self._argsEntry.GetValue())
2260 config.Write("LastRunStartIn", self._startEntry.GetValue())
2261 config.Write("LastPythonPath",self._pythonPathEntry.GetValue())
2262 if hasattr(self, "_postpendCheckBox"):
2263 config.WriteInt("PythonPathPostpend", int(self._postpendCheckBox.GetValue()))
2264
2265 self.EndModal(wx.ID_OK)
2266
2267 def GetSettings(self):
2268 projectPath = self._selectedProjectDocument.GetFilename()
2269 filename = self._fileNameList[self._selectedFileIndex]
2270 args = self._argsEntry.GetValue()
2271 startIn = self._startEntry.GetValue()
2272 isPython = filename.endswith(self._pyext)
2273 env = os.environ
2274 if hasattr(self, "_postpendCheckBox"):
2275 postpend = self._postpendCheckBox.GetValue()
2276 else:
2277 postpend = False
2278 if postpend:
2279 env['PYTHONPATH'] = self._pythonPathEntry.GetValue() + os.pathsep + os.path.join(os.getcwd(), "3rdparty", "pywin32")
2280 else:
2281 env['PYTHONPATH'] = self._pythonPathEntry.GetValue()
2282
2283 return projectPath, filename, args, startIn, isPython, env
2284
2285 def OnFileSelected(self, event):
2286 self._selectedFileIndex = self._fileList.GetSelection()
2287 self.EnableForFileType(event.GetString())
2288
2289 def EnableForFileType(self, fileName):
2290 show = fileName.endswith(self._pyext)
2291 self._startEntry.Enable(show)
2292 self._findDir.Enable(show)
2293 self._argsEntry.Enable(show)
2294
2295 if not show:
2296 self._lastStartIn = self._startEntry.GetValue()
2297 self._startEntry.SetValue("")
2298 self._lastArguments = self._argsEntry.GetValue()
2299 self._argsEntry.SetValue("")
2300 else:
2301 self._startEntry.SetValue(self._lastStartIn)
2302 self._argsEntry.SetValue(self._lastArguments)
2303
2304
2305 def OnFindDirClick(self, event):
2306 dlg = wx.DirDialog(self, "Choose a starting directory:", self._startEntry.GetValue(),
2307 style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON)
2308
2309 dlg.CenterOnParent()
2310 if dlg.ShowModal() == wx.ID_OK:
2311 self._startEntry.SetValue(dlg.GetPath())
2312
2313 dlg.Destroy()
2314
2315
2316 def EvtListBox(self, event):
2317 if event.GetString():
2318 index = self._projectNameList.index(event.GetString())
2319 self._selectedProjectDocument = self._projectDocumentList[index]
2320 self._selectedProjectIndex = index
2321 self.PopulateFileList(self._selectedProjectDocument)
2322
2323 def FilterFileList(self, list):
2324 if self._pythonOnly:
2325 files = filter(lambda f: f.endswith(self._pyext), list)
2326 else:
2327 files = filter(lambda f: (self._pmext and f.endswith(self._pmext)) or f.endswith(self._pyext), list)
2328 return files
2329
2330 def PopulateFileList(self, project, shortNameToSelect=None):
2331 self._fileNameList = self.FilterFileList(project.GetFiles()[:])
2332 self._fileList.Clear()
2333 if not self._fileNameList:
2334 return
2335 self._fileNameList.sort(lambda a, b: cmp(os.path.basename(a).lower(), os.path.basename(b).lower()))
2336 strings = map(lambda file: os.path.basename(file), self._fileNameList)
2337 for index in range(0, len(strings)):
2338 if shortNameToSelect == strings[index]:
2339 self._selectedFileIndex = index
2340 break
2341 self._fileList.Hide()
2342 self._fileList.AppendItems(strings)
2343 self._fileList.Show()
2344 if self._selectedFileIndex not in range(0, len(strings)) : self._selectedFileIndex = 0
2345 self._fileList.SetSelection(self._selectedFileIndex)
2346 self.EnableForFileType(strings[self._selectedFileIndex])
2347
2348 def GetProjectList(self):
2349 docList = []
2350 nameList = []
2351 found = False
2352 index = -1
2353 count = 0
2354 for document in self._projService.GetDocumentManager().GetDocuments():
2355 if document.GetDocumentTemplate().GetDocumentType() == ProjectEditor.ProjectDocument and len(document.GetFiles()):
2356 docList.append(document)
2357 nameList.append(os.path.basename(document.GetFilename()))
2358 if document == self._currentProj:
2359 found = True
2360 index = count
2361 count += 1
2362 #Check for open files not in any of these projects and add them to a default project
2363 def AlreadyInProject(fileName):
2364 for projectDocument in docList:
2365 if projectDocument.IsFileInProject(fileName):
2366 return True
2367 return False
2368
2369 unprojectedFiles = []
2370 for document in self._projService.GetDocumentManager().GetDocuments():
2371 if not ACTIVEGRID_BASE_IDE and type(document) == ProcessModelEditor.ProcessModelDocument:
2372 if not AlreadyInProject(document.GetFilename()):
2373 unprojectedFiles.append(document.GetFilename())
2374 if type(document) == PythonEditor.PythonDocument:
2375 if not AlreadyInProject(document.GetFilename()):
2376 unprojectedFiles.append(document.GetFilename())
2377
2378 if unprojectedFiles:
2379 unprojProj = ProjectEditor.ProjectDocument()
2380 unprojProj.SetFilename(_("Not in any Project"))
2381 unprojProj.AddFiles(unprojectedFiles)
2382 docList.append(unprojProj)
2383 nameList.append(_("Not in any Project"))
2384
2385 return nameList, docList, index
2386
2387
2388 #----------------------------------------------------------------------
2389 from wx import ImageFromStream, BitmapFromImage
2390 import cStringIO
2391
2392 #----------------------------------------------------------------------
2393 def getBreakData():
2394 return \
2395 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
2396 \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
2397 \x00\x85IDAT(\x91\xbd\x92A\x16\x03!\x08CI\xdf\xdc\x0b\x8e\xe6\xd1\xe0d\xe9\
2398 \x82\xd6\xc7(\x9di7\xfd\xab<\x14\x13Q\xb8\xbb\xfc\xc2\xe3\xd3\x82\x99\xb9\
2399 \xe9\xaeq\xe1`f)HF\xc4\x8dC2\x06\xbf\x8a4\xcf\x1e\x03K\xe5h\x1bH\x02\x98\xc7\
2400 \x03\x98\xa9z\x07\x00%\xd6\xa9\xd27\x90\xac\xbbk\xe5\x15I\xcdD$\xdc\xa7\xceT\
2401 5a\xce\xf3\xe4\xa0\xaa\x8bO\x12\x11\xabC\xcb\x9c}\xd57\xef\xb0\xf3\xb7\x86p\
2402 \x97\xf7\xb5\xaa\xde\xb9\xfa|-O\xbdjN\x9b\xf8\x06A\xcb\x00\x00\x00\x00IEND\
2403 \xaeB`\x82'
2404
2405 def getBreakBitmap():
2406 return BitmapFromImage(getBreakImage())
2407
2408 def getBreakImage():
2409 stream = cStringIO.StringIO(getBreakData())
2410 return ImageFromStream(stream)
2411
2412 def getBreakIcon():
2413 return wx.IconFromBitmap(getBreakBitmap())
2414
2415 #----------------------------------------------------------------------
2416
2417 def getClearOutputData():
2418 return \
2419 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2420 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2421 \x00\x00\xb7IDAT8\x8d\xa5\x93\xdd\x11\xc3 \x0c\x83%`\xa3\xee\xd4\xaeA\xc6\
2422 \xe8N\xedF%\xea\x03\t\x81\xf0\x97\xbb\xf8%G\xce\xfe\x90eC\x1a\x8b;\xe1\xf2\
2423 \x83\xd6\xa0Q2\x8de\xf5oW\xa05H\xea\xd7\x93\x84$\x18\xeb\n\x88;\'.\xd5\x1d\
2424 \x80\x07\xe1\xa1\x1d\xa2\x1cbF\x92\x0f\x80\xe0\xd1 \xb7\x14\x8c \x00*\x15\
2425 \x97\x14\x8c\x8246\x1a\xf8\x98\'/\xdf\xd8Jn\xe65\xc0\xa7\x90_L"\x01\xde\x9d\
2426 \xda\xa7\x92\xfb\xc5w\xdf\t\x07\xc4\x05ym{\xd0\x1a\xe3\xb9xS\x81\x04\x18\x05\
2427 \xc9\x04\xc9a\x00Dc9\x9d\x82\xa4\xbc\xe8P\xb2\xb5P\xac\xf2\x0c\xd4\xf5\x00\
2428 \x88>\xac\xe17\x84\xe4\xb9G\x8b7\x9f\xf3\x1fsUl^\x7f\xe7y\x0f\x00\x00\x00\
2429 \x00IEND\xaeB`\x82'
2430
2431 def getClearOutputBitmap():
2432 return BitmapFromImage(getClearOutputImage())
2433
2434 def getClearOutputImage():
2435 stream = cStringIO.StringIO(getClearOutputData())
2436 return ImageFromStream(stream)
2437
2438 def getClearOutputIcon():
2439 return wx.IconFromBitmap(getClearOutputBitmap())
2440
2441 #----------------------------------------------------------------------
2442 def getCloseData():
2443 return \
2444 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x02\
2445 \x00\x00\x00\x90\x91h6\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\
2446 \x00\xedIDAT(\x91\xa5\x90!\xae\x840\x10\x86g_\xd6"*kz\x82j\xb0h\x1c\t\' x\
2447 \x92Z\xc2\x05\x10\x95\x18\x0e\x00\x02M\x82 \xe1\nMF#jz\x80\xea&+\x9a\x10\x96\
2448 \xdd}\xfb\xc8\x1b\xd7?\xdf\x97\xfe3\xb7u]\xe1\xca\xfc\\\xa2\xff- \xe24M\xc7\
2449 \xc49wJ\xee\xc7G]\xd7\x8c1\xc6\x18\xe7\xdc\'B\x08k\xed1y\xfaa\x1cG\xad\xb5\
2450 \x94\x12\x11\x9dsy\x9e+\xa5\x84\x10;\r\x00\xb7\xd3\x95\x8c1UU\x05A\x00\x00\
2451 \xd6\xda,\xcb\x92$\xf9\xb8\x03\x00PJ\x85\x10Zk\xa5\xd4+\xfdF\x00\x80\xae\xeb\
2452 \x08!\x84\x90y\x9e\x11\xf1\x8bP\x96\xa5\xef\xdd\xb6\xad\xb5VJ\xf9\x9b\xe0\
2453 \xe9\xa6i8\xe7\xbe\xdb\xb6mi\x9a\x0e\xc3\xf0F\x88\xe3\x18\x00\xfa\xbe\x0f\
2454 \xc3\xd0\'\x9c\xf3eY\xa2(*\x8ab\xc7\x9e\xaed\x8c\xa1\x94\xben\xf5\xb1\xd2W\
2455 \xfa,\xfce.\x0b\x0f\xb8\x96e\x90gS\xe0v\x00\x00\x00\x00IEND\xaeB`\x82'
2456
2457 def getCloseBitmap():
2458 return BitmapFromImage(getCloseImage())
2459
2460 def getCloseImage():
2461 stream = cStringIO.StringIO(getCloseData())
2462 return ImageFromStream(stream)
2463
2464 def getCloseIcon():
2465 return wx.IconFromBitmap(getCloseBitmap())
2466
2467 #----------------------------------------------------------------------
2468 def getContinueData():
2469 return \
2470 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2471 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2472 \x00\x00\xcdIDAT8\x8d\xa5\x93\xd1\r\xc20\x0cD\xef\xec,\xc0b\x88\x8d`$\x06Cb\
2473 \x81\xc6\xc7GI\xeb\x94RZq?U"\xdby\xe7SIs\xfc#\xfbU\xa0\xa8\xba\xc6\xa0og\xee\
2474 !P\xd4y\x80\x04\xf3\xc2U\x82{\x9ct\x8f\x93\xb0\xa2\xdbm\xf5\xba\'h\xcdg=`\
2475 \xeeTT\xd1\xc6o& \t\x9a\x13\x00J\x9ev\xb1\'\xa3~\x14+\xbfN\x12\x92\x00@\xe6\
2476 \x85\xdd\x00\x000w\xe6\xe2\xde\xc7|\xdf\x08\xba\x1d(\xaa2n+\xca\xcd\x8d,\xea\
2477 \x98\xc4\x07\x01\x00D\x1dd^\xa8\xa8j\x9ew\xed`\xa9\x16\x99\xde\xa6G\x8b\xd3Y\
2478 \xe6\x85]\n\r\x7f\x99\xf5\x96Jnlz#\xab\xdb\xc1\x17\x19\xb0XV\xc2\xdf\xa3)\
2479 \x85<\xe4\x88\x85.F\x9a\xf3H3\xb0\xf3g\xda\xd2\x0b\xc5_|\x17\xe8\xf5R\xd6\
2480 \x00\x00\x00\x00IEND\xaeB`\x82'
2481
2482 def getContinueBitmap():
2483 return BitmapFromImage(getContinueImage())
2484
2485 def getContinueImage():
2486 stream = cStringIO.StringIO(getContinueData())
2487 return ImageFromStream(stream)
2488
2489 def getContinueIcon():
2490 return wx.IconFromBitmap(getContinueBitmap())
2491
2492 #----------------------------------------------------------------------
2493 def getNextData():
2494 return \
2495 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2496 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2497 \x00\x00\x8eIDAT8\x8d\xa5SA\x12\xc4 \x08K\xb0\xff\xde\xe9\xbf\xb7\xa6\x87\
2498 \x1d:\xba\xa2tZn(\x84`"i\x05obk\x13\xd5CmN+\xcc\x00l\xd6\x0c\x00\xf5\xf8\x0e\
2499 gK\x06\x00 \xa5=k\x00\x00\xb0\xb2]\xd4?5f\xb1\xdb\xaf\xc6\xa2\xcb\xa8\xf0?\
2500 \x1c\x98\xae\x82\xbf\x81\xa4\x8eA\x16\xe1\n\xd1\xa4\x19\xb3\xe9\n\xce\xe8\
2501 \xf1\n\x9eg^\x18\x18\x90\xec<\x11\xf9#\x04XMZ\x19\xaac@+\x94\xd4\x99)SeP\xa1\
2502 )\xd6\x1dI\xe7*\xdc\xf4\x03\xdf~\xe7\x13T^Q?:X\x19d\x00\x00\x00\x00IEND\xaeB\
2503 `\x82'
2504
2505 def getNextBitmap():
2506 return BitmapFromImage(getNextImage())
2507
2508 def getNextImage():
2509 stream = cStringIO.StringIO(getNextData())
2510 return ImageFromStream(stream)
2511
2512 def getNextIcon():
2513 return wx.IconFromBitmap(getNextBitmap())
2514
2515 #----------------------------------------------------------------------
2516 def getStepInData():
2517 return \
2518 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2519 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2520 \x00\x00\x87IDAT8\x8d\xadSA\x12\x84 \x0ck\x8a\xffv\xfc\xb74{X\xeb0P@\x07s\
2521 \x84\xa4$\x01\x00M\xb2\x02]R\x8b\xc86\xda\xdc\xedd\xb4~\xe8\x86\xc6\x01-\x93\
2522 \x96\xd9#\xf6\x06\xc3;p1I\xd1\x14\x0b#|\x17aF\xec\r\xeeF\xa0eB\xd34\xca\xd0A\
2523 ]j\x84\xa6\x03\x00""\xb7\xb0tRZ\xf7x\xb7\x83\x91]\xcb\x7fa\xd9\x89\x0fC\xfd\
2524 \x94\x9d|9\x99^k\x13\xa1 \xb3\x16\x0f#\xd4\x88N~\x14\xe1-\x96\x7f\xe3\x0f\
2525 \x11\x91UC\x0cX\'\x1e\x00\x00\x00\x00IEND\xaeB`\x82'
2526
2527 def getStepInBitmap():
2528 return BitmapFromImage(getStepInImage())
2529
2530 def getStepInImage():
2531 stream = cStringIO.StringIO(getStepInData())
2532 return ImageFromStream(stream)
2533
2534 def getStepInIcon():
2535 return wx.IconFromBitmap(getStepInBitmap())
2536
2537 #----------------------------------------------------------------------
2538 def getStopData():
2539 return \
2540 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2541 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2542 \x00\x00QIDAT8\x8d\xdd\x93A\n\xc00\x08\x04g\xb5\xff\x7fq\x13sn\xda&\x01\x0b\
2543 \xa5]\xf0"\xec(.J\xe6dd)\xf7\x13\x80\xadoD-12\xc8\\\xd3\r\xe2\xa6\x00j\xd9\
2544 \x0f\x03\xde\xbf\xc1\x0f\x00\xa7\x18\x01t\xd5\\\x05\xc8\\}T#\xe9\xfb\xbf\x90\
2545 \x064\xd8\\\x12\x1fQM\xf5\xd9\x00\x00\x00\x00IEND\xaeB`\x82'
2546
2547 def getStopBitmap():
2548 return BitmapFromImage(getStopImage())
2549
2550 def getStopImage():
2551 stream = cStringIO.StringIO(getStopData())
2552 return ImageFromStream(stream)
2553
2554 def getStopIcon():
2555 return wx.IconFromBitmap(getStopBitmap())
2556
2557 #----------------------------------------------------------------------
2558 def getStepReturnData():
2559 return \
2560 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2561 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2562 \x00\x00\x8dIDAT8\x8d\xa5S\xd1\x0e\xc4 \x08\xa3\xb0\xff\xbe\xdc\x7fO\xba'6\
2563 \xf1\xf44\xb3O$Phk\x04\xd4d\x07\xba\xc5\x16\x91#\nza\xdb\x84\x1a\xa2\xfe\xf8\
2564 \x99\xfa_=p+\xe8\x91ED\xbc<\xa4 \xb4\x0b\x01\xb5{\x01\xf9\xbbG-\x13\x87\x16f\
2565 \x84\xbf\x16V\xb0l\x01@\no\x86\xae\x82Q\xa8=\xa4\x0c\x80\xe70\xbd\x10jh\xbd\
2566 \x07R\x06#\xc9^N\xb6\xde\x03)\x83\x18\xaeU\x90\x9c>a\xb2P\r\xb3&/Y\xa8\xd1^^\
2567 \xb6\xf0\x16\xdb\xbf\xf1\x02\x81\xa5TK\x1d\x07\xde\x92\x00\x00\x00\x00IEND\
2568 \xaeB`\x82"
2569
2570 def getStepReturnBitmap():
2571 return BitmapFromImage(getStepReturnImage())
2572
2573 def getStepReturnImage():
2574 stream = cStringIO.StringIO(getStepReturnData())
2575 return ImageFromStream(stream)
2576
2577 def getStepReturnIcon():
2578 return wx.IconFromBitmap(getStepReturnBitmap())
2579
2580 #----------------------------------------------------------------------
2581 def getAddWatchData():
2582 return \
2583 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2584 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2585 \x00\x00\x85IDAT8\x8dc`\x18h\xc0\x88.\xd0\xc0\xf0\xff?*\x9f\x11C\rN\x80\xae\
2586 \x19\x97\x18\xd1\x9a\x896\x84\x18[p\xa9aA\xe6\xfc7f\xc0P\xc4x\x163\x9cp\x1a0\
2587 \xeb,!w\x100 \x1dK\xac\x10\r\x08\x05".yFL\x85\x8c\x18b\xa8|Ty\xa2\x13\x92\'\
2588 \xc3\xe4\xff\x9f\x18\x1e3\xb82t\xa2\x88\x13\xedg.\x06aa&\x06VV\x7f\x86\xb9\
2589 \xcfU\x19\xbc\xb0\xba\x86h\xe0\xc8\xd0\xfc\xbf\x80\xe1>q)\x94\xe6\x00\x00\
2590 \x85\x923_\xd22\xa4\xcd\x00\x00\x00\x00IEND\xaeB`\x82'
2591
2592 def getAddWatchBitmap():
2593 return BitmapFromImage(getAddWatchImage())
2594
2595 def getAddWatchImage():
2596 stream = cStringIO.StringIO(getAddWatchData())
2597 return ImageFromStream(stream)
2598
2599 def getAddWatchIcon():
2600 return wx.IconFromBitmap(getAddWatchBitmap())
2601
2602 #----------------------------------------------------------------------
2603 def getRunningManData():
2604 return \
2605 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2606 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2607 \x00\x01\x86IDAT8\x8d\xa5\x93\xb1K\x02Q\x1c\xc7\xbf\xcf\x9a\x1bZl\x88\xb4\
2608 \x04\x83\x10\xa2\x96\xc0A\xa8\x96\x96\xf4h\xe9\xf0\x1f\xd0\xcd(Bpi\x13nH\xb2\
2609 %\x9d\x1a"\xb9)\xb4\x16i\x10\n\x13MA\x84\xa3&\xa1\xa1A\xa1E\xbdw\x97\xa2\xbd\
2610 \x06\xf1(\xef,\xac\xef\xf6x\xdf\xf7}\x9f\xdf\x97\xf7\x081M\xe0?\x9a\xfc\xcd \
2611 \\\xdc2\x99\xb6A[\x14\x91C\x9e\x8c\x1d\x00\x00\xd5\xa7*\x9a\x8a\xfa7\x82u\
2612 \xfb\x14dj\x03mQ\xc3}\xf2\xb5\x83\xc7B\x9e\x89\xf7/\xda\xba\xd1\x94\x01\x00j\
2613 CF\xe2t\xef\x1b>\x1f\x8c3Q\xf0\x11\xd3p\xa2yf\x1a\xbc\xcb\n\xdee\x85\xdd>\
2614 \x07\xb5!C\xe9\xb4\xb1\xe9=b\x03\x8fc\xc3\xcf\xbcN\xb3\x9e`@\x11\xb9\xaa`\
2615 \x7fg\x19\'\x97y\xd8\x96\xfa\xf8\x95\xf23d\xa5O4\xbfh\x87(\xf8\x88a\xc0 $|~\
2616 \x87n\xf7\x03\xaa\xf2\x8e\xc0\xee\n\x00 \x91\xab\xc3\xeb4\xc3\xed\xe1\xb4qF\
2617 \x96\xb8`\xb3h\xb7\xa6Jo\xa0\x9d\x1eD\xc1G\xc4!\x9f\xae\x03\x00\xa8\xd5jh4e\
2618 \r\xb9\xf0P\x82T,\x83\xf3\x0bl\xd8k\x18\xe0\xf6p\x84vz\xa0M\x8aB\xf2\x98\x84\
2619 \x03[\xb0.XP\xcafu^m\x04>\x18\xd7\x9aM\xe4\xea\xba\xc0x\xec\x8c\xa9\xca*^\
2620 \xa5\x1b}\xc0u*\xc9B\xd14\x12\xe8\x97%\x15\xcbF`\xdaH\xba\x80P4\r)\x13#R\xc6\
2621 \xf0\xdc\x8f2\x01\x80\x94\x89\xe9>\xc9(\xcd:\xb6\xd9\x1aw\xa0\x95i\xf8\x0e\
2622 \xc6\xd1\'\'\x86\xa2\xd5\x8d \xbe@\x00\x00\x00\x00IEND\xaeB`\x82'
2623
2624 def getRunningManBitmap():
2625 return BitmapFromImage(getRunningManImage())
2626
2627 def getRunningManImage():
2628 stream = cStringIO.StringIO(getRunningManData())
2629 return ImageFromStream(stream)
2630
2631 def getRunningManIcon():
2632 icon = EmptyIcon()
2633 icon.CopyFromBitmap(getRunningManBitmap())
2634 return icon
2635
2636 #----------------------------------------------------------------------
2637 def getDebuggingManData():
2638 return \
2639 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2640 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2641 \x00\x01\xafIDAT8\x8d\x8d\x93\xbfK[Q\x14\xc7?7\n:\t\xb5SA\xc1?@\xc1A\x9c,%\
2642 \xd0\xa9\x83\xb5\x98!(b\t\xbc\xa7q("m\x1c\n5V]D\xd4-\xf8\x83\xa7\xa2\t\xa1\
2643 \xa6\xed$8\x08\x92\xa1\x8b\x14A\xd0YB"\xa4\xf4\x87\x90\x97K\xa8\xcb\xed\xf0\
2644 \xc8m\xae\xfa\xd4\x03\x07.\xe7\x9e\xf3\xfd\x9e\x9f\x88@\x1d\xb5\xba\x94\xca\
2645 \xaa\xeb\xb6\xbb4\xc0\x03d&\xb1\xa7\xfc\xfe\x0c\x80L\xdaQ\xd2\xad\x90I;F\x80\
2646 ++\xbe\xe0bve\xdf\xd7y\xfemH\xc4\x162\xaa\xbb\xa5D(\x1c\x11\xb7\x02\x88@\x9d\
2647 f?*4\xd1\xf6\xa2\x0f\x80\x93\xf4\x8e\xe1\xb8\xf2\xf1\xb5\x18\x9cH(\x80\xe4bT\
2648 \x83\xd5W\x1f\xa1pD\x8c|\xd8T\x00\xdf\xd6\xd7\xe8\x1f\xb3tp\xf1\n^\xfe\xf8\
2649 \xa5^u7\x00P\x1eYP\xd2\x95\x1c\xa4\xa6\x84\x18\x8do\xab*C&\xed\xa8\xafG\x7f\
2650 \xe9\x1f\xb3x\xdc\x08\xad\x8f \x7f\tg%\xf8Y\x82\xe3\x8de\x86\x82\xcdF9\xba\
2651 \x84\xc1\x89\x84*K\t\xc0\xf0\xbbq:\x9f\xfcO\x7f?\xe7\x01\x9c\xff\x86Br\x8e\
2652 \x83\xd4\x94\x06\xd0SH.F\xc5P\xb0\x19\xe9z \xf9KOmkN\x07\x03\x14/r\xb4?\x8b\
2653 \xe8\xc6\xeb\x1e\x00l\x1f\xfe\xd15\x17\xaf<\xdb\xd37\xef\xd9\x9d\xb4\xe9\x8a\
2654 \xadj\xbfx\xb4\x878(#\x03\x00\xe9JF{[\xf92\xeb\xb1V\x99\xbbb\xab|\x9f\xb7\
2655 \x8d\xa9\x9cf\x1dq\x9au\xc4\x8dM\x0c\x85#\xa2x\x91cw\xd2\xd6i\x83\trk\x13\
2656 \x9f\x0fL\xab\xda\xe6\xd4\xd6Y+\xf1h\x8f\xb9T~G\xd2\x11\xb4\xd4\xe7O[\xf7\
2657 \x1e\xd6\x9d\xc7\xe4\xb7\xbe\x86\xf8\xb1?\xf4\x9c\xff\x01\xbe\xe9\xaf\x96\
2658 \xf0\x7fPA\x00\x00\x00\x00IEND\xaeB`\x82'
2659
2660 def getDebuggingManBitmap():
2661 return BitmapFromImage(getDebuggingManImage())
2662
2663 def getDebuggingManImage():
2664 stream = cStringIO.StringIO(getDebuggingManData())
2665 return ImageFromStream(stream)
2666
2667 def getDebuggingManIcon():
2668 icon = EmptyIcon()
2669 icon.CopyFromBitmap(getDebuggingManBitmap())
2670 return icon
2671
2672 #----------------------------------------------------------------------
2673