Files
Terminal.Gui/Examples/UICatalog/Scenarios/ClassExplorer.cs

349 lines
12 KiB
C#

#nullable enable
using System.Reflection;
using System.Text;
namespace UICatalog.Scenarios;
[ScenarioMetadata ("Class Explorer", "Tree view explorer for classes by namespace based on TreeView.")]
[ScenarioCategory ("Controls")]
[ScenarioCategory ("TreeView")]
public class ClassExplorer : Scenario
{
private CheckBox? _highlightModelTextOnlyCheckBox;
private CheckBox? _showPrivateCheckBox;
private TextView? _textView;
private TreeView<object>? _treeView;
public override void Main ()
{
Application.Init ();
Window win = new ()
{
Title = GetName (),
BorderStyle = LineStyle.None
};
// MenuBar
MenuBar menuBar = new ();
// Search controls
Label lblSearch = new ()
{
Y = Pos.Bottom (menuBar),
Title = "Search:"
};
TextField tfSearch = new ()
{
Y = Pos.Top (lblSearch),
X = Pos.Right (lblSearch) + 1,
Width = 20
};
// TreeView
_treeView = new ()
{
Y = Pos.Bottom (lblSearch),
Width = Dim.Percent (50),
Height = Dim.Fill ()
};
TreeViewTextFilter<object> filter = new (_treeView);
_treeView.Filter = filter;
tfSearch.TextChanged += (s, e) =>
{
filter.Text = tfSearch.Text;
if (_treeView.SelectedObject is { })
{
_treeView.EnsureVisible (_treeView.SelectedObject);
}
};
_treeView.AddObjects (AppDomain.CurrentDomain.GetAssemblies ());
_treeView.AspectGetter = GetRepresentation;
_treeView.TreeBuilder = new DelegateTreeBuilder<object> (ChildGetter, CanExpand);
_treeView.SelectionChanged += TreeView_SelectionChanged;
// TextView for details
_textView = new ()
{
X = Pos.Right (_treeView),
Y = Pos.Top (_treeView),
Width = Dim.Fill (),
Height = Dim.Fill (),
ReadOnly = true,
};
// Menu setup
_showPrivateCheckBox = new ()
{
Title = "_Include Private"
};
_showPrivateCheckBox.CheckedStateChanged += (s, e) => ShowPrivate ();
_highlightModelTextOnlyCheckBox = new ()
{
Title = "_Highlight Model Text Only"
};
_highlightModelTextOnlyCheckBox.CheckedStateChanged += (s, e) => OnCheckHighlightModelTextOnly ();
menuBar.Add (
new MenuBarItem (
"_File",
[
new MenuItem
{
Title = "_Quit",
Action = Quit
}
]
)
);
menuBar.Add (
new MenuBarItem (
"_View",
[
new MenuItem
{
CommandView = _showPrivateCheckBox
},
new MenuItem
{
Title = "_Expand All",
Action = () => _treeView?.ExpandAll ()
},
new MenuItem
{
Title = "_Collapse All",
Action = () => _treeView?.CollapseAll ()
}
]
)
);
menuBar.Add (
new MenuBarItem (
"_Style",
[
new MenuItem
{
CommandView = _highlightModelTextOnlyCheckBox
}
]
)
);
// Add views in order of visual appearance
win.Add (menuBar, lblSearch, tfSearch, _treeView, _textView);
Application.Run (win);
win.Dispose ();
Application.Shutdown ();
}
private bool CanExpand (object arg) => arg is Assembly or Type or ShowForType;
private IEnumerable<object> ChildGetter (object arg)
{
try
{
return arg switch
{
Assembly assembly => assembly.GetTypes (),
Type type => Enum.GetValues (typeof (Showable))
.Cast<Showable> ()
.Select (v => new ShowForType (v, type)),
ShowForType show => show.ToShow switch
{
Showable.Properties => show.Type.GetProperties (GetFlags ()),
Showable.Constructors => show.Type.GetConstructors (GetFlags ()),
Showable.Events => show.Type.GetEvents (GetFlags ()),
Showable.Fields => show.Type.GetFields (GetFlags ()),
Showable.Methods => show.Type.GetMethods (GetFlags ()),
_ => Enumerable.Empty<object> ()
},
_ => Enumerable.Empty<object> ()
};
}
catch (Exception)
{
return Enumerable.Empty<object> ();
}
}
private BindingFlags GetFlags () =>
_showPrivateCheckBox?.CheckedState == CheckState.Checked
? BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic
: BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
private string GetRepresentation (object model)
{
try
{
return model switch
{
Assembly assembly => assembly.GetName ().Name ?? string.Empty,
PropertyInfo propertyInfo => propertyInfo.Name,
FieldInfo fieldInfo => fieldInfo.Name,
EventInfo eventInfo => eventInfo.Name,
_ => model.ToString () ?? string.Empty
};
}
catch (Exception ex)
{
return ex.Message;
}
}
private void OnCheckHighlightModelTextOnly ()
{
if (_treeView is null)
{
return;
}
_treeView.Style.HighlightModelTextOnly = _highlightModelTextOnlyCheckBox?.CheckedState == CheckState.Checked;
_treeView.SetNeedsDraw ();
}
private void Quit () { Application.RequestStop (); }
private void ShowPrivate ()
{
_treeView?.RebuildTree ();
_treeView?.SetFocus ();
}
private void TreeView_SelectionChanged (object? sender, SelectionChangedEventArgs<object> e)
{
if (_treeView is null || _textView is null)
{
return;
}
object? val = e.NewValue;
object [] all = _treeView.GetAllSelectedObjects ().ToArray ();
if (val is null or ShowForType)
{
return;
}
try
{
if (all.Length > 1)
{
_textView.Text = $"{all.Length} Objects";
}
else
{
StringBuilder sb = new ();
sb.AppendLine (e.NewValue?.GetType ().Name ?? string.Empty);
switch (val)
{
case Assembly assembly:
sb.AppendLine ($"Location:{assembly.Location}");
sb.AppendLine ($"FullName:{assembly.FullName}");
break;
case PropertyInfo propertyInfo:
sb.AppendLine ($"Name:{propertyInfo.Name}");
sb.AppendLine ($"Type:{propertyInfo.PropertyType}");
sb.AppendLine ($"CanWrite:{propertyInfo.CanWrite}");
sb.AppendLine ($"CanRead:{propertyInfo.CanRead}");
break;
case FieldInfo fieldInfo:
sb.AppendLine ($"Name:{fieldInfo.Name}");
sb.AppendLine ($"Type:{fieldInfo.FieldType}");
break;
case EventInfo eventInfo:
sb.AppendLine ($"Name:{eventInfo.Name}");
sb.AppendLine ("Parameters:");
if (eventInfo.EventHandlerType?.GetMethod ("Invoke") is { } invokeMethod)
{
foreach (ParameterInfo parameter in invokeMethod.GetParameters ())
{
sb.AppendLine ($" {parameter.ParameterType} {parameter.Name}");
}
}
break;
case MethodInfo methodInfo:
sb.AppendLine ($"Name:{methodInfo.Name}");
sb.AppendLine ($"IsPublic:{methodInfo.IsPublic}");
sb.AppendLine ($"IsStatic:{methodInfo.IsStatic}");
sb.AppendLine ($"Parameters:{(methodInfo.GetParameters ().Length > 0 ? string.Empty : "None")}");
foreach (ParameterInfo parameter in methodInfo.GetParameters ())
{
sb.AppendLine ($" {parameter.ParameterType} {parameter.Name}");
}
break;
case ConstructorInfo constructorInfo:
sb.AppendLine ($"Name:{constructorInfo.Name}");
sb.AppendLine ($"Parameters:{(constructorInfo.GetParameters ().Length > 0 ? string.Empty : "None")}");
foreach (ParameterInfo parameter in constructorInfo.GetParameters ())
{
sb.AppendLine ($" {parameter.ParameterType} {parameter.Name}");
}
break;
}
_textView.Text = sb.ToString ().Replace ("\r\n", "\n");
}
}
catch (Exception ex)
{
_textView.Text = ex.Message;
}
_textView.SetNeedsDraw ();
}
private enum Showable
{
Properties,
Fields,
Events,
Constructors,
Methods
}
private sealed class ShowForType
{
public ShowForType (Showable toShow, Type type)
{
ToShow = toShow;
Type = type;
}
public Showable ToShow { get; }
public Type Type { get; }
public override bool Equals (object? obj) =>
obj is ShowForType type && EqualityComparer<Type>.Default.Equals (Type, type.Type) && ToShow == type.ToShow;
public override int GetHashCode () => HashCode.Combine (Type, ToShow);
public override string ToString () => ToShow.ToString ();
}
}