Browse Source

Work on TreeView.

pull/1/head
Daniel Grunwald 14 years ago
parent
commit
fd0c9cfe7d
  1. 38
      ILSpy/AssemblyListTreeNode.cs
  2. 106
      ILSpy/AssemblyTreeNode.cs
  3. 47
      ILSpy/FieldTreeNode.cs
  4. 3
      ILSpy/ILSpy.csproj
  5. 2
      ILSpy/MainWindow.xaml
  6. 23
      ILSpy/MainWindow.xaml.cs
  7. 45
      ILSpy/MethodTreeNode.cs
  8. 59
      ILSpy/TypeTreeNode.cs

38
ILSpy/AssemblyListTreeNode.cs

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Represents a list of assemblies.
/// </summary>
public sealed class AssemblyListTreeNode : SharpTreeNode
{
public override bool CanDelete(SharpTreeNode[] nodes)
{
return nodes.All(n => n is AssemblyTreeNode);
}
public override void Delete(SharpTreeNode[] nodes)
{
DeleteCore(nodes);
}
public override void DeleteCore(SharpTreeNode[] nodes)
{
foreach (SharpTreeNode node in nodes)
this.Children.Remove(node);
}
public override DropEffect CanDrop(System.Windows.IDataObject data, DropEffect requestedEffect)
{
return requestedEffect;
}
}
}

106
ILSpy/AssemblyTreeNode.cs

@ -4,8 +4,10 @@ @@ -4,8 +4,10 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -13,62 +15,46 @@ namespace ICSharpCode.ILSpy @@ -13,62 +15,46 @@ namespace ICSharpCode.ILSpy
{
sealed class AssemblyTreeNode : SharpTreeNode
{
readonly AssemblyDefinition assembly;
readonly string fileName;
readonly string name;
readonly Task<AssemblyDefinition> assemblyTask;
readonly List<TypeTreeNode> classes = new List<TypeTreeNode>();
public ObservableCollection<NamespaceTreeNode> Namespaces { get; private set; }
readonly Dictionary<TypeDefinition, TypeTreeNode> typeDict = new Dictionary<TypeDefinition, TypeTreeNode>();
readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>();
public AssemblyTreeNode(AssemblyDefinition assembly)
public AssemblyTreeNode(string fileName)
{
if (assembly == null)
throw new ArgumentNullException("assembly");
this.assembly = assembly;
this.Namespaces = new ObservableCollection<NamespaceTreeNode>();
InitClassList();
BuildNestedTypeLists();
BuildNamespaceList();
if (fileName == null)
throw new ArgumentNullException("fileName");
this.fileName = fileName;
this.assemblyTask = Task.Factory.StartNew<AssemblyDefinition>(LoadAssembly); // requires that this.fileName is set
this.name = Path.GetFileNameWithoutExtension(fileName);
this.LazyLoading = true;
}
public override object Text {
get { return assembly.Name.Name; }
get { return name; }
}
public override object Icon {
get { return Images.Assembly; }
}
void InitClassList()
AssemblyDefinition LoadAssembly()
{
// runs on background thread
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(fileName);
foreach (TypeDefinition type in assembly.MainModule.Types.OrderBy(t => t.FullName)) {
var viewmodel = new TypeTreeNode(type);
typeDict.Add(type, viewmodel);
if (type.IsNested == false) {
classes.Add(viewmodel);
}
foreach (TypeDefinition nestedType in TreeTraversal.PreOrder(type.NestedTypes, t => t.NestedTypes)) {
typeDict.Add(nestedType, new TypeTreeNode(nestedType));
}
classes.Add(new TypeTreeNode(type));
}
return assembly;
}
void BuildNestedTypeLists()
protected override void LoadChildren()
{
foreach (var typeModel in typeDict.Values) {
typeModel.NestedTypes.Clear();
}
foreach (var pair in typeDict) {
if (showInternalAPI == false && pair.Value.IsPublicAPI == false)
continue;
if (pair.Key.IsNested) {
typeDict[pair.Key.DeclaringType].NestedTypes.Add(pair.Value);
}
}
}
void BuildNamespaceList()
{
this.Children.Clear();
assemblyTask.Wait();
foreach (NamespaceTreeNode ns in namespaces.Values) {
ns.Children.Clear();
}
@ -88,18 +74,56 @@ namespace ICSharpCode.ILSpy @@ -88,18 +74,56 @@ namespace ICSharpCode.ILSpy
}
}
bool showInternalAPI;
/// <summary>
/// Invalidates the list of children.
/// </summary>
void InvalidateChildren()
{
this.Children.Clear();
if (this.IsExpanded)
this.LoadChildren();
else
this.LazyLoading = true;
}
bool showInternalAPI = true;
public bool ShowInternalAPI {
get { return showInternalAPI; }
set {
if (showInternalAPI != value) {
showInternalAPI = value;
BuildNestedTypeLists();
BuildNamespaceList();
InvalidateChildren();
RaisePropertyChanged("ShowInternalAPI");
}
}
}
public override bool CanDrag(SharpTreeNode[] nodes)
{
return nodes.All(n => n is AssemblyTreeNode);
}
public override bool CanDelete(SharpTreeNode[] nodes)
{
return Parent != null && Parent.CanDelete(nodes); // handle deletion in the AssemblyListTreeNode
}
public override void Delete(SharpTreeNode[] nodes)
{
Parent.Delete(nodes); // handle deletion in the AssemblyListTreeNode
}
public override void DeleteCore(SharpTreeNode[] nodes)
{
Parent.DeleteCore(nodes); // handle deletion in the AssemblyListTreeNode
}
public override IDataObject Copy(SharpTreeNode[] nodes)
{
DataObject dataObject = new DataObject();
dataObject.SetData("ILSpyAssemblies", nodes.OfType<AssemblyTreeNode>());
return dataObject;
}
}
}

47
ILSpy/FieldTreeNode.cs

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Represents a field in the TreeView.
/// </summary>
sealed class FieldTreeNode : SharpTreeNode
{
readonly FieldDefinition field;
public FieldTreeNode(FieldDefinition field)
{
if (field == null)
throw new ArgumentNullException("field");
this.field = field;
}
public override object Text {
get { return field.Name; }
}
public override object Icon {
get {
if (field.IsLiteral)
return Images.Literal;
switch (field.Attributes & FieldAttributes.FieldAccessMask) {
case FieldAttributes.Public:
return Images.Field;
case FieldAttributes.Assembly:
case FieldAttributes.FamANDAssem:
return Images.InternalField;
case FieldAttributes.Family:
case FieldAttributes.FamORAssem:
return Images.ProtectedField;
default:
return Images.PrivateField;
}
}
}
}
}

3
ILSpy/ILSpy.csproj

@ -64,8 +64,11 @@ @@ -64,8 +64,11 @@
<SubType>Code</SubType>
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="AssemblyListTreeNode.cs" />
<Compile Include="AssemblyTreeNode.cs" />
<Compile Include="FieldTreeNode.cs" />
<Compile Include="Images\Images.cs" />
<Compile Include="MethodTreeNode.cs" />
<Compile Include="Mono.Cecil.Rocks\MethodBodyRocks.cs" />
<Compile Include="NamespaceTreeNode.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

2
ILSpy/MainWindow.xaml

@ -11,6 +11,6 @@ @@ -11,6 +11,6 @@
Hyperlink.RequestNavigate="Window_RequestNavigate"
TextOptions.TextFormattingMode="Display"
>
<tv:SharpTreeView Name="treeView" ShowRoot="False" AllowDropOrder="True">
<tv:SharpTreeView Name="treeView" ShowRoot="False" AllowDropOrder="True" AllowDrop="True">
</tv:SharpTreeView>
</Window>

23
ILSpy/MainWindow.xaml.cs

@ -3,9 +3,10 @@ @@ -3,9 +3,10 @@
using System;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
@ -16,14 +17,30 @@ namespace ICSharpCode.ILSpy @@ -16,14 +17,30 @@ namespace ICSharpCode.ILSpy
{
SharpTreeNodeCollection assemblies;
static readonly Assembly[] initialAssemblies = {
typeof(object).Assembly,
typeof(Uri).Assembly,
typeof(System.Linq.Enumerable).Assembly,
typeof(System.Xml.XmlDocument).Assembly,
typeof(System.Windows.Markup.MarkupExtension).Assembly,
typeof(System.Windows.Rect).Assembly,
typeof(System.Windows.UIElement).Assembly,
typeof(System.Windows.FrameworkElement).Assembly,
typeof(ICSharpCode.TreeView.SharpTreeView).Assembly,
typeof(Mono.Cecil.AssemblyDefinition).Assembly,
typeof(ICSharpCode.NRefactory.SupportedLanguage).Assembly,
typeof(MainWindow).Assembly
};
public MainWindow()
{
InitializeComponent();
treeView.Root = new SharpTreeNode();
treeView.Root = new AssemblyListTreeNode();
assemblies = treeView.Root.Children;
assemblies.Add(new AssemblyTreeNode(AssemblyDefinition.ReadAssembly(typeof(object).Assembly.Location)));
foreach (Assembly asm in initialAssemblies)
assemblies.Add(new AssemblyTreeNode(asm.Location));
}
void Window_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)

45
ILSpy/MethodTreeNode.cs

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Tree Node representing a field, method, property, or event.
/// </summary>
public sealed class MethodTreeNode : SharpTreeNode
{
MethodDefinition method;
public MethodTreeNode(MethodDefinition method)
{
if (method == null)
throw new ArgumentNullException("method");
this.method = method;
}
public override object Text {
get { return method.Name; }
}
public override object Icon {
get {
switch (method.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
return Images.Method;
case MethodAttributes.Assembly:
case MethodAttributes.FamANDAssem:
return Images.InternalMethod;
case MethodAttributes.Family:
case MethodAttributes.FamORAssem:
return Images.ProtectedMethod;
default:
return Images.PrivateMethod;
}
}
}
}
}

59
ILSpy/TypeTreeNode.cs

@ -15,15 +15,13 @@ namespace ICSharpCode.ILSpy @@ -15,15 +15,13 @@ namespace ICSharpCode.ILSpy
{
readonly TypeDefinition type;
public ObservableCollection<TypeTreeNode> NestedTypes { get; private set; }
public TypeTreeNode(TypeDefinition type)
{
if (type == null)
throw new ArgumentNullException("type");
this.type = type;
this.NestedTypes = new ObservableCollection<TypeTreeNode>();
this.LazyLoading = true;
}
public string Name {
@ -38,6 +36,40 @@ namespace ICSharpCode.ILSpy @@ -38,6 +36,40 @@ namespace ICSharpCode.ILSpy
get { return type.Name; }
}
public TypeAttributes Visibility {
get {
return type.Attributes & TypeAttributes.VisibilityMask;
}
}
public bool IsPublicAPI {
get {
switch (this.Visibility) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
return true;
default:
return false;
}
}
}
protected override void LoadChildren()
{
foreach (TypeDefinition nestedType in type.NestedTypes) {
this.Children.Add(new TypeTreeNode(nestedType));
}
foreach (FieldDefinition field in type.Fields) {
this.Children.Add(new FieldTreeNode(field));
}
foreach (MethodDefinition method in type.Methods) {
this.Children.Add(new MethodTreeNode(method));
}
}
#region Icon
enum ClassType
{
Class,
@ -64,26 +96,6 @@ namespace ICSharpCode.ILSpy @@ -64,26 +96,6 @@ namespace ICSharpCode.ILSpy
}
}
public TypeAttributes Visibility {
get {
return type.Attributes & TypeAttributes.VisibilityMask;
}
}
public bool IsPublicAPI {
get {
switch (this.Visibility) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
return true;
default:
return false;
}
}
}
public override object Icon {
get {
switch (this.Visibility) {
@ -128,5 +140,6 @@ namespace ICSharpCode.ILSpy @@ -128,5 +140,6 @@ namespace ICSharpCode.ILSpy
}
}
}
#endregion
}
}

Loading…
Cancel
Save