123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using Terminal.Gui;
- 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 MenuItem _highlightModelTextOnly;
- private MenuItem _miShowPrivate;
- private TextView _textView;
- private TreeView<object> _treeView;
- public override void Main ()
- {
- Application.Init ();
- var top = new Toplevel ();
- var menu = new MenuBar
- {
- Menus =
- [
- new MenuBarItem ("_File", new MenuItem [] { new ("_Quit", "", () => Quit ()) }),
- new MenuBarItem (
- "_View",
- new []
- {
- _miShowPrivate =
- new MenuItem (
- "_Include Private",
- "",
- () => ShowPrivate ()
- ) { Checked = false, CheckType = MenuItemCheckStyle.Checked },
- new ("_Expand All", "", () => _treeView.ExpandAll ()),
- new ("_Collapse All", "", () => _treeView.CollapseAll ())
- }
- ),
- new MenuBarItem (
- "_Style",
- new []
- {
- _highlightModelTextOnly = new MenuItem (
- "_Highlight Model Text Only",
- "",
- () => OnCheckHighlightModelTextOnly ()
- ) { CheckType = MenuItemCheckStyle.Checked }
- }
- )
- ]
- };
- top.Add (menu);
- var win = new Window
- {
- Title = GetName (),
- Y = Pos.Bottom (menu)
- };
- _treeView = new TreeView<object> { X = 0, Y = 1, Width = Dim.Percent (50), Height = Dim.Fill () };
- var lblSearch = new Label { Text = "Search" };
- var tfSearch = new TextField { Width = 20, X = Pos.Right (lblSearch) };
- win.Add (lblSearch);
- win.Add (tfSearch);
- TreeViewTextFilter<object> filter = new (_treeView);
- _treeView.Filter = filter;
- tfSearch.TextChanged += (s, e) =>
- {
- filter.Text = tfSearch.Text;
- if (_treeView.SelectedObject != null)
- {
- _treeView.EnsureVisible (_treeView.SelectedObject);
- }
- };
- _treeView.AddObjects (AppDomain.CurrentDomain.GetAssemblies ());
- _treeView.AspectGetter = GetRepresentation;
- _treeView.TreeBuilder = new DelegateTreeBuilder<object> (ChildGetter, CanExpand);
- _treeView.SelectionChanged += TreeView_SelectionChanged;
- win.Add (_treeView);
- _textView = new TextView { X = Pos.Right (_treeView), Y = 0, Width = Dim.Fill (), Height = Dim.Fill () };
- win.Add (_textView);
- top.Add (win);
- Application.Run (top);
- top.Dispose ();
- Application.Shutdown ();
- }
- private bool CanExpand (object arg) { return arg is Assembly || arg is Type || arg is ShowForType; }
- private IEnumerable<object> ChildGetter (object arg)
- {
- try
- {
- if (arg is Assembly a)
- {
- return a.GetTypes ();
- }
- if (arg is Type t)
- {
- // Note that here we cannot simply return the enum values as the same object cannot appear under multiple branches
- return Enum.GetValues (typeof (Showable))
- .Cast<Showable> ()
- // Although we new the Type every time the delegate is called state is preserved because the class has appropriate equality members
- .Select (v => new ShowForType (v, t));
- }
- if (arg is ShowForType show)
- {
- switch (show.ToShow)
- {
- case Showable.Properties:
- return show.Type.GetProperties (GetFlags ());
- case Showable.Constructors:
- return show.Type.GetConstructors (GetFlags ());
- case Showable.Events:
- return show.Type.GetEvents (GetFlags ());
- case Showable.Fields:
- return show.Type.GetFields (GetFlags ());
- case Showable.Methods:
- return show.Type.GetMethods (GetFlags ());
- }
- }
- }
- catch (Exception)
- {
- return Enumerable.Empty<object> ();
- }
- return Enumerable.Empty<object> ();
- }
- private BindingFlags GetFlags ()
- {
- if (_miShowPrivate.Checked == true)
- {
- return BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
- }
- return BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
- }
- private string GetRepresentation (object model)
- {
- try
- {
- if (model is Assembly ass)
- {
- return ass.GetName ().Name;
- }
- if (model is PropertyInfo p)
- {
- return p.Name;
- }
- if (model is FieldInfo f)
- {
- return f.Name;
- }
- if (model is EventInfo ei)
- {
- return ei.Name;
- }
- }
- catch (Exception ex)
- {
- return ex.Message;
- }
- return model.ToString ();
- }
- private void OnCheckHighlightModelTextOnly ()
- {
- _treeView.Style.HighlightModelTextOnly = !_treeView.Style.HighlightModelTextOnly;
- _highlightModelTextOnly.Checked = _treeView.Style.HighlightModelTextOnly;
- _treeView.SetNeedsDraw ();
- }
- private void Quit () { Application.RequestStop (); }
- private void ShowPrivate ()
- {
- _miShowPrivate.Checked = !_miShowPrivate.Checked;
- _treeView.RebuildTree ();
- _treeView.SetFocus ();
- }
- private void TreeView_SelectionChanged (object sender, SelectionChangedEventArgs<object> e)
- {
- object val = e.NewValue;
- object [] all = _treeView.GetAllSelectedObjects ().ToArray ();
- if (val == null || val is ShowForType)
- {
- return;
- }
- try
- {
- if (all.Length > 1)
- {
- _textView.Text = all.Length + " Objects";
- }
- else
- {
- var sb = new StringBuilder ();
- // tell the user about the currently selected tree node
- sb.AppendLine (e.NewValue.GetType ().Name);
- if (val is Assembly ass)
- {
- sb.AppendLine ($"Location:{ass.Location}");
- sb.AppendLine ($"FullName:{ass.FullName}");
- }
- if (val is PropertyInfo p)
- {
- sb.AppendLine ($"Name:{p.Name}");
- sb.AppendLine ($"Type:{p.PropertyType}");
- sb.AppendLine ($"CanWrite:{p.CanWrite}");
- sb.AppendLine ($"CanRead:{p.CanRead}");
- }
- if (val is FieldInfo f)
- {
- sb.AppendLine ($"Name:{f.Name}");
- sb.AppendLine ($"Type:{f.FieldType}");
- }
- if (val is EventInfo ev)
- {
- sb.AppendLine ($"Name:{ev.Name}");
- sb.AppendLine ("Parameters:");
- foreach (ParameterInfo parameter in ev.EventHandlerType.GetMethod ("Invoke")
- .GetParameters ())
- {
- sb.AppendLine ($" {parameter.ParameterType} {parameter.Name}");
- }
- }
- if (val is MethodInfo method)
- {
- sb.AppendLine ($"Name:{method.Name}");
- sb.AppendLine ($"IsPublic:{method.IsPublic}");
- sb.AppendLine ($"IsStatic:{method.IsStatic}");
- sb.AppendLine ($"Parameters:{(method.GetParameters ().Any () ? "" : "None")}");
- foreach (ParameterInfo parameter in method.GetParameters ())
- {
- sb.AppendLine ($" {parameter.ParameterType} {parameter.Name}");
- }
- }
- if (val is ConstructorInfo ctor)
- {
- sb.AppendLine ($"Name:{ctor.Name}");
- sb.AppendLine ($"Parameters:{(ctor.GetParameters ().Any () ? "" : "None")}");
- foreach (ParameterInfo parameter in ctor.GetParameters ())
- {
- sb.AppendLine ($" {parameter.ParameterType} {parameter.Name}");
- }
- }
- _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 class ShowForType
- {
- public ShowForType (Showable toShow, Type type)
- {
- ToShow = toShow;
- Type = type;
- }
- public Showable ToShow { get; }
- public Type Type { get; }
- // Make sure to implement Equals methods on your objects if you intend to return new instances every time in ChildGetter
- public override bool Equals (object obj)
- {
- return obj is ShowForType type && EqualityComparer<Type>.Default.Equals (Type, type.Type) && ToShow == type.ToShow;
- }
- public override int GetHashCode () { return HashCode.Combine (Type, ToShow); }
- public override string ToString () { return ToShow.ToString (); }
- }
- }
|