339 lines
10 KiB
C#
339 lines
10 KiB
C#
//
|
|
// ManagedAssemblyPanel.cs - provides a UWT Container with controls to edit managed assembly information for an ExecutableObjectModel
|
|
//
|
|
// Author:
|
|
// Michael Becker <alcexhim@gmail.com>
|
|
//
|
|
// Copyright (c) 2019-2020 Mike Becker's Software
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
using System;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using MBS.Framework.UserInterface;
|
|
using MBS.Framework.UserInterface.Controls;
|
|
using MBS.Framework.UserInterface.Dialogs;
|
|
using MBS.Framework.UserInterface.Layouts;
|
|
|
|
namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable
|
|
{
|
|
/// <summary>
|
|
/// Provides a UWT Container with controls to edit managed assembly information for an <see cref="ObjectModels.Executable.ExecutableObjectModel" />.
|
|
/// </summary>
|
|
public class ManagedAssemblyPanel : Container
|
|
{
|
|
private TextBox txtSearch = null;
|
|
private ListView tvTypes = null;
|
|
private DefaultTreeModel tmTypes = null;
|
|
private TextBox txtSource = null;
|
|
|
|
private ComboBox cboLanguage = null;
|
|
|
|
private Assembly _Assembly = null;
|
|
public Assembly Assembly
|
|
{
|
|
get { return _Assembly; }
|
|
set
|
|
{
|
|
_Assembly = value;
|
|
UpdateTypeList();
|
|
}
|
|
}
|
|
|
|
private void UpdateTypeList()
|
|
{
|
|
tmTypes.Rows.Clear();
|
|
|
|
Type[] types = null;
|
|
try
|
|
{
|
|
types = _Assembly.GetTypes();
|
|
}
|
|
catch (ReflectionTypeLoadException ex)
|
|
{
|
|
types = ex.Types;
|
|
}
|
|
|
|
for (int i = 0; i < types.Length; i++)
|
|
{
|
|
if (types[i] == null)
|
|
continue;
|
|
|
|
string[] nameParts = types[i].FullName.Split(new char[] { '.' });
|
|
bool nestedClass = false;
|
|
while (nameParts[nameParts.Length - 1].Contains("+"))
|
|
{
|
|
// handle the case of nested classes
|
|
nestedClass = true;
|
|
Array.Resize<string>(ref nameParts, nameParts.Length + 1);
|
|
string[] p = nameParts[nameParts.Length - 2].Split(new char[] { '+' });
|
|
nameParts[nameParts.Length - 2] = p[0];
|
|
nameParts[nameParts.Length - 1] = p[1];
|
|
}
|
|
|
|
TreeModelRow row = tmTypes.RecursiveCreateTreeModelRow(tmTypes.Columns[0], nameParts, new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmTypes.Columns[1], "Namespace")
|
|
});
|
|
|
|
if (nestedClass)
|
|
row.ParentRow.RowColumns[1].Value = "Class";
|
|
|
|
row.RowColumns.Add(new TreeModelRowColumn(tmTypes.Columns[1], "Class"));
|
|
|
|
SetupTypeTreeModelRow(row, types[i]);
|
|
}
|
|
}
|
|
|
|
private void SetupTypeTreeModelRow(TreeModelRow row, Type type)
|
|
{
|
|
row.SetExtraData<Type>("item", type);
|
|
|
|
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
|
|
|
|
TreeModelRow rowBaseTypes = new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmTypes.Columns[0], "Base Types")
|
|
});
|
|
|
|
if (type.BaseType != null)
|
|
{
|
|
TreeModelRow rowBaseType = new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmTypes.Columns[0], type.BaseType.FullName)
|
|
});
|
|
SetupTypeTreeModelRow(rowBaseType, type.BaseType);
|
|
rowBaseTypes.Rows.Add(rowBaseType);
|
|
}
|
|
|
|
row.Rows.Add(rowBaseTypes);
|
|
|
|
TreeModelRow rowDerivedTypes = new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmTypes.Columns[0], "Derived Types")
|
|
});
|
|
row.Rows.Add(rowDerivedTypes);
|
|
|
|
FieldInfo[] fields = type.GetFields(bindingFlags);
|
|
for (int j = 0; j < fields.Length; j++)
|
|
{
|
|
TreeModelRow row2 = new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmTypes.Columns[0], fields[j]),
|
|
new TreeModelRowColumn(tmTypes.Columns[1], "Field")
|
|
});
|
|
row2.SetExtraData<FieldInfo>("item", fields[j]);
|
|
row.Rows.Add(row2);
|
|
}
|
|
|
|
EventInfo[] events = type.GetEvents(bindingFlags);
|
|
for (int j = 0; j < events.Length; j++)
|
|
{
|
|
TreeModelRow row2 = new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmTypes.Columns[0], events[j]),
|
|
new TreeModelRowColumn(tmTypes.Columns[1], "Event")
|
|
});
|
|
row2.SetExtraData<EventInfo>("item", events[j]);
|
|
row.Rows.Add(row2);
|
|
}
|
|
|
|
PropertyInfo[] props = type.GetProperties(bindingFlags);
|
|
for (int j = 0; j < props.Length; j++)
|
|
{
|
|
TreeModelRow row2 = new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmTypes.Columns[0], props[j]),
|
|
new TreeModelRowColumn(tmTypes.Columns[1], "Property")
|
|
});
|
|
row2.SetExtraData<PropertyInfo>("item", props[j]);
|
|
row.Rows.Add(row2);
|
|
}
|
|
|
|
MethodInfo[] meths = type.GetMethods(bindingFlags);
|
|
for (int j = 0; j < meths.Length; j++)
|
|
{
|
|
if (meths[j].IsSpecialName && (meths[j].Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase) || meths[j].Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
// we can be REASONABLY sure that this is a property setter / getter,
|
|
// and as we've already gotten all the properties, ignore it
|
|
continue;
|
|
}
|
|
|
|
TreeModelRow row2 = new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmTypes.Columns[0], GetMethodTitle(meths[j])),
|
|
new TreeModelRowColumn(tmTypes.Columns[1], "Method")
|
|
});
|
|
row2.SetExtraData<MethodInfo>("item", meths[j]);
|
|
row.Rows.Add(row2);
|
|
}
|
|
}
|
|
|
|
private void tsbILSave_Click(object sender, EventArgs e)
|
|
{
|
|
MemberInfo t = tvTypes.SelectedRows[0].GetExtraData<MemberInfo>("item");
|
|
if (t == null)
|
|
return;
|
|
|
|
FileDialog dlg = new FileDialog();
|
|
dlg.Text = "Save Code File";
|
|
|
|
dlg.SelectedFileNames.Clear();
|
|
|
|
dlg.SelectedFileNames.Add(t.Name + Language.CodeFileExtension);
|
|
|
|
if (dlg.ShowDialog() == DialogResult.OK)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
public ManagedAssemblyPanel()
|
|
{
|
|
Layout = new BoxLayout(Orientation.Vertical);
|
|
|
|
Container ctToolbarAndOthers = new Container();
|
|
ctToolbarAndOthers.Layout = new BoxLayout(Orientation.Horizontal);
|
|
|
|
Toolbar tb = new Toolbar();
|
|
tb.Items.Add(new ToolbarItemButton("tsbILSave", StockType.Save, tsbILSave_Click));
|
|
ctToolbarAndOthers.Controls.Add(tb, new BoxLayout.Constraints(false, true));
|
|
|
|
cboLanguage = new ComboBox();
|
|
cboLanguage.Changed += cboLanguage_Changed;
|
|
Type[] codeProviders = MBS.Framework.Reflection.GetAvailableTypes(new Type[] { typeof(CodeProvider) });
|
|
DefaultTreeModel tmLanguage = new DefaultTreeModel(new Type[] { typeof(string) });
|
|
|
|
/*
|
|
tmLanguage.Rows.Add(new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmLanguage.Columns[0], "Raw Bytes")
|
|
}));
|
|
*/
|
|
|
|
for (int i = 0; i < codeProviders.Length; i++)
|
|
{
|
|
CodeProvider codeProvider = (codeProviders[i].Assembly.CreateInstance(codeProviders[i].FullName) as CodeProvider);
|
|
TreeModelRow row = new TreeModelRow(new TreeModelRowColumn[]
|
|
{
|
|
new TreeModelRowColumn(tmLanguage.Columns[0], codeProvider.Title)
|
|
});
|
|
row.SetExtraData<CodeProvider>("provider", codeProvider);
|
|
tmLanguage.Rows.Add(row);
|
|
}
|
|
if (tmLanguage.Rows.Count > 0)
|
|
{
|
|
cboLanguage.SelectedItem = tmLanguage.Rows[0];
|
|
}
|
|
cboLanguage.ReadOnly = true;
|
|
cboLanguage.Model = tmLanguage;
|
|
ctToolbarAndOthers.Controls.Add(cboLanguage, new BoxLayout.Constraints(false, false));
|
|
|
|
Controls.Add(ctToolbarAndOthers, new BoxLayout.Constraints(false, true));
|
|
|
|
SplitContainer scLeftRight = new SplitContainer(Orientation.Vertical);
|
|
scLeftRight.SplitterPosition = 250;
|
|
|
|
txtSearch = new TextBox();
|
|
|
|
scLeftRight.Panel1.Layout = new BoxLayout(Orientation.Vertical);
|
|
scLeftRight.Panel1.Controls.Add(txtSearch, new BoxLayout.Constraints(false, true));
|
|
|
|
tvTypes = new ListView();
|
|
tvTypes.SelectionChanged += tvTypes_SelectionChanged;
|
|
|
|
tmTypes = new DefaultTreeModel(new Type[] { typeof(string), typeof(string) });
|
|
tvTypes.Model = tmTypes;
|
|
|
|
tvTypes.Columns.Add(new ListViewColumnText(tmTypes.Columns[0], "Name"));
|
|
tvTypes.Columns.Add(new ListViewColumnText(tmTypes.Columns[1], "Type"));
|
|
scLeftRight.Panel1.Controls.Add(tvTypes, new BoxLayout.Constraints(true, true));
|
|
|
|
scLeftRight.Panel2.Layout = new BoxLayout(Orientation.Vertical);
|
|
txtSource = new TextBox();
|
|
txtSource.Multiline = true;
|
|
scLeftRight.Panel2.Controls.Add(txtSource, new BoxLayout.Constraints(true, true));
|
|
|
|
Controls.Add(scLeftRight, new BoxLayout.Constraints(true, true));
|
|
}
|
|
|
|
void cboLanguage_Changed(object sender, EventArgs e)
|
|
{
|
|
CodeProvider provider = cboLanguage.SelectedItem.GetExtraData<CodeProvider>("provider");
|
|
Language = provider;
|
|
}
|
|
|
|
|
|
private CodeProvider _Language = CodeProvider.CSharp;
|
|
public CodeProvider Language
|
|
{
|
|
get { return _Language; }
|
|
set
|
|
{
|
|
_Language = value;
|
|
tvTypes_SelectionChanged(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
private string GetAccessModifiersSourceCode(PropertyInfo mi)
|
|
{
|
|
return Language.GetAccessModifiers(mi);
|
|
}
|
|
private string GetAccessModifiersSourceCode(MethodInfo mi)
|
|
{
|
|
return Language.GetAccessModifiers(mi);
|
|
}
|
|
private string GetAccessModifiersSourceCode(FieldInfo mi)
|
|
{
|
|
return Language.GetAccessModifiers(mi);
|
|
}
|
|
private string GetAccessModifiersSourceCode(Type mi)
|
|
{
|
|
return Language.GetAccessModifiers(mi);
|
|
}
|
|
|
|
private string GetMethodTitle(MethodInfo mi)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
string typeName = Language.GetTypeName(mi.ReturnType);
|
|
sb.Append(mi.Name);
|
|
sb.Append('(');
|
|
sb.Append(')');
|
|
sb.Append(" : ");
|
|
sb.Append(typeName);
|
|
return sb.ToString();
|
|
}
|
|
|
|
private void tvTypes_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
if (tvTypes.SelectedRows.Count == 0)
|
|
return;
|
|
|
|
object item = tvTypes.SelectedRows[0].GetExtraData("item");
|
|
if (item is Type)
|
|
{
|
|
Type typ = (item as Type);
|
|
txtSource.Text = Language.GetSourceCode(typ, 0);
|
|
}
|
|
else if (item is MethodInfo)
|
|
{
|
|
txtSource.Text = Language.GetSourceCode(item as MethodInfo, 0);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|