1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.Collections.Generic;
6
using System.Collections.ObjectModel;
7
using System.ComponentModel;
10
using System.Windows.Controls;
11
using System.Windows.Documents;
13
using ICSharpCode.Profiler.Controller.Data;
15
namespace ICSharpCode.Profiler.Controls
17
public class CallTreeNodeViewModel : IViewModel<CallTreeNodeViewModel>, INotifyPropertyChanged
19
#region INotifyPropertyChanged Member
21
public event PropertyChangedEventHandler PropertyChanged;
23
protected void OnPropertyChanged(string name)
25
if (this.PropertyChanged != null)
27
PropertyChanged(this, new PropertyChangedEventArgs(name));
33
ReadOnlyCollection<CallTreeNodeViewModel> children;
34
protected readonly CallTreeNode node;
35
CallTreeNodeViewModel parent;
38
public CallTreeNode Node { get { return node; } }
40
public event EventHandler<NodeEventArgs<CallTreeNodeViewModel>> VisibleChildExpandedChanged;
41
public event EventHandler<NodeEventArgs<CallTreeNodeViewModel>> RequestBringIntoView;
43
protected virtual void OnRequestBringIntoView(NodeEventArgs<CallTreeNodeViewModel> e)
45
if (RequestBringIntoView != null) {
46
RequestBringIntoView(this, e);
50
protected virtual void OnVisibleChildExpandedChanged(NodeEventArgs<CallTreeNodeViewModel> e)
52
if (VisibleChildExpandedChanged != null) {
53
VisibleChildExpandedChanged(this, e);
57
public void BringIntoView()
62
void BringIntoView(CallTreeNodeViewModel item)
64
if (this.parent != null) {
65
parent.BringIntoView(item);
68
OnRequestBringIntoView(new NodeEventArgs<CallTreeNodeViewModel>(item));
74
set { level = value; }
77
public CallTreeNodeViewModel Parent
79
get { return parent; }
82
public virtual long CpuCyclesSpent
85
return node.CpuCyclesSpent;
89
public virtual double TimePercentageOfParent
92
if (this.parent == null)
95
return (double)this.node.CpuCyclesSpent / (double)this.parent.node.CpuCyclesSpent;
99
public Visibility HotPathIndicatorVisibility {
101
if (TimePercentageOfParent >= 0.2)
102
return Visibility.Visible;
104
return Visibility.Collapsed;
108
public virtual string TimePercentageOfParentAsText
111
return (TimePercentageOfParent * 100).ToString("0.00") + "%";
115
public virtual object ToolTip
117
get { return CreateShortToolTip(); }
120
object CreateShortToolTip()
123
return null; // no tooltip for root
127
TextBlock text = new TextBlock {
129
((!string.IsNullOrEmpty(node.ReturnType)) ? node.ReturnType + " " : ""),
130
new Bold { Inlines = { node.Name } },
131
"(" + ((node.Parameters.Count > 0) ? string.Join(", ", node.Parameters.ToArray()) : "") + ")"
138
public object CreateToolTip(ControlsTranslation translation)
141
return Name; // only name for threads
143
TextBlock text = new TextBlock
146
((!string.IsNullOrEmpty(node.ReturnType)) ? node.ReturnType + " " : ""),
147
new Bold { Inlines = { node.Name } },
148
"(" + ((node.Parameters.Count > 0) ? string.Join(", ", node.Parameters.ToArray()) : "") + ")\n",
149
new Bold { Inlines = { translation.CpuCyclesText } },
150
" " + node.CpuCyclesSpent + "\n",
151
new Bold { Inlines = { translation.TimeText } },
152
" " + node.TimeSpent.ToString("f6") + "ms\n",
153
new Bold { Inlines = { translation.CallsText } },
154
" " + node.CallCount.ToString()
161
public string GetSignature()
165
return node.Signature;
168
public ReadOnlyCollection<string> Parameters
171
return new ReadOnlyCollection<string>(this.node.Parameters);
175
public CallTreeNodeViewModel(CallTreeNode node, CallTreeNodeViewModel parent)
178
throw new ArgumentNullException("node");
180
this.parent = parent;
181
this.level = (this.parent == null) ? 1 : this.parent.level + 1;
184
public bool IsAncestorOf(CallTreeNodeViewModel descendant)
186
if (this != descendant) {
187
if (descendant == null)
190
return IsAncestorOf(descendant.Parent);
196
public virtual ReadOnlyCollection<CallTreeNodeViewModel> Children {
199
if (this.children == null) {
201
this.children = this.node.Children
202
.Select(c => new CallTreeNodeViewModel(c, this))
207
return this.children;
212
public virtual string Name
215
return this.node.Name ?? string.Empty;
219
public virtual string FullyQualifiedClassName
222
string nodeName = this.node.Name;
223
if (string.IsNullOrEmpty(nodeName))
225
if (!nodeName.Contains("."))
227
int index = nodeName.LastIndexOf('.');
228
if (nodeName[index - 1] == '.')
230
return nodeName.Substring(0, index);
234
public virtual string MethodName
237
string nodeName = this.node.Name;
238
if (string.IsNullOrEmpty(nodeName))
240
if (!nodeName.Contains("."))
242
int index = nodeName.LastIndexOf('.');
243
if (nodeName[index - 1] == '.')
245
return nodeName.Substring(index + 1);
249
public virtual string ShortName
252
string className = this.FullyQualifiedClassName;
253
if (className == null)
255
int index = className.LastIndexOf('.');
256
return className.Substring(index + 1) + "." + MethodName;
262
public bool IsExpanded {
263
get { return isExpanded; }
265
if (isExpanded != value) {
267
OnPropertyChanged("IsExpanded");
268
this.IsExpandedChanged(new NodeEventArgs<CallTreeNodeViewModel>(this));
271
DeselectChildren(children);
277
void DeselectChildren(IList<CallTreeNodeViewModel> children)
279
foreach (CallTreeNodeViewModel item in children) {
280
item.IsSelected = false;
282
DeselectChildren(item.Children);
286
void IsExpandedChanged(NodeEventArgs<CallTreeNodeViewModel> e)
288
this.visibleElementCount = 1 + (IsExpanded ? Children.Sum(c => c.VisibleElementCount) : 0);
289
OnVisibleChildExpandedChanged(e);
291
if (Parent != null && Parent.IsExpanded) {
292
Parent.IsExpandedChanged(e);
296
/*void IsSelectedChanged(CallTreeNodeViewModel item)
299
Parent.IsSelectedChanged(item);
301
OnChildSelectedChanged(new CallTreeNodeViewModelEventArgs(item));
304
protected virtual void OnChildSelectedChanged(CallTreeNodeViewModelEventArgs eventArgs)
306
if (ChildSelectedChanged != null)
307
ChildSelectedChanged(this, eventArgs);
312
public bool IsSelected {
313
get { return isSelected; }
315
if (isSelected != value) {
317
OnPropertyChanged("IsSelected");
318
//this.IsSelectedChanged(this);
321
CallTreeNodeViewModel node = this.Parent;
322
while (node != null) {
323
node.IsExpanded = true;
331
public string TimeSpent {
334
return node.TimeSpent.ToString("f6") + "ms";
340
public string TimeSpentSelf {
343
return node.TimeSpentSelf.ToString("f6") + "ms";
349
public string TimeSpentSelfPerCall {
352
return (node.TimeSpentSelf / node.CallCount).ToString("f6") + "ms";
358
public string TimeSpentPerCall {
361
return (node.TimeSpent / node.CallCount).ToString("f6") + "ms";
367
public string CallCount {
370
return node.CallCount.ToString();
376
public Visibility CheckBoxVisibility
379
if (node.HasChildren)
380
return Visibility.Visible;
382
return Visibility.Hidden;
386
public override string ToString()
388
return "[" + Name + "]";
391
#region IViewModel<CallTreeNodeViewModel> Member
392
int visibleElementCount = 1;
394
public virtual int VisibleElementCount
397
return this.visibleElementCount;
401
public virtual Thickness IndentationMargin {
403
return new Thickness((level - 1) * 12, 0, 2, 0);