Browse Source

Implemented watch pad

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3470 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 17 years ago
parent
commit
9d7747a126
  1. 19
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin
  2. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
  3. 18
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs
  4. 249
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/WatchPad.cs
  5. 95
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/WatchPadCommands.cs
  6. 8
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/AbstractNode.cs
  7. 4
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewVarNode.cs
  8. 4
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Utils.cs
  9. 6
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs

19
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin

@ -88,6 +88,25 @@ @@ -88,6 +88,25 @@
icon = "PadIcons.Output"
shortcut = "Control|Alt|N"
class = "ICSharpCode.SharpDevelop.Gui.Pads.ConsolePad"/>
<Pad id = "WatchPad"
category = "Debugger"
title = "${res:MainWindow.Windows.Debug.Watch}"
icon = "PadIcons.LocalVariables"
shortcut = "Control|Alt|W"
class = "ICSharpCode.SharpDevelop.Gui.Pads.WatchPad"/>
</Path>
<Path name ="/SharpDevelop/Pads/WatchPad/ContextMenu">
<MenuItem id="AddWatch" label="${res:MainWindow.Windows.Debug.Watch.AddWatch}" class="Debugger.AddIn.AddWatchCommand" />
<MenuItem id="RemoveWatch" label="${res:MainWindow.Windows.Debug.Watch.RemoveWatch}" class="Debugger.AddIn.RemoveWatchCommand" />
<MenuItem id="ClearWatches" label="${res:MainWindow.Windows.Debug.Watch.RemoveAll}" class="Debugger.AddIn.ClearWatchesCommand" />
<Condition name = "IsProcessRunning" isdebugging="True">
<Condition name = "IsProcessRunning" isdebugging="True" isprocessrunning="False">
<MenuItem id="Separator1" type="Separator" />
<MenuItem id="RefreshWatches" label="${res:MainWindow.Windows.Debug.Watch.Refresh}" class="Debugger.AddIn.RefreshWatchesCommand" />
</Condition>
</Condition>
</Path>
<Path name = "/SharpDevelop/Dialogs/OptionsDialog">

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj

@ -61,12 +61,14 @@ @@ -61,12 +61,14 @@
<Compile Include="Src\Options\DebuggingSymbolsPanel.Designer.cs">
<DependentUpon>DebuggingSymbolsPanel.cs</DependentUpon>
</Compile>
<Compile Include="Src\Pads\WatchPadCommands.cs" />
<Compile Include="Src\Pads\BreakPointsPad.cs" />
<Compile Include="Src\Pads\CallStackPad.cs" />
<Compile Include="Src\Pads\ConsolePad.cs" />
<Compile Include="Src\Pads\LoadedModulesPad.cs" />
<Compile Include="Src\Pads\LocalVarPad.cs" />
<Compile Include="Src\Pads\RunningThreadsPad.cs" />
<Compile Include="Src\Pads\WatchPad.cs" />
<Compile Include="Src\Service\AttachToProcessForm.cs" />
<Compile Include="Src\Service\DebugeeExceptionForm.cs">
<SubType>Form</SubType>

18
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs

@ -157,13 +157,25 @@ namespace Debugger.AddIn @@ -157,13 +157,25 @@ namespace Debugger.AddIn
switch (binaryOperatorExpression.Op)
{
case BinaryOperatorType.Equality :
val.PrimitiveValue = (right.PrimitiveValue.ToString() == left.PrimitiveValue.ToString());
val.PrimitiveValue = (right.PrimitiveValue == left.PrimitiveValue);
break;
case BinaryOperatorType.InEquality :
val.PrimitiveValue = (right.PrimitiveValue.ToString() != left.PrimitiveValue.ToString());
val.PrimitiveValue = (right.PrimitiveValue != left.PrimitiveValue);
break;
// case BinaryOperatorType.Add :
// val.PrimitiveValue = (right.PrimitiveValue.ToString() + left.PrimitiveValue.ToString());
// break;
// case BinaryOperatorType.GreaterThan :
// val.PrimitiveValue = (right.PrimitiveValue > left.PrimitiveValue);
// break;
// case BinaryOperatorType.LessThanOrEqual :
// val.PrimitiveValue = (right.PrimitiveValue <= left.PrimitiveValue);
// break;
// case BinaryOperatorType.GreaterThanOrEqual :
// val.PrimitiveValue = (right.PrimitiveValue >= left.PrimitiveValue);
// break;
default :
throw new NotImplementedException("BinaryOperator not implemented!");
throw new NotImplementedException("BinaryOperator: " + binaryOperatorExpression.Op + "!");
}
return val;

249
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/WatchPad.cs

@ -0,0 +1,249 @@ @@ -0,0 +1,249 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
// <version>$Revision: 2039 $</version>
// </file>
using ICSharpCode.Core.WinForms;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using Debugger;
using Debugger.AddIn;
using Debugger.AddIn.TreeModel;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class TextNode : AbstractNode, ISetText
{
public TextNode(string text)
{
this.Name = text;
}
public bool CanSetText {
get {
return true;
}
}
public bool SetText(string text)
{
this.Text = text;
return true;
}
public bool SetName(string name)
{
this.Name = name;
return true;
}
}
public sealed class WatchItemName: NodeTextBox {
public WatchItemName()
{
this.EditEnabled = true;
this.EditOnClick = true;
}
protected override bool CanEdit(TreeNodeAdv node)
{
AbstractNode content = ((TreeViewVarNode)node).Content;
return (content is ISetText) && ((ISetText)content).CanSetText;
}
public override object GetValue(TreeNodeAdv node)
{
if (node is TreeViewVarNode) {
return ((TreeViewVarNode)node).Content.Name;
} else {
// Happens during incremental search
return base.GetValue(node);
}
}
public override void SetValue(TreeNodeAdv node, object value)
{
if (((TreeViewVarNode)node).Content is ValueNode)
((ValueNode)((TreeViewVarNode)node).Content).SetName(value.ToString());
else {
if (((TreeViewVarNode)node).Content is TextNode)
((TextNode)((TreeViewVarNode)node).Content).SetName(value.ToString());
}
}
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
{
AbstractNode content = ((TreeViewVarNode)args.Node).Content;
if (content is IContextMenu && args.Button == MouseButtons.Right) {
ContextMenuStrip menu = ((IContextMenu)content).GetContextMenu();
if (menu != null) {
menu.Show(args.Node.Tree, args.Location);
}
} else {
base.MouseDown(args);
}
}
}
public class WatchPad : DebuggerPad
{
TreeViewAdv watchList;
Debugger.Process debuggedProcess;
List<TextNode> watches;
public List<TextNode> Watches {
get { return watches; }
}
readonly TreeColumn nameColumn = new TreeColumn();
readonly TreeColumn valColumn = new TreeColumn();
readonly TreeColumn typeColumn = new TreeColumn();
/// <remarks>
/// This is not used anywhere, but it is neccessary to be overridden in children of AbstractPadContent.
/// </remarks>
public override Control Control {
get {
return watchList;
}
}
public Process Process {
get { return debuggedProcess; }
}
protected override void InitializeComponents()
{
watchList = new TreeViewAdv();
watchList.Columns.Add(nameColumn);
watchList.Columns.Add(valColumn);
watchList.Columns.Add(typeColumn);
watchList.UseColumns = true;
watchList.SelectionMode = TreeSelectionMode.Single;
watchList.LoadOnDemand = true;
NodeIcon iconControl = new ItemIcon();
iconControl.ParentColumn = nameColumn;
watchList.NodeControls.Add(iconControl);
NodeTextBox nameControl = new WatchItemName();
nameControl.ParentColumn = nameColumn;
watchList.NodeControls.Add(nameControl);
NodeTextBox textControl = new ItemText();
textControl.ParentColumn = valColumn;
watchList.NodeControls.Add(textControl);
NodeTextBox typeControl = new ItemType();
typeControl.ParentColumn = typeColumn;
watchList.NodeControls.Add(typeControl);
watchList.AutoRowHeight = true;
watchList.DoubleClick += new EventHandler(watchList_DoubleClick);
watchList.ContextMenuStrip = MenuService.CreateContextMenu(this, "/SharpDevelop/Pads/WatchPad/ContextMenu");
watches = new List<TextNode>();
RedrawContent();
}
void watchList_DoubleClick(object sender, EventArgs e)
{
if (watchList.SelectedNode == null)
{
watchList.BeginUpdate();
TextNode text = new TextNode("");
TreeViewVarNode node = new TreeViewVarNode(this.debuggedProcess, this.watchList, text);
watches.Add(text);
watchList.Root.Children.Add(node);
watchList.EndUpdate();
this.RefreshPad();
}
}
void ResetPad(object sender, EventArgs e)
{
watchList.BeginUpdate();
watchList.Root.Children.Clear();
foreach (TextNode text in watches)
watchList.Root.Children.Add(new TreeViewVarNode(this.debuggedProcess, this.watchList, text));
watchList.EndUpdate();
}
public override void RedrawContent()
{
nameColumn.Header = ResourceService.GetString("Global.Name");
nameColumn.Width = 250;
valColumn.Header = ResourceService.GetString("Dialog.HighlightingEditor.Properties.Value");
valColumn.Width = 300;
typeColumn.Header = ResourceService.GetString("ResourceEditor.ResourceEdit.TypeColumn");
typeColumn.Width = 250;
}
protected override void SelectProcess(Debugger.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("Local Variables refresh")) {
try {
watchList.BeginUpdate();
Utils.DoEvents(debuggedProcess);
List<TreeViewVarNode> nodes = new List<TreeViewVarNode>();
foreach (TreeViewVarNode nod in this.watchList.Root.Children) {
try {
Value val = AstEvaluator.Evaluate(nod.Content.Name, SupportedLanguage.CSharp, debuggedProcess.SelectedStackFrame);
ValueNode valNode = new ValueNode(val);
valNode.SetName(nod.Content.Name);
nodes.Add(new TreeViewVarNode(debuggedProcess, watchList, valNode));
} catch (GetValueException) {
MessageService.ShowError(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.InvalidExpression}"), nod.Content.Name));
}
}
watchList.Root.Children.Clear();
foreach (TreeViewVarNode nod in nodes)
watchList.Root.Children.Add(nod);
} catch(AbortedBecauseDebuggeeResumedException) {
} catch(System.Exception) {
if (debuggedProcess == null || debuggedProcess.HasExited) {
// Process unexpectedly exited
} else {
throw;
}
}
}
watchList.EndUpdate();
}
}
}

95
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/WatchPadCommands.cs

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="sie_pam@gmx.at"/>
// <version>$Revision: 2039 $</version>
// </file>
using ICSharpCode.SharpDevelop.Gui.Pads;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using Debugger;
using Debugger.AddIn;
using Debugger.AddIn.TreeModel;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.NRefactory;
namespace Debugger.AddIn
{
public class AddWatchCommand : AbstractMenuCommand
{
public override void Run()
{
if (this.Owner is WatchPad) {
WatchPad pad = (WatchPad)this.Owner;
((TreeViewAdv)pad.Control).BeginUpdate();
TextNode text = new TextNode(MessageService.ShowInputBox(StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.AddWatch}"),
StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.EnterExpression}"),
""));
TreeViewVarNode node = new TreeViewVarNode(pad.Process, (TreeViewAdv)pad.Control, text);
pad.Watches.Add(text);
((TreeViewAdv)pad.Control).Root.Children.Add(node);
((TreeViewAdv)pad.Control).EndUpdate();
((WatchPad)this.Owner).RefreshPad();
}
}
}
public class RemoveWatchCommand : AbstractMenuCommand
{
public override void Run()
{
if (this.Owner is WatchPad) {
WatchPad pad = (WatchPad)this.Owner;
// TODO : Implement remove
TreeNodeAdv node = ((TreeViewAdv)pad.Control).SelectedNode;
if (node == null)
return;
while (node.Parent != ((TreeViewAdv)pad.Control).Root)
{
node = node.Parent;
}
pad.Watches.RemoveAt(node.Index);
((TreeViewAdv)pad.Control).Root.Children.Remove(node);
((WatchPad)this.Owner).RefreshPad();
}
}
}
public class RefreshWatchesCommand : AbstractMenuCommand
{
public override void Run()
{
if (this.Owner is WatchPad) {
((WatchPad)this.Owner).RefreshPad();
}
}
}
public class ClearWatchesCommand : AbstractMenuCommand
{
public override void Run()
{
if (this.Owner is WatchPad) {
WatchPad pad = (WatchPad)this.Owner;
((TreeViewAdv)pad.Control).BeginUpdate();
pad.Watches.Clear();
((TreeViewAdv)pad.Control).Root.Children.Clear();
((TreeViewAdv)pad.Control).EndUpdate();
}
}
}
}

8
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/AbstractNode.cs

@ -26,22 +26,22 @@ namespace Debugger.AddIn.TreeModel @@ -26,22 +26,22 @@ namespace Debugger.AddIn.TreeModel
public string Name {
get { return name; }
protected set { name = value; }
set { name = value; }
}
public string Text {
get { return text; }
protected set { text = value; }
set { text = value; }
}
public string Type {
get { return type; }
protected set { type = value; }
set { type = value; }
}
public IEnumerable<AbstractNode> ChildNodes {
get { return childNodes; }
protected set { childNodes = value; }
set { childNodes = value; }
}
}
}

4
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewVarNode.cs

@ -142,7 +142,7 @@ namespace Debugger.AddIn.TreeModel @@ -142,7 +142,7 @@ namespace Debugger.AddIn.TreeModel
}
}
private TreeViewVarNode(Debugger.Process process, TreeViewAdv localVarList, AbstractNode content): base(localVarList, new object())
public TreeViewVarNode(Debugger.Process process, TreeViewAdv localVarList, AbstractNode content): base(localVarList, new object())
{
this.process = process;
this.localVarList = localVarList;
@ -262,6 +262,8 @@ namespace Debugger.AddIn.TreeModel @@ -262,6 +262,8 @@ namespace Debugger.AddIn.TreeModel
protected override void OnExpanded()
{
base.OnExpanded();
if (process == null)
return;
expandedNodes[FullName] = true;
if (process.IsRunning) {
MessageService.ShowMessage(

4
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Utils.cs

@ -20,10 +20,14 @@ namespace Debugger.AddIn.TreeModel @@ -20,10 +20,14 @@ namespace Debugger.AddIn.TreeModel
/// <param name="process">Process on which to track debuggee state</param>
public static void DoEvents(Process process)
{
if (process == null) return;
DebuggeeState oldState = process.DebuggeeState;
//using(new PrintTimes("Application.DoEvents()"))
{
Application.DoEvents();
}
{
}
DebuggeeState newState = process.DebuggeeState;
if (oldState != newState) {

6
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs

@ -30,6 +30,12 @@ namespace Debugger.AddIn.TreeModel @@ -30,6 +30,12 @@ namespace Debugger.AddIn.TreeModel
get { return expression; }
}
/// <remarks>HACK for WatchPad</remarks>
public void SetName(string name)
{
this.Name = name;
}
/// <summary>
/// Factory method to create an instance.
/// </summary>

Loading…
Cancel
Save