Browse Source
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-cef0b8235c61shortcuts
22 changed files with 701 additions and 1122 deletions
@ -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. |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; } |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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
|
||||
} |
||||
} |
@ -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 |
||||
{ |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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)); |
||||
}; |
||||
} |
||||
} |
||||
} |
@ -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
|
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue