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