diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
index 4da39c6ba2..b00fb63f24 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
@@ -58,7 +58,6 @@
-
Configuration\GlobalAssemblyInfo.cs
@@ -66,11 +65,12 @@
-
+
+
@@ -104,11 +104,6 @@
False
False
-
- {B08385CD-F0CC-488C-B4F4-EEB34B6D2688}
- TreeListView
- False
-
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}
@@ -123,6 +118,10 @@
+
+ {E73BB233-D88B-44A7-A98F-D71EE158381D}
+ Aga.Controls
+
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/DebuggerTreeListView.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/DebuggerTreeListView.cs
deleted file mode 100644
index 34e7b05a10..0000000000
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/DebuggerTreeListView.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-//
-//
-//
-// $Revision$
-//
-
-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;
- }
- }
- }
-}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs
index d1923d11a2..24df9ebdae 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs
@@ -6,22 +6,66 @@
//
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
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
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);
}
}
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/TreeListViewDebuggerItem.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/TreeListViewDebuggerItem.cs
deleted file mode 100644
index bf39a4b99d..0000000000
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/TreeListViewDebuggerItem.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-//
-//
-//
-// $Revision$
-//
-
-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;
- }
- }
- }
-}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/FunctionItem.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/FunctionItem.cs
new file mode 100644
index 0000000000..bcf980e4cc
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/FunctionItem.cs
@@ -0,0 +1,77 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+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 SubItems {
+ get {
+ List ret = new List();
+ 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));
+ };
+ }
+ }
+}
diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/TreeViewNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/TreeViewNode.cs
new file mode 100644
index 0000000000..c043a36c66
--- /dev/null
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Variables/TreeViewNode.cs
@@ -0,0 +1,197 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+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 collection, IList 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 expandedNodes = new Dictionary();
+
+ 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
+ }
+}
diff --git a/src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeNodeAdv.cs b/src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeNodeAdv.cs
index c6356275a4..8c2da110fe 100644
--- a/src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeNodeAdv.cs
+++ b/src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeNodeAdv.cs
@@ -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
#endregion
private Collection _nodes;
- private ReadOnlyCollection _children;
+ private Collection _children;
#region Properties
private TreeViewAdv _tree;
- internal TreeViewAdv Tree
+ public TreeViewAdv Tree
{
get { return _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
public object Tag
{
get { return _tag; }
+ set { _tag = value; }
}
internal Collection Nodes
@@ -224,7 +225,7 @@ namespace Aga.Controls.Tree
get { return _nodes; }
}
- public ReadOnlyCollection Children
+ public Collection Children
{
get
{
@@ -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(_nodes);
+ _children = _nodes;
_tag = tag;
}
diff --git a/src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeViewAdv.cs b/src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeViewAdv.cs
index e391885866..9ea9cdb450 100644
--- a/src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeViewAdv.cs
+++ b/src/Libraries/TreeViewAdv/Aga.Controls/Tree/TreeViewAdv.cs
@@ -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
_needFullUpdate = false;
}
- internal void UpdateView()
+ public void UpdateView()
{
if (!_suspendUpdate)
Invalidate(false);
@@ -648,7 +648,7 @@ namespace Aga.Controls.Tree
return node == _root;
}
- private void UpdateSelection()
+ public void UpdateSelection()
{
bool flag = false;