Преглед изворни кода

Added new scenario ClassExplorer which presents all Types and Methods divided by assembly

tznind пре 4 година
родитељ
комит
f675b3b39c
2 измењених фајлова са 244 додато и 0 уклоњено
  1. 12 0
      Terminal.Gui/Views/TreeView.cs
  2. 232 0
      UICatalog/Scenarios/ClassExplorer.cs

+ 12 - 0
Terminal.Gui/Views/TreeView.cs

@@ -320,6 +320,12 @@ namespace Terminal.Gui {
 		/// Secondary selected regions of tree when <see cref="MultiSelect"/> is true
 		/// </summary>
 		private Stack<TreeSelection<T>> _multiSelectedRegions = new Stack<TreeSelection<T>>();
+		
+
+		/// <summary>
+		/// Error message to display when the control is not properly initialized at draw time (nodes added but no tree builder set)
+		/// </summary>
+		public static ustring NoBuilderError = "ERROR: Builder Not Set";
 
 		/// <summary>
 		/// Called when the <see cref="SelectedObject"/> changes
@@ -501,6 +507,12 @@ namespace Terminal.Gui {
 			if(roots == null)
 				return;
 
+			if(TreeBuilder == null) {
+				Move(0,0);
+				Driver.AddStr(NoBuilderError);
+				return;
+			}
+
 			var map = BuildLineMap();
 
 			for(int line = 0 ; line < bounds.Height; line++){

+ 232 - 0
UICatalog/Scenarios/ClassExplorer.cs

@@ -0,0 +1,232 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios {
+
+	[ScenarioMetadata (Name: "Class Explorer", Description: "Tree view explorer for classes by namespace based on TreeView")]
+	[ScenarioCategory ("Controls")]
+	class ClassExplorer : Scenario {
+		private TreeView<object> treeView;
+		private TextView textView;
+		private MenuItem miShowPrivate;
+
+		private enum Showable {
+			Properties,
+			Fields,
+			Events,
+			Constructors,
+			Methods,
+		}
+
+		private class ShowForType {
+			public ShowForType (Showable toShow, Type type)
+			{
+				ToShow = toShow;
+				Type = type;
+			}
+
+			public Type Type {get;set;}
+			public Showable ToShow {get;set;}
+
+			public override string ToString ()
+			{
+				return ToShow.ToString();
+			}
+		}
+
+		public override void Setup ()
+		{
+			Win.Title = this.GetName();
+			Win.Y = 1; // menu
+			Win.Height = Dim.Fill (1); // status bar
+			Top.LayoutSubviews();
+						
+			var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem ("_File", new MenuItem [] {
+					new MenuItem ("_Quit", "", () => Quit()),
+				})
+				,
+				new MenuBarItem ("_View", new MenuItem [] {
+					miShowPrivate = new MenuItem ("_Include Private", "", () => ShowPrivate()){
+						Checked = false,
+						CheckType = MenuItemCheckStyle.Checked
+					} }),
+			});
+			Top.Add (menu);
+
+			treeView = new TreeView<object> () {
+				X = 0,
+				Y = 0,
+				Width = Dim.Percent(50),
+				Height = Dim.Fill(),
+			};
+
+
+			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);
+		}
+
+		private void ShowPrivate ()
+		{
+			miShowPrivate.Checked = !miShowPrivate.Checked;
+			treeView.RebuildTree();
+		}
+
+		private BindingFlags GetFlags()
+		{
+			if(miShowPrivate.Checked)
+				return BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+			
+			return BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
+		}
+
+		private void TreeView_SelectionChanged (object sender, SelectionChangedEventArgs<object> e)
+		{
+			var val = e.NewValue;
+
+			if(val == null || val is ShowForType)
+				return;
+			try {
+				
+				StringBuilder 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(var parameter in ev.EventHandlerType.GetMethod("Invoke").GetParameters()) {
+						sb.AppendLine($"\t{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(var parameter in method.GetParameters()) {
+						sb.AppendLine($"\t{parameter.ParameterType} {parameter.Name}");
+					}
+				}
+			
+					
+				if(val is ConstructorInfo ctor) {
+					sb.AppendLine($"Name:{ctor.Name}");
+					sb.AppendLine($"Parameters:{(ctor.GetParameters().Any() ? "":"None")}");
+					foreach(var parameter in ctor.GetParameters()) {
+						sb.AppendLine($"\t{parameter.ParameterType} {parameter.Name}");
+					}
+				}
+
+				textView.Text = sb.ToString().Replace("\r\n","\n");
+
+			} catch (Exception ex) {
+
+				textView.Text = ex.Message;
+			}
+			textView.SetNeedsDisplay();
+		}
+
+		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 must 
+					return Enum.GetValues(typeof(Showable)).Cast<Showable>().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 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 Quit ()
+		{
+			Application.RequestStop ();
+		}
+	}
+}