// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) using System; using System.Collections.Generic; using System.Windows; using System.Windows.Input; using Debugger; using Debugger.AddIn; using Debugger.AddIn.Pads.Controls; using Debugger.AddIn.TreeModel; using ICSharpCode.Core; using ICSharpCode.Core.Presentation; using ICSharpCode.NRefactory; using ICSharpCode.SharpDevelop.Project; using Exception = System.Exception; namespace ICSharpCode.SharpDevelop.Gui.Pads { public class WatchPad : DebuggerPad { WatchList watchList; Process debuggedProcess; static WatchPad instance; /// Always check if Instance is null, might be null if pad is not opened! public static WatchPad Instance { get { return instance; } } public WatchPad() { instance = this; } /// /// This is not used anywhere, but it is neccessary to be overridden in children of AbstractPadContent. /// public override object Control { get { return watchList; } } public Process Process { get { return debuggedProcess; } } protected override void InitializeComponents() { watchList = new WatchList(); watchList.MouseDoubleClick += watchList_DoubleClick; watchList.ContextMenu = MenuService.CreateContextMenu(this, "/SharpDevelop/Pads/WatchPad/ContextMenu"); watchList.AllowDrop = true; watchList.DragEnter += watchList_DragOver; watchList.Drop += watchList_Drop; watchList.KeyUp += watchList_KeyUp; } void watchList_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Delete) { RemoveWatchCommand cmd = new RemoveWatchCommand { Owner = this }; cmd.Run(); } } void watchList_Drop(object sender, DragEventArgs e) { if (ProjectService.CurrentProject == null) return; if (e.Data == null) return; if (!e.Data.GetDataPresent(DataFormats.StringFormat)) return; if (string.IsNullOrEmpty(e.Data.GetData(DataFormats.StringFormat).ToString())) return; string language = ProjectService.CurrentProject.Language; // FIXME languages TextNode text = new TextNode(e.Data.GetData(DataFormats.StringFormat).ToString(), language == "VB" || language == "VBNet" ? SupportedLanguage.VBNet : SupportedLanguage.CSharp); if (!watchList.WatchItems.Contains(text)) watchList.WatchItems.ContainsItem(text); this.RefreshPad(); } void watchList_DragOver(object sender, DragEventArgs e) { if(e.Data.GetDataPresent(DataFormats.StringFormat)) { e.Effects = DragDropEffects.Copy; } else { e.Effects = DragDropEffects.None; e.Handled = true; } } void watchList_DoubleClick(object sender, MouseEventArgs e) { if (watchList.SelectedNode == null) { AddWatchCommand command = new AddWatchCommand { Owner = this }; command.Run(); } } void ResetPad(object sender, EventArgs e) { string language = ProjectService.CurrentProject.Language; // rebuild list var nodes = new List(); foreach (var nod in watchList.WatchItems) nodes.Add(new TextNode(nod.Name, language == "VB" || language == "VBNet" ? SupportedLanguage.VBNet : SupportedLanguage.CSharp)); watchList.WatchItems.Clear(); foreach (var nod in nodes) watchList.WatchItems.Add(nod); } protected override void SelectProcess(Process process) { if (debuggedProcess != null) { debuggedProcess.Paused -= debuggedProcess_Paused; debuggedProcess.Exited -= ResetPad; } debuggedProcess = process; if (debuggedProcess != null) { debuggedProcess.Paused += debuggedProcess_Paused; debuggedProcess.Exited += ResetPad; } RefreshPad(); } void debuggedProcess_Paused(object sender, ProcessEventArgs e) { RefreshPad(); } public override void RefreshPad() { if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedStackFrame == null) return; using(new PrintTimes("Watch Pad refresh")) { try { Utils.DoEvents(debuggedProcess); List nodes = new List(); foreach (var nod in watchList.WatchItems) { try { LoggingService.Info("Evaluating: " + (string.IsNullOrEmpty(nod.Name) ? "is null or empty!" : nod.Name)); var nodExpression = debugger.GetExpression(nod.Name); //Value val = ExpressionEvaluator.Evaluate(nod.Name, nod.Language, debuggedProcess.SelectedStackFrame); ExpressionNode valNode = new ExpressionNode(null, nod.Name, nodExpression); nodes.Add(valNode); } catch (GetValueException) { string error = String.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.InvalidExpression}"), nod.Name); ErrorInfoNode infoNode = new ErrorInfoNode(nod.Name, error); nodes.Add(infoNode); } } // rebuild list watchList.WatchItems.Clear(); foreach (var nod in nodes) watchList.WatchItems.Add(nod); } catch(AbortedBecauseDebuggeeResumedException) { } catch(Exception ex) { if (debuggedProcess == null || debuggedProcess.HasExited) { // Process unexpectedly exited } else { MessageService.ShowException(ex); } } } } } }