Browse Source

Using Andrey Gliznetsov's Advanced TreeView for Local Variables Pad

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2311 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 19 years ago
parent
commit
18fc86e2b7
  1. 13
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
  2. 37
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/DebuggerTreeListView.cs
  3. 153
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs
  4. 88
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/TreeListViewDebuggerItem.cs
  5. 77
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/FunctionItem.cs
  6. 197
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/TreeViewNode.cs
  7. 17
      src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeNodeAdv.cs
  8. 6
      src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeViewAdv.cs

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

@ -58,7 +58,6 @@ @@ -58,7 +58,6 @@
</EmbeddedResource>
<Compile Include="Src\Service\DynamicTreeDebuggerRow.cs" />
<Compile Include="Src\Service\SetCurrentStatementCommand.cs" />
<Compile Include="Src\Pads\TreeListViewDebuggerItem.cs" />
<Compile Include="Src\Service\DebuggerIcons.cs" />
<Compile Include="..\..\..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Configuration\GlobalAssemblyInfo.cs</Link>
@ -66,11 +65,12 @@ @@ -66,11 +65,12 @@
<Compile Include="Src\Pads\DebuggerPad.cs" />
<Compile Include="Src\Pads\CallStackPad.Menu.cs" />
<Compile Include="Src\Pads\RunningThreadsPad.Menu.cs" />
<Compile Include="Src\Pads\DebuggerTreeListView.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\FunctionItem.cs" />
<Compile Include="Src\Variables\TreeViewNode.cs" />
<Compile Include="Src\Variables\ValueItem.cs" />
</ItemGroup>
<ItemGroup>
@ -104,11 +104,6 @@ @@ -104,11 +104,6 @@
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</ProjectReference>
<ProjectReference Include="..\..\TreeListView\Project\TreeListView.csproj">
<Project>{B08385CD-F0CC-488C-B4F4-EEB34B6D2688}</Project>
<Name>TreeListView</Name>
<Private>False</Private>
</ProjectReference>
<Content Include="PostBuildEvent.proj" />
<ProjectReference Include="..\..\..\..\..\Main\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj">
<Project>{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}</Project>
@ -123,6 +118,10 @@ @@ -123,6 +118,10 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Src\Variables" />
<ProjectReference Include="..\..\..\..\..\Libraries\TreeViewAdv\Aga.Controls\Aga.Controls.csproj">
<Project>{E73BB233-D88B-44A7-A98F-D71EE158381D}</Project>
<Name>Aga.Controls</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
<Import Project="PostBuildEvent.proj" />

37
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/DebuggerTreeListView.cs

@ -1,37 +0,0 @@ @@ -1,37 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Forms;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class DebuggerTreeListView: TreeListView
{
static int updateInterval = 100; // ms
Timer refreshingTimer;
public DebuggerTreeListView()
{
refreshingTimer = new Timer();
refreshingTimer.Interval = updateInterval;
refreshingTimer.Tick += delegate {
refreshingTimer.Enabled = false;
this.EndUpdate();
};
}
public void DelayRefresh()
{
if (!refreshingTimer.Enabled) {
this.BeginUpdate();
refreshingTimer.Enabled = true;
}
}
}
}

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

@ -6,22 +6,66 @@ @@ -6,22 +6,66 @@
// </file>
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using ICSharpCode.Core;
using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using Debugger;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class LocalVarPad : DebuggerPad
{
DebuggerTreeListView localVarList;
class ItemIcon: NodeIcon {
protected override System.Drawing.Image GetIcon(TreeNodeAdv node)
{
return ((TreeViewNode)node).Icon;
}
}
class ItemName: NodeTextBox {
protected override bool CanEdit(TreeNodeAdv node)
{
return false;
}
public override object GetValue(TreeNodeAdv node)
{
return ((TreeViewNode)node).Name;
}
}
class ItemText: NodeTextBox {
protected override bool CanEdit(TreeNodeAdv node)
{
return ((TreeViewNode)node).CanEditText;
}
public override object GetValue(TreeNodeAdv node)
{
return ((TreeViewNode)node).Text;
}
}
class ItemType: NodeTextBox {
protected override bool CanEdit(TreeNodeAdv node)
{
return false;
}
public override object GetValue(TreeNodeAdv node)
{
return ((TreeViewNode)node).Type;
}
}
TreeViewAdv localVarList;
Debugger.Process debuggedProcess;
ColumnHeader name = new ColumnHeader();
ColumnHeader val = new ColumnHeader();
ColumnHeader type = new ColumnHeader();
TreeColumn nameColumn = new TreeColumn();
TreeColumn valColumn = new TreeColumn();
TreeColumn typeColumn = new TreeColumn();
public override Control Control {
get {
@ -31,39 +75,53 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -31,39 +75,53 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
protected override void InitializeComponents()
{
//iconsService = (ClassBrowserIconsService)ServiceManager.Services.GetService(typeof(ClassBrowserIconsService));
localVarList = new DebuggerTreeListView();
localVarList.SmallImageList = DebuggerIcons.ImageList;
localVarList.ShowPlusMinus = true;
localVarList.FullRowSelect = true;
localVarList.Dock = DockStyle.Fill;
localVarList.Sorting = SortOrder.Ascending;
//localVarList.GridLines = false;
//localVarList.Activation = ItemActivation.OneClick;
localVarList.Columns.AddRange(new ColumnHeader[] {name, val, type} );
name.Width = 250;
val.Width = 300;
type.Width = 250;
localVarList.Visible = false;
localVarList.SizeChanged += new EventHandler(localVarList_SizeChanged);
localVarList.BeforeExpand += new TreeListViewCancelEventHandler(localVarList_BeforeExpand);
localVarList.AfterExpand += new TreeListViewEventHandler(localVarList_AfterExpand);
localVarList = new TreeViewAdv();
localVarList.Columns.Add(nameColumn);
localVarList.Columns.Add(valColumn);
localVarList.Columns.Add(typeColumn);
localVarList.UseColumns = true;
localVarList.SelectionMode = TreeSelectionMode.Single;
localVarList.LoadOnDemand = true;
localVarList.VisibleChanged += delegate { if (localVarList.Visible) RefreshPad(); };
localVarList.SizeChanged += delegate { RefreshPad(); };
localVarList.Expanding += delegate(object sender, TreeViewAdvEventArgs e) {
if (e.Node is TreeViewNode) ((TreeViewNode)e.Node).OnExpanding();
};
localVarList.Expanded += delegate(object sender, TreeViewAdvEventArgs e) {
if (e.Node is TreeViewNode) ((TreeViewNode)e.Node).OnExpanded();
};
localVarList.Collapsed += delegate(object sender, TreeViewAdvEventArgs e) {
if (e.Node is TreeViewNode) ((TreeViewNode)e.Node).OnCollapsed();
};
NodeIcon iconControl = new ItemIcon();
iconControl.ParentColumn = nameColumn;
localVarList.NodeControls.Add(iconControl);
NodeTextBox nameControl = new ItemName();
nameControl.ParentColumn = nameColumn;
localVarList.NodeControls.Add(nameControl);
NodeTextBox textControl = new ItemText();
textControl.ParentColumn = valColumn;
localVarList.NodeControls.Add(textControl);
NodeTextBox typeControl = new ItemType();
typeControl.ParentColumn = typeColumn;
localVarList.NodeControls.Add(typeControl);
RedrawContent();
}
public override void RedrawContent()
{
name.Text = ResourceService.GetString("Global.Name");
val.Text = ResourceService.GetString("Dialog.HighlightingEditor.Properties.Value");
type.Text = ResourceService.GetString("ResourceEditor.ResourceEdit.TypeColumn");
}
// This is a walkarond for a visual issue
void localVarList_SizeChanged(object sender, EventArgs e)
{
localVarList.Visible = true;
nameColumn.Header = ResourceService.GetString("Global.Name");
nameColumn.Width = 250;
valColumn.Header = ResourceService.GetString("Dialog.HighlightingEditor.Properties.Value");
valColumn.Width = 300;
typeColumn.Header = ResourceService.GetString("ResourceEditor.ResourceEdit.TypeColumn");
typeColumn.Width = 250;
}
protected override void SelectProcess(Debugger.Process process)
@ -85,37 +143,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -85,37 +143,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
public override void RefreshPad()
{
localVarList.BeginUpdate();
localVarList.Items.Clear();
if (debuggedProcess != null) {
foreach(NamedValue val in debuggedProcess.LocalVariables) {
localVarList.Items.Add(new TreeListViewDebuggerItem(val));
}
}
localVarList.EndUpdate();
}
void localVarList_BeforeExpand(object sender, TreeListViewCancelEventArgs e)
{
if (debuggedProcess.IsPaused) {
((TreeListViewDebuggerItem)e.Item).Populate();
DateTime start = Debugger.Util.HighPrecisionTimer.Now;
if (debuggedProcess != null && debuggedProcess.SelectedFunction != null) {
TreeViewNode.UpdateNodes(localVarList, localVarList.Root.Children, new FunctionItem(debuggedProcess.SelectedFunction).SubItems);
} else {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.LocalVariables.CannotExploreVariablesWhileRunning}");
e.Cancel = true;
}
}
void localVarList_AfterExpand(object sender, TreeListViewEventArgs e)
{
UpdateSubTree(e.Item);
}
static void UpdateSubTree(TreeListViewItem tree)
{
foreach(TreeListViewItem item in tree.Items) {
((TreeListViewDebuggerItem)item).Update();
if (item.IsExpanded) UpdateSubTree(item);
TreeViewNode.UpdateNodes(localVarList, localVarList.Root.Children, new ListItem[0]);
}
DateTime end = Debugger.Util.HighPrecisionTimer.Now;
LoggingService.InfoFormatted("Local Variables pad refreshed ({0} ms)", (end - start).TotalMilliseconds);
}
}
}

88
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/TreeListViewDebuggerItem.cs

@ -1,88 +0,0 @@ @@ -1,88 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Drawing;
using System.Windows.Forms;
using Debugger;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class TreeListViewDebuggerItem: TreeListViewItem
{
ListItem listItem;
bool populated = false;
public ListItem ListItem {
get {
return listItem;
}
}
bool IsVisible {
get {
if (this.Parent == null) {
return true;
} else {
foreach(TreeListViewItem parent in this.ParentsInHierarch) {
if (!parent.IsExpanded) return false;
}
return true;
}
}
}
public TreeListViewDebuggerItem(NamedValue val): this(new ValueItem(val))
{
}
public TreeListViewDebuggerItem(ListItem listItem)
{
this.listItem = listItem;
listItem.Changed += delegate { Update(); };
SubItems.Add("");
SubItems.Add("");
Update();
}
public void Update()
{
if (!IsVisible) return;
if (this.TreeListView != null) {
((DebuggerTreeListView)this.TreeListView).DelayRefresh();
}
this.ImageIndex = listItem.ImageIndex;
this.SubItems[0].Text = listItem.Name;
this.SubItems[1].Text = listItem.Text;
this.SubItems[2].Text = listItem.Type;
if (!IsExpanded && !populated && listItem.HasSubItems) {
Items.Add(new TreeListViewItem()); // Show plus sign
}
}
public void Populate()
{
if (!populated) {
Items.Clear();
this.Items.SortOrder = SortOrder.None;
foreach(ListItem subItem in listItem.SubItems) {
Items.Add(new TreeListViewDebuggerItem(subItem));
}
populated = true;
}
}
}
}

77
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/FunctionItem.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
namespace Debugger
{
public class FunctionItem: ListItem
{
Function function;
public Function Function {
get {
return function;
}
}
public override int ImageIndex {
get {
return -1;
}
}
public override string Name {
get {
return function.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(NamedValue val in function.LocalVariables) {
ret.Add(new ValueItem(val));
}
return ret.AsReadOnly();
}
}
public FunctionItem(Function function)
{
this.function = function;
this.function.Process.DebuggeeStateChanged += delegate {
this.OnChanged(new ListItemEventArgs(this));
};
}
}
}

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

@ -0,0 +1,197 @@ @@ -0,0 +1,197 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <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
{
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
}
}

17
src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeNodeAdv.cs

@ -10,7 +10,7 @@ using System.Security.Permissions; @@ -10,7 +10,7 @@ using System.Security.Permissions;
namespace Aga.Controls.Tree
{
[Serializable]
public sealed class TreeNodeAdv: ISerializable
public class TreeNodeAdv: ISerializable
{
#region NodeCollection
//TODO: use one common Parent-Children collection
@ -61,12 +61,12 @@ namespace Aga.Controls.Tree @@ -61,12 +61,12 @@ namespace Aga.Controls.Tree
#endregion
private Collection<TreeNodeAdv> _nodes;
private ReadOnlyCollection<TreeNodeAdv> _children;
private Collection<TreeNodeAdv> _children;
#region Properties
private TreeViewAdv _tree;
internal TreeViewAdv Tree
public TreeViewAdv Tree
{
get { return _tree; }
}
@ -121,14 +121,14 @@ namespace Aga.Controls.Tree @@ -121,14 +121,14 @@ namespace Aga.Controls.Tree
public bool IsLeaf
{
get { return _isLeaf; }
internal set { _isLeaf = value; }
set { _isLeaf = value; }
}
private bool _isExpandedOnce;
public bool IsExpandedOnce
{
get { return _isExpandedOnce; }
internal set { _isExpandedOnce = value; }
set { _isExpandedOnce = value; }
}
private bool _isExpanded;
@ -217,6 +217,7 @@ namespace Aga.Controls.Tree @@ -217,6 +217,7 @@ namespace Aga.Controls.Tree
public object Tag
{
get { return _tag; }
set { _tag = value; }
}
internal Collection<TreeNodeAdv> Nodes
@ -224,7 +225,7 @@ namespace Aga.Controls.Tree @@ -224,7 +225,7 @@ namespace Aga.Controls.Tree
get { return _nodes; }
}
public ReadOnlyCollection<TreeNodeAdv> Children
public Collection<TreeNodeAdv> Children
{
get
{
@ -238,12 +239,12 @@ namespace Aga.Controls.Tree @@ -238,12 +239,12 @@ namespace Aga.Controls.Tree
{
}
internal TreeNodeAdv(TreeViewAdv tree, object tag)
public TreeNodeAdv(TreeViewAdv tree, object tag)
{
_row = -1;
_tree = tree;
_nodes = new NodeCollection(this);
_children = new ReadOnlyCollection<TreeNodeAdv>(_nodes);
_children = _nodes;
_tag = tag;
}

6
src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeViewAdv.cs

@ -466,7 +466,7 @@ namespace Aga.Controls.Tree @@ -466,7 +466,7 @@ namespace Aga.Controls.Tree
return Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
}
internal void FullUpdate()
public void FullUpdate()
{
_rowLayout.ClearCache();
CreateRowMap();
@ -475,7 +475,7 @@ namespace Aga.Controls.Tree @@ -475,7 +475,7 @@ namespace Aga.Controls.Tree
_needFullUpdate = false;
}
internal void UpdateView()
public void UpdateView()
{
if (!_suspendUpdate)
Invalidate(false);
@ -648,7 +648,7 @@ namespace Aga.Controls.Tree @@ -648,7 +648,7 @@ namespace Aga.Controls.Tree
return node == _root;
}
private void UpdateSelection()
public void UpdateSelection()
{
bool flag = false;

Loading…
Cancel
Save