Browse Source

Completely rewritten the variable model for Local Variables Pad and for the debugger tooltips.

Previously the nodes wrapped debugger values - any requests were redirected to the underling value.
The nodes are now based on Expressions and act as dum data storage.  When node is created the expression is evaluated and the properties (Image, Name, Text, Type) are stored locally in the node.  The node is immutable so its content can not be changed - the GUI need to create a fresh node.  This implies that the expression is evaluated only once - when the node is created.
A node can have child nodes.  The child nodes are created on-demand using enumerators.  This is desirable since creation of node involves evaluation of expression.  It also prevents infinite recursion.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2791 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 18 years ago
parent
commit
365047db5d
  1. 30
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/COPYING
  2. 20
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
  3. 15
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs
  4. 157
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DynamicTreeDebuggerRow.cs
  5. 17
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs
  6. 47
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/AbstractNode.cs
  7. 114
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/DynamicTreeDebuggerRow.cs
  8. 133
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewNode.cs
  9. 30
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ArrayRangeNode.cs
  10. 115
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs
  11. 127
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ExpressionNode.cs
  12. 19
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/IContextMenu.cs
  13. 17
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ISetText.cs
  14. 38
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs
  15. 156
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/BaseTypeItem.cs
  16. 106
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/FixedItem.cs
  17. 85
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/ListItem.cs
  18. 59
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/ListItemEventArgs.cs
  19. 109
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/StackFrameItem.cs
  20. 229
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/TreeViewNode.cs
  21. 184
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/ValueItem.cs
  22. 16
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Expressions/Expression.Evaluate.cs

30
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/COPYING

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
Copyright (c) 2007, ic#code
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the ic#code nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

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

@ -56,7 +56,6 @@ @@ -56,7 +56,6 @@
<EmbeddedResource Include="Src\Service\ExceptionForm.resx">
<DependentUpon>ExceptionForm.cs</DependentUpon>
</EmbeddedResource>
<Compile Include="Src\Service\DynamicTreeDebuggerRow.cs" />
<Compile Include="Src\Service\SetCurrentStatementCommand.cs" />
<Compile Include="Src\Service\DebuggerIcons.cs" />
<Compile Include="..\..\..\..\..\Main\GlobalAssemblyInfo.cs">
@ -65,13 +64,16 @@ @@ -65,13 +64,16 @@
<Compile Include="Src\Pads\DebuggerPad.cs" />
<Compile Include="Src\Pads\CallStackPad.Menu.cs" />
<Compile Include="Src\Pads\RunningThreadsPad.Menu.cs" />
<Compile Include="Src\Variables\BaseTypeItem.cs" />
<Compile Include="Src\Variables\FixedItem.cs" />
<Compile Include="Src\Variables\ListItem.cs" />
<Compile Include="Src\Variables\ListItemEventArgs.cs" />
<Compile Include="Src\Variables\StackFrameItem.cs" />
<Compile Include="Src\Variables\TreeViewNode.cs" />
<Compile Include="Src\Variables\ValueItem.cs" />
<Compile Include="Src\TreeModel\AbstractNode.cs" />
<Compile Include="Src\TreeModel\Adapters\DynamicTreeDebuggerRow.cs" />
<Compile Include="Src\TreeModel\Adapters\TreeViewNode.cs" />
<Compile Include="Src\TreeModel\ArrayRangeNode.cs" />
<Compile Include="Src\TreeModel\ExpressionNode.cs" />
<Compile Include="Src\TreeModel\IContextMenu.cs" />
<Compile Include="Src\TreeModel\ISetText.cs" />
<Compile Include="Src\TreeModel\ChildNodesOfObject.cs" />
<Compile Include="Src\TreeModel\StackFrameNode.cs" />
<None Include="COPYING" />
</ItemGroup>
<ItemGroup>
<Content Include="Client.config">
@ -117,6 +119,8 @@ @@ -117,6 +119,8 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Src\TreeModel" />
<Folder Include="Src\TreeModel\Adapters" />
<Folder Include="Src\Variables" />
<ProjectReference Include="..\..\..\..\..\Libraries\NRefactory\Project\NRefactory.csproj">
<Project>{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}</Project>

15
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs

@ -47,6 +47,7 @@ using Aga.Controls.Tree; @@ -47,6 +47,7 @@ using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using Debugger;
using Debugger.AddIn.TreeModel;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
@ -55,7 +56,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -55,7 +56,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
class ItemIcon: NodeIcon {
protected override System.Drawing.Image GetIcon(TreeNodeAdv node)
{
return ((TreeViewNode)node).Icon;
return ((TreeViewNode)node).Content.Image;
}
}
@ -66,18 +67,18 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -66,18 +67,18 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
public override object GetValue(TreeNodeAdv node)
{
return ((TreeViewNode)node).Name;
return ((TreeViewNode)node).Content.Name;
}
}
class ItemText: NodeTextBox {
protected override bool CanEdit(TreeNodeAdv node)
{
return ((TreeViewNode)node).CanEditText;
return ((TreeViewNode)node).Content is ISetText;
}
public override object GetValue(TreeNodeAdv node)
{
return ((TreeViewNode)node).Text;
return ((TreeViewNode)node).Content.Text;
}
}
@ -88,7 +89,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -88,7 +89,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
public override object GetValue(TreeNodeAdv node)
{
return ((TreeViewNode)node).Type;
return ((TreeViewNode)node).Content.Type;
}
}
@ -177,9 +178,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -177,9 +178,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{
DateTime start = Debugger.Util.HighPrecisionTimer.Now;
if (debuggedProcess != null && debuggedProcess.SelectedStackFrame != null) {
TreeViewNode.UpdateNodes(localVarList, localVarList.Root.Children, new StackFrameItem(debuggedProcess.SelectedStackFrame).SubItems);
TreeViewNode.OverwriteNodes(localVarList, localVarList.Root.Children, new StackFrameNode(debuggedProcess.SelectedStackFrame).ChildNodes);
} else {
TreeViewNode.UpdateNodes(localVarList, localVarList.Root.Children, new ListItem[0]);
TreeViewNode.OverwriteNodes(localVarList, localVarList.Root.Children, null);
}
DateTime end = Debugger.Util.HighPrecisionTimer.Now;
LoggingService.InfoFormatted("Local Variables pad refreshed ({0} ms)", (end - start).TotalMilliseconds);

157
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DynamicTreeDebuggerRow.cs

@ -1,157 +0,0 @@ @@ -1,157 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Debugger;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Widgets.TreeGrid;
using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Services
{
public class DynamicTreeDebuggerRow: DynamicTreeRow
{
// Columns:
// 0 = plus sign
// 1 = icon
// 2 = text
// 3 = value
ListItem listItem;
Image image;
bool populated = false;
bool visible = true;
public ListItem ListItem {
get {
return listItem;
}
}
public DynamicTreeDebuggerRow(Value val): this(new ValueItem(val))
{
}
public DynamicTreeDebuggerRow(ListItem listItem)
{
if (listItem == null) throw new ArgumentNullException("listItem");
this.listItem = listItem;
this.listItem.Changed += delegate { Update(); };
this.Shown += delegate {
visible = true;
WindowsDebugger.DoInPausedState( delegate { Update(); } );
};
this.Hidden += delegate {
visible = false;
};
DebuggerGridControl.AddColumns(this.ChildColumns);
this[1].Paint += OnIconPaint;
this[3].FinishLabelEdit += OnLabelEdited;
this[3].MouseDown += OnMouseDown;
Update();
}
void Update()
{
if (!visible) return;
this.image = listItem.Image;
this[1].Text = ""; // Icon
this[2].Text = listItem.Name;
this[3].Text = listItem.Text;
this[3].AllowLabelEdit = listItem.CanEditText;
this.ShowPlus = listItem.HasSubItems;
this.ShowMinusWhileExpanded = true;
}
void OnIconPaint(object sender, ItemPaintEventArgs e)
{
if (image != null) {
e.Graphics.DrawImageUnscaled(image, e.ClipRectangle);
}
}
void OnLabelEdited(object sender, DynamicListEventArgs e)
{
listItem.SetText(((DynamicListItem)sender).Text);
}
void OnMouseDown(object sender, DynamicListMouseEventArgs e)
{
if (e.Button == MouseButtons.Right) {
ContextMenuStrip menu = listItem.GetContextMenu();
if (menu != null) {
menu.Show(e.List, e.Location);
}
}
}
/// <summary>
/// Called when plus is pressed in debugger tooltip.
/// Sets the data to be show in the next level.
/// </summary>
protected override void OnExpanding(DynamicListEventArgs e)
{
if (!populated) {
WindowsDebugger.DoInPausedState(delegate { Populate(); });
}
}
void Populate()
{
this.ChildRows.Clear();
foreach(ListItem subItem in listItem.SubItems) {
this.ChildRows.Add(new DynamicTreeDebuggerRow(subItem));
}
populated = true;
}
}
}

17
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs

@ -42,6 +42,7 @@ using System.Diagnostics; @@ -42,6 +42,7 @@ using System.Diagnostics;
using System.Windows.Forms;
using Debugger;
using Debugger.AddIn.TreeModel;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
@ -247,12 +248,12 @@ namespace ICSharpCode.SharpDevelop.Services @@ -247,12 +248,12 @@ namespace ICSharpCode.SharpDevelop.Services
/// Gets variable of given name.
/// Returns null if unsuccessful.
/// </summary>
public Value GetVariableFromName(string variableName)
public Expression GetExpressionFromName(string variableName)
{
if (debuggedProcess == null || debuggedProcess.IsRunning) {
return null;
} else {
return debuggedProcess.GetValue(variableName);
return new Expression(variableName);
}
}
@ -263,12 +264,12 @@ namespace ICSharpCode.SharpDevelop.Services @@ -263,12 +264,12 @@ namespace ICSharpCode.SharpDevelop.Services
/// </summary>
public string GetValueAsString(string variableName)
{
Value val = GetVariableFromName(variableName);
Expression expression = GetExpressionFromName(variableName);
if (val == null) {
if (expression == null) {
return null;
} else {
return val.AsString;
return expression.Evaluate(this.DebuggedProcess.SelectedStackFrame).AsString;
}
}
@ -278,12 +279,12 @@ namespace ICSharpCode.SharpDevelop.Services @@ -278,12 +279,12 @@ namespace ICSharpCode.SharpDevelop.Services
/// </summary>
public DebuggerGridControl GetTooltipControl(string variableName)
{
Value val = GetVariableFromName(variableName.Trim());
Expression expression = GetExpressionFromName(variableName);
if (val == null) {
if (expression == null) {
return null;
} else {
return new DebuggerGridControl(new DynamicTreeDebuggerRow(val));
return new DebuggerGridControl(new DynamicTreeDebuggerRow(new ExpressionNode(expression)));
}
}

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

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
namespace Debugger.AddIn.TreeModel
{
public abstract class AbstractNode
{
Image image = null;
string name = string.Empty;
string text = string.Empty;
string type = string.Empty;
IEnumerable<AbstractNode> childNodes = null;
public Image Image {
get { return image; }
protected set { image = value; }
}
public string Name {
get { return name; }
protected set { name = value; }
}
public string Text {
get { return text; }
protected set { text = value; }
}
public string Type {
get { return type; }
protected set { type = value; }
}
public IEnumerable<AbstractNode> ChildNodes {
get { return childNodes; }
protected set { childNodes = value; }
}
}
}

114
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/DynamicTreeDebuggerRow.cs

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Debugger;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Services;
using ICSharpCode.SharpDevelop.Widgets.TreeGrid;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel
{
public class DynamicTreeDebuggerRow: DynamicTreeRow
{
// Columns:
// 0 = plus sign
// 1 = icon
// 2 = text
// 3 = value
AbstractNode content;
bool populated = false;
bool visible = true;
public AbstractNode Content {
get { return content; }
}
public DynamicTreeDebuggerRow(AbstractNode content)
{
this.content = content;
this.Shown += delegate {
visible = true;
WindowsDebugger.DoInPausedState( delegate { Update(); } );
};
this.Hidden += delegate {
visible = false;
};
DebuggerGridControl.AddColumns(this.ChildColumns);
this[1].Paint += OnIconPaint;
this[3].FinishLabelEdit += OnLabelEdited;
this[3].MouseDown += OnMouseDown;
Update();
}
void Update()
{
if (!visible) return;
this[1].Text = ""; // Icon
this[2].Text = content.Name;
this[3].Text = content.Text;
this[3].AllowLabelEdit = content is ISetText;
this.ShowPlus = content.ChildNodes != null;
this.ShowMinusWhileExpanded = true;
}
void OnIconPaint(object sender, ItemPaintEventArgs e)
{
if (content.Image != null) {
e.Graphics.DrawImageUnscaled(content.Image, e.ClipRectangle);
}
}
void OnLabelEdited(object sender, DynamicListEventArgs e)
{
((ISetText)content).SetText(((DynamicListItem)sender).Text);
}
void OnMouseDown(object sender, DynamicListMouseEventArgs e)
{
if (e.Button == MouseButtons.Right && content is IContextMenu) {
ContextMenuStrip menu = ((IContextMenu)content).GetContextMenu();
if (menu != null) {
menu.Show(e.List, e.Location);
}
}
}
/// <summary>
/// Called when plus is pressed in debugger tooltip.
/// Sets the data to be show in the next level.
/// </summary>
protected override void OnExpanding(DynamicListEventArgs e)
{
if (!populated) {
WindowsDebugger.DoInPausedState(delegate { Populate(); });
}
}
void Populate()
{
this.ChildRows.Clear();
foreach(AbstractNode childNode in content.ChildNodes) {
this.ChildRows.Add(new DynamicTreeDebuggerRow(childNode));
}
populated = true;
}
}
}

133
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewNode.cs

@ -0,0 +1,133 @@ @@ -0,0 +1,133 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Windows.Forms;
using Aga.Controls.Tree;
using ICSharpCode.Core;
namespace Debugger.AddIn.TreeModel
{
public partial class TreeViewNode: TreeNodeAdv
{
AbstractNode content;
bool populated = false;
public AbstractNode Content {
get { return content; }
set { content = value; }
}
public TreeViewNode(TreeViewAdv tree, AbstractNode content): base(tree, new object())
{
this.content = content;
this.IsLeaf = content.ChildNodes == null;
}
public void OnExpanding()
{
if (!populated) {
foreach(AbstractNode childNode in this.Content.ChildNodes) {
Children.Add(new TreeViewNode(Tree, childNode));
}
populated = true;
this.IsExpandedOnce = true;
this.Tree.UpdateSelection();
this.Tree.FullUpdate();
}
}
public static void OverwriteNodes(TreeViewAdv tree, Collection<TreeNodeAdv> treeNodes, IEnumerable<AbstractNode> modelNodes)
{
modelNodes = modelNodes ?? new AbstractNode[0];
int index = 0;
foreach(AbstractNode modelNode in modelNodes) {
// Add or overwrite existing items
if (index < treeNodes.Count) {
// Overwrite
((TreeViewNode)treeNodes[index]).Content = modelNode;
} else {
// Add
treeNodes.Add(new TreeViewNode(tree, modelNode));
}
index++;
}
int count = index;
// Delete other nodes
while(treeNodes.Count > count) {
treeNodes.RemoveAt(count);
}
tree.FullUpdate();
}
#region DoApplicationEvents()
static DateTime nextDoEventsTime = Debugger.Util.HighPrecisionTimer.Now;
const double workLoad = 0.75; // Fraction of getting variables vs. repainting
const double maxFPS = 30; // ms this prevents too much drawing on good machine
const double maxWorkTime = 250; // ms this ensures minimal response on bad machine
void DoApplicationEvents()
{
if (Debugger.Util.HighPrecisionTimer.Now > nextDoEventsTime) {
DateTime start = Debugger.Util.HighPrecisionTimer.Now;
Application.DoEvents();
DateTime end = Debugger.Util.HighPrecisionTimer.Now;
double doEventsDuration = (end - start).TotalMilliseconds;
double minWorkTime = 1000 / maxFPS - doEventsDuration; // ms
double workTime = (doEventsDuration / (1 - workLoad)) * workLoad;
workTime = Math.Max(minWorkTime, Math.Min(maxWorkTime, workTime)); // Clamp
nextDoEventsTime = end.AddMilliseconds(workTime);
double fps = 1000 / (doEventsDuration + workTime);
LoggingService.InfoFormatted("Rendering: {0} ms => work budget: {1} ms ({2:f1} FPS)", doEventsDuration, workTime, fps);
}
}
#endregion
#region Maintain expanded state
static Dictionary<string, bool> expandedNodes = new Dictionary<string, bool>();
string FullName {
get {
if (this.Parent != null && this.Parent is TreeViewNode) {
return ((TreeViewNode)this.Parent).FullName + "." + Content.Name;
} else {
return Content.Name;
}
}
}
public void OnExpanded()
{
expandedNodes[FullName] = true;
// Expand children as well
foreach(TreeViewNode child in Children) {
string name = child.FullName;
if (expandedNodes.ContainsKey(name) && expandedNodes[name]) {
child.IsExpanded = true;
}
}
}
public void OnCollapsed()
{
expandedNodes[FullName] = false;
}
#endregion
}
}

30
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ArrayRangeNode.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using ICSharpCode.Core;
using Debugger;
namespace Debugger.AddIn.TreeModel
{
public partial class Util
{
public static IEnumerable<AbstractNode> GetChildNodesOfArray(Expression expression, ArrayDimensions dimensions)
{
foreach(Expression childExpr in expression.AppendIndexers(dimensions)) {
yield return new ExpressionNode(childExpr);
}
}
}
public class ArrayRangeNode
{
}
}

115
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs

@ -0,0 +1,115 @@ @@ -0,0 +1,115 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using ICSharpCode.Core;
using Debugger;
namespace Debugger.AddIn.TreeModel
{
public partial class Util
{
public static IEnumerable<AbstractNode> GetChildNodesOfObject(Expression expression, DebugType shownType)
{
if (shownType.BaseType != null) {
yield return new BaseClassNode(expression, shownType.BaseType);
}
yield return new PrivateMembersNode(expression, shownType);
yield return new StaticMembersNode(expression, shownType);
foreach(Expression childExpr in expression.AppendObjectMembers(shownType, BindingFlags.Public | BindingFlags.Instance)) {
yield return new ExpressionNode(childExpr);
}
}
}
public class BaseClassNode: AbstractNode
{
Expression expression;
DebugType shownType;
public BaseClassNode(Expression expression, DebugType shownType)
{
this.expression = expression;
this.shownType = shownType;
this.Image = DebuggerIcons.ImageList.Images[0]; // Class
this.Name = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.BaseClass}");
this.Type = shownType.FullName;
this.ChildNodes = Util.GetChildNodesOfObject(expression, shownType);
}
}
public class PrivateMembersNode: AbstractNode
{
Expression expression;
DebugType shownType;
public PrivateMembersNode(Expression expression, DebugType shownType)
{
this.expression = expression;
this.shownType = shownType;
this.Name = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.PrivateMembers}");
this.ChildNodes = GetChildNodes();
}
IEnumerable<AbstractNode> GetChildNodes()
{
foreach(Expression childExpr in expression.AppendObjectMembers(shownType, BindingFlags.NonPublic | BindingFlags.Instance)) {
yield return new ExpressionNode(childExpr);
}
}
}
public class StaticMembersNode: AbstractNode
{
Expression expression;
DebugType shownType;
public StaticMembersNode(Expression expression, DebugType shownType)
{
this.expression = expression;
this.shownType = shownType;
this.Name = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.StaticMembers}");
this.ChildNodes = GetChildNodes();
}
IEnumerable<AbstractNode> GetChildNodes()
{
yield return new PrivateStaticMembersNode(expression, shownType);
foreach(Expression childExpr in expression.AppendObjectMembers(shownType, BindingFlags.Public | BindingFlags.Static)) {
yield return new ExpressionNode(childExpr);
}
}
}
public class PrivateStaticMembersNode: AbstractNode
{
Expression expression;
DebugType shownType;
public PrivateStaticMembersNode(Expression expression, DebugType shownType)
{
this.expression = expression;
this.shownType = shownType;
this.Name = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.PrivateStaticMembers}");
this.ChildNodes = GetChildNodes();
}
IEnumerable<AbstractNode> GetChildNodes()
{
foreach(Expression childExpr in expression.AppendObjectMembers(shownType, BindingFlags.NonPublic | BindingFlags.Static)) {
yield return new ExpressionNode(childExpr);
}
}
}
}

127
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ExpressionNode.cs

@ -0,0 +1,127 @@ @@ -0,0 +1,127 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Services;
using Debugger;
namespace Debugger.AddIn.TreeModel
{
public class ExpressionNode: AbstractNode, ISetText, IContextMenu
{
Expression expression;
public Expression Expression {
get { return expression; }
}
public ExpressionNode(Expression expression)
{
this.expression = expression;
Value val = expression.Evaluate(WindowsDebugger.DebuggedProcess.SelectedStackFrame);
if (val.IsObject) {
this.Image = DebuggerIcons.ImageList.Images[0]; // Class
} else {
this.Image = DebuggerIcons.ImageList.Images[1]; // Field
}
this.Name = val.Name;
if (ShowValuesInHexadecimal && val.IsInteger) {
this.Text = String.Format("0x{0:X}", val.PrimitiveValue);
} else {
this.Text = val.AsString;
}
if (val.Type != null) {
this.Type = val.Type.FullName;
} else {
this.Type = String.Empty;
}
// Note that these return enumerators so they are lazy-evaluated
if (val.IsObject) {
this.ChildNodes = Util.GetChildNodesOfObject(this.Expression, val.Type);
} else if (val.IsArray) {
this.ChildNodes = Util.GetChildNodesOfArray(this.Expression, val.ArrayDimensions);
} else {
this.ChildNodes = null;
}
}
public bool SetText(string newText)
{
Value val = null;
try {
val = this.Expression.Evaluate(WindowsDebugger.DebuggedProcess.SelectedStackFrame);
val.PrimitiveValue = newText;
return true;
} catch (NotSupportedException) {
string format = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CannotSetValue.BadFormat");
string msg = String.Format(format, newText, val.Type.ManagedType.ToString());
MessageService.ShowMessage(msg ,"${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}");
} catch (System.Runtime.InteropServices.COMException) {
// COMException (0x80131330): Cannot perfrom SetValue on non-leaf frames.
// Happens if trying to set value after exception is breaked
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.UnknownError}",
"${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}");
}
return false;
}
public ContextMenuStrip GetContextMenu()
{
ContextMenuStrip menu = new ContextMenuStrip();
ToolStripMenuItem copyItem;
copyItem = new ToolStripMenuItem();
copyItem.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CopyToClipboard");
copyItem.Checked = false;
copyItem.Click += delegate {
ClipboardWrapper.SetText(this.Text);
};
ToolStripMenuItem hexView;
hexView = new ToolStripMenuItem();
hexView.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.ShowInHexadecimal");
hexView.Checked = ShowValuesInHexadecimal;
hexView.Click += delegate {
ShowValuesInHexadecimal = !ShowValuesInHexadecimal;
};
menu.Items.AddRange(new ToolStripItem[] {
copyItem,
hexView
});
return menu;
}
public static WindowsDebugger WindowsDebugger {
get {
return (WindowsDebugger)DebuggerService.CurrentDebugger;
}
}
public static bool ShowValuesInHexadecimal {
get {
return WindowsDebugger.Properties.Get("ShowValuesInHexadecimal", false);
}
set {
WindowsDebugger.Properties.Set("ShowValuesInHexadecimal", value);
}
}
}
}

19
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/IContextMenu.cs

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Debugger.AddIn.TreeModel
{
public interface IContextMenu
{
ContextMenuStrip GetContextMenu();
}
}

17
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ISetText.cs

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
namespace Debugger.AddIn.TreeModel
{
public interface ISetText
{
bool SetText(string text);
}
}

38
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using Debugger;
namespace Debugger.AddIn.TreeModel
{
public class StackFrameNode: AbstractNode
{
StackFrame stackFrame;
public StackFrame StackFrame {
get { return stackFrame; }
}
public StackFrameNode(StackFrame stackFrame)
{
this.stackFrame = stackFrame;
this.Name = stackFrame.MethodInfo.Name;
this.ChildNodes = GetChildNodes();
}
IEnumerable<AbstractNode> GetChildNodes()
{
foreach(Expression expr in Expression.MethodVariables(stackFrame.MethodInfo)) {
yield return new ExpressionNode(expr);
}
}
}
}

156
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/BaseTypeItem.cs

@ -1,156 +0,0 @@ @@ -1,156 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
using System.Collections.Generic;
using ICSharpCode.Core;
namespace Debugger
{
public class BaseTypeItem: ListItem
{
Value val;
DebugType type;
public Value Value {
get {
return val;
}
}
public DebugType DebugType {
get {
return type;
}
}
public override int ImageIndex {
get {
return -1;
}
}
public override string Name {
get {
return StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.BaseClass}");
}
}
public override string Text {
get {
return String.Empty;
}
}
public override bool CanEditText {
get {
return false;
}
}
public override string Type {
get {
return type.FullName;
}
}
public override bool HasSubItems {
get {
return true;
}
}
public override IList<ListItem> SubItems {
get {
return GetSubItems();
}
}
public BaseTypeItem(Value val, DebugType type)
{
this.val = val;
this.type = type;
}
List<ListItem> GetMembers(BindingFlags flags)
{
List<ListItem> list = new List<ListItem>();
foreach(Value v in val.GetMembers(type, flags)) {
list.Add(new ValueItem(v));
}
return list;
}
IList<ListItem> GetSubItems()
{
List<ListItem> list = new List<ListItem>();
string privateRes = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.PrivateMembers}");
string staticRes = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.StaticMembers}");
string privateStaticRes = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.PrivateStaticMembers}");
List<ListItem> publicInstance = GetMembers(BindingFlags.Public | BindingFlags.Instance);
List<ListItem> publicStatic = GetMembers(BindingFlags.Public | BindingFlags.Static);
List<ListItem> privateInstance = GetMembers(BindingFlags.NonPublic | BindingFlags.Instance);
List<ListItem> privateStatic = GetMembers(BindingFlags.NonPublic | BindingFlags.Static);
if (type.BaseType != null) {
list.Add(new BaseTypeItem(val, type.BaseType));
}
if (publicStatic.Count > 0) {
list.Add(new FixedItem(-1, staticRes, String.Empty, String.Empty, true, publicStatic));
}
if (privateInstance.Count > 0 || privateStatic.Count > 0) {
List<ListItem> nonPublicItems = new List<ListItem>();
if (privateStatic.Count > 0) {
nonPublicItems.Add(new FixedItem(-1, privateStaticRes, String.Empty, String.Empty, true, privateStatic));
}
nonPublicItems.AddRange(privateInstance);
list.Add(new FixedItem(-1, privateRes, String.Empty, String.Empty, true, nonPublicItems));
}
list.AddRange(publicInstance);
return list;
}
}
}

106
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/FixedItem.cs

@ -1,106 +0,0 @@ @@ -1,106 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
using System.Collections.Generic;
namespace Debugger
{
public class FixedItem: ListItem
{
int imageIndex;
string name;
string text;
string type;
bool hasSubItems;
IList<ListItem> subItems;
public override int ImageIndex {
get {
return imageIndex;
}
}
public override string Name {
get {
return name;
}
}
public override string Text {
get {
return text;
}
}
public override bool CanEditText {
get {
return false;
}
}
public override string Type {
get {
return type;
}
}
public override bool HasSubItems {
get {
return hasSubItems;
}
}
public override IList<ListItem> SubItems {
get {
return subItems;
}
}
public FixedItem(int imageIndex, string name, string text, string type, bool hasSubItems, IList<ListItem> subItems)
{
this.imageIndex = imageIndex;
this.name = name;
this.text = text;
this.type = type;
this.hasSubItems = hasSubItems;
this.subItems = subItems;
}
}
}

85
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/ListItem.cs

@ -1,85 +0,0 @@ @@ -1,85 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Debugger
{
public abstract class ListItem
{
public event EventHandler<ListItemEventArgs> Changed;
public abstract int ImageIndex { get; }
public abstract string Name { get; }
public abstract string Text { get; }
public abstract bool CanEditText { get; }
public abstract string Type { get; }
public abstract bool HasSubItems { get; }
public abstract IList<ListItem> SubItems { get; }
public System.Drawing.Image Image {
get {
if (ImageIndex == -1) {
return null;
} else {
return DebuggerIcons.ImageList.Images[ImageIndex];
}
}
}
protected virtual void OnChanged(ListItemEventArgs e)
{
if (Changed != null) {
Changed(this, e);
}
}
public virtual bool SetText(string newValue)
{
throw new NotImplementedException();
}
public virtual ContextMenuStrip GetContextMenu()
{
return null;
}
}
}

59
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/ListItemEventArgs.cs

@ -1,59 +0,0 @@ @@ -1,59 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
namespace Debugger
{
public class ListItemEventArgs: EventArgs
{
ListItem listItem;
public ListItem ListItem {
get {
return listItem;
}
}
public ListItemEventArgs(ListItem listItem)
{
this.listItem = listItem;
}
}
}

109
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/StackFrameItem.cs

@ -1,109 +0,0 @@ @@ -1,109 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
using System.Collections.Generic;
namespace Debugger
{
public class StackFrameItem: ListItem
{
StackFrame stackFrame;
public StackFrame StackFrame {
get {
return stackFrame;
}
}
public override int ImageIndex {
get {
return -1;
}
}
public override string Name {
get {
return stackFrame.MethodInfo.Name;
}
}
public override string Text {
get {
return String.Empty;
}
}
public override bool CanEditText {
get {
return false;
}
}
public override string Type {
get {
return String.Empty;
}
}
public override bool HasSubItems {
get {
return true;
}
}
public override IList<ListItem> SubItems {
get {
List<ListItem> ret = new List<ListItem>();
foreach(Value val in stackFrame.LocalVariables) {
ret.Add(new ValueItem(val));
}
return ret.AsReadOnly();
}
}
public StackFrameItem(StackFrame stackFrame)
{
this.stackFrame = stackFrame;
this.stackFrame.Process.DebuggeeStateChanged += delegate {
this.OnChanged(new ListItemEventArgs(this));
};
}
}
}

229
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/TreeViewNode.cs

@ -1,229 +0,0 @@ @@ -1,229 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Windows.Forms;
using Aga.Controls.Tree;
using ICSharpCode.Core;
namespace Debugger
{
public partial class TreeViewNode: TreeNodeAdv
{
ListItem content;
Image icon;
string name;
string text;
bool canEditText;
string type;
public ListItem Content {
get {
return content;
}
set {
if (content != null) {
content.Changed -= OnContentChanged;
}
content = value;
if (content != null) {
content.Changed += OnContentChanged;
}
Update();
}
}
public Image Icon {
get { return icon; }
}
public string Name {
get { return name; }
}
public string Text {
get { return text; }
}
public bool CanEditText {
get { return canEditText; }
}
public string Type {
get { return type; }
}
void OnContentChanged(object sender, ListItemEventArgs e)
{
//Update();
}
public TreeViewNode(TreeViewAdv tree, ListItem content): base(tree, new object())
{
this.Content = content;
}
public void Update()
{
DoApplicationEvents();
DateTime start = Debugger.Util.HighPrecisionTimer.Now;
this.IsLeaf = !Content.HasSubItems;
this.icon = content.Image;
this.name = content.Name;
this.text = content.Text;
this.canEditText = content.CanEditText;
this.type = content.Type;
//DateTime time = Debugger.Util.HighPrecisionTimer.Now;
//this.type = time.ToLongTimeString() + "." + time.Millisecond.ToString();
DateTime end = Debugger.Util.HighPrecisionTimer.Now;
LoggingService.InfoFormatted("Updated node {0} ({1} ms)", FullName, (end - start).TotalMilliseconds);
if (this.IsExpanded) {
UpdateNodes(Tree, this.Children, Content.SubItems);
} else {
Children.Clear();
populated = false;
}
this.Tree.FullUpdate();
}
public static void UpdateNodes(TreeViewAdv tree, Collection<TreeNodeAdv> collection, IList<ListItem> contents)
{
// Add or overwrite existing items
for(int i = 0; i < contents.Count; i++) {
if (i < collection.Count) {
// Overwrite
((TreeViewNode)collection[i]).Content = contents[i];
} else {
// Add
collection.Add(new TreeViewNode(tree, contents[i]));
}
}
// Delete other nodes
while(collection.Count > contents.Count) {
collection.RemoveAt(collection.Count - 1);
}
tree.FullUpdate();
}
bool populated = false;
public void OnExpanding()
{
if (!populated) {
foreach(ListItem item in Content.SubItems) {
Children.Add(new TreeViewNode(Tree, item));
}
populated = true;
this.IsExpandedOnce = true;
this.Tree.UpdateSelection();
this.Tree.FullUpdate();
}
}
#region DoApplicationEvents()
static DateTime nextDoEventsTime = Debugger.Util.HighPrecisionTimer.Now;
const double workLoad = 0.75; // Fraction of getting variables vs. repainting
const double maxFPS = 30; // ms this prevents too much drawing on good machine
const double maxWorkTime = 250; // ms this ensures minimal response on bad machine
void DoApplicationEvents()
{
if (Debugger.Util.HighPrecisionTimer.Now > nextDoEventsTime) {
DateTime start = Debugger.Util.HighPrecisionTimer.Now;
Application.DoEvents();
DateTime end = Debugger.Util.HighPrecisionTimer.Now;
double doEventsDuration = (end - start).TotalMilliseconds;
double minWorkTime = 1000 / maxFPS - doEventsDuration; // ms
double workTime = (doEventsDuration / (1 - workLoad)) * workLoad;
workTime = Math.Max(minWorkTime, Math.Min(maxWorkTime, workTime)); // Clamp
nextDoEventsTime = end.AddMilliseconds(workTime);
double fps = 1000 / (doEventsDuration + workTime);
LoggingService.InfoFormatted("Rendering: {0} ms => work budget: {1} ms ({2:f1} FPS)", doEventsDuration, workTime, fps);
}
}
#endregion
#region Maintain expanded state
static Dictionary<string, bool> expandedNodes = new Dictionary<string, bool>();
string FullName {
get {
if (this.Parent != null && this.Parent is TreeViewNode) {
return ((TreeViewNode)this.Parent).FullName + "." + Content.Name;
} else {
return Content.Name;
}
}
}
public void OnExpanded()
{
expandedNodes[FullName] = true;
// Expand children as well
foreach(TreeViewNode child in Children) {
string name = child.FullName;
if (expandedNodes.ContainsKey(name) && expandedNodes[name]) {
child.IsExpanded = true;
}
}
}
public void OnCollapsed()
{
expandedNodes[FullName] = false;
}
#endregion
}
}

184
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/ValueItem.cs

@ -1,184 +0,0 @@ @@ -1,184 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Services;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger
{
class ValueItem: ListItem
{
Value val;
public Value Value {
get {
return val;
}
}
public static bool ShowValuesInHexadecimal {
get {
return ((WindowsDebugger)DebuggerService.CurrentDebugger).Properties.Get("ShowValuesInHexadecimal", false);
}
set {
((WindowsDebugger)DebuggerService.CurrentDebugger).Properties.Set("ShowValuesInHexadecimal", value);
}
}
public override int ImageIndex {
get {
if (val.IsObject) {
return 0; // Class
} else {
return 1; // Field
}
}
}
public override string Name {
get {
return val.Name;
}
}
public override string Text {
get {
if (ShowValuesInHexadecimal && val.IsInteger) {
return String.Format("0x{0:X}", val.PrimitiveValue);
} else {
return val.AsString;
}
}
}
public override bool CanEditText {
get {
return val.IsInteger && !ShowValuesInHexadecimal;
}
}
public override string Type {
get {
if (val.Type != null) {
return val.Type.FullName;
} else {
return String.Empty;
}
}
}
public override bool HasSubItems {
get {
return val.IsObject || val.IsArray;
}
}
public override IList<ListItem> SubItems {
get {
List<ListItem> list = new List<ListItem>();
if (val.IsArray) {
foreach(Value element in val.GetArrayElements()) {
list.Add(new ValueItem(element));
}
}
if (val.IsObject) {
return new BaseTypeItem(val, val.Type).SubItems;
}
return list;
}
}
public ValueItem(Value val)
{
this.val = val;
}
public override bool SetText(string newValue)
{
try {
val.PrimitiveValue = newValue;
return true;
} catch (NotSupportedException) {
string format = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CannotSetValue.BadFormat");
string msg = String.Format(format, newValue, val.Type.ManagedType.ToString());
MessageService.ShowMessage(msg ,"${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}");
} catch (COMException) {
// COMException (0x80131330): Cannot perfrom SetValue on non-leaf frames.
// Happens if trying to set value after exception is breaked
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.UnknownError}",
"${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}");
}
return false;
}
public override ContextMenuStrip GetContextMenu()
{
ContextMenuStrip menu = new ContextMenuStrip();
ToolStripMenuItem copyItem;
copyItem = new ToolStripMenuItem();
copyItem.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CopyToClipboard");
copyItem.Checked = false;
copyItem.Click += delegate {
ClipboardWrapper.SetText(this.Text);
};
ToolStripMenuItem hewView;
hewView = new ToolStripMenuItem();
hewView.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.ShowInHexadecimal");
hewView.Checked = ShowValuesInHexadecimal;
hewView.Click += delegate {
ShowValuesInHexadecimal = !ShowValuesInHexadecimal;
};
menu.Items.AddRange(new ToolStripItem[] {
copyItem,
hewView
});
return menu;
}
}
}

16
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Expressions/Expression.Evaluate.cs

@ -17,21 +17,9 @@ namespace Debugger @@ -17,21 +17,9 @@ namespace Debugger
{
public partial class Expression: DebuggerObject
{
public Value Evaluate(Process process)
public Value Evaluate(StackFrame context)
{
if (process != null &&
process.SelectedThread != null &&
process.SelectedThread.SelectedStackFrame != null)
{
return Evaluate(process.SelectedThread.SelectedStackFrame);
} else {
return null;
}
}
public Value Evaluate(StackFrame stackFrame)
{
EvaluateAstVisitor astVisitor = new EvaluateAstVisitor(stackFrame);
EvaluateAstVisitor astVisitor = new EvaluateAstVisitor(context);
return (Value)this.AbstractSynatxTree.AcceptVisitor(astVisitor, null);
}
}

Loading…
Cancel
Save