Procházet zdrojové kódy

Added interactive scenario (create and delete tree nodes on demand). Added Tag and Text to interface for ITreeNode

tznind před 4 roky
rodič
revize
2d7b3f4f52

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

@@ -12,11 +12,21 @@ namespace Terminal.Gui {
 	/// </summary>
 	public interface ITreeNode
 	{
+		/// <summary>
+		/// Text to display when rendering the node
+		/// </summary>
+		string Text {get;set;}
+
 		/// <summary>
 		/// The children of your class which should be rendered underneath it when expanded
 		/// </summary>
 		/// <value></value>
 		IList<ITreeNode> Children {get;}
+
+		/// <summary>
+		/// Optionally allows you to store some custom data/class here.
+		/// </summary>
+		object Tag {get;set;}
 	}
 
 	/// <summary>
@@ -36,6 +46,11 @@ namespace Terminal.Gui {
 		/// <value></value>
 		public string Text {get;set;}
 
+		/// <summary>
+		/// Optionally allows you to store some custom data/class here.
+		/// </summary>
+		public object Tag {get;set;}
+
 		/// <summary>
 		/// returns <see cref="Text"/>
 		/// </summary>
@@ -228,6 +243,7 @@ namespace Terminal.Gui {
 		public TreeView ()
 		{
 			TreeBuilder = new TreeNodeBuilder();
+			AspectGetter = o=>o == null ? "Null" : (o.Text ?? o?.ToString() ?? "Unamed Node");
 		}
 	}
 	

+ 150 - 0
UICatalog/Scenarios/InteractiveTree.cs

@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Terminal.Gui;
+using static UICatalog.Scenario;
+
+namespace UICatalog.Scenarios {
+
+	[ScenarioMetadata (Name: "Interactive Tree", Description: "Create nodes and child nodes in TreeView")]
+	[ScenarioCategory ("Controls")]
+	class InteractiveTree : Scenario{
+
+		TreeView treeView;
+
+		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()),
+				}) 
+				});
+			
+			treeView = new TreeView() {
+				X = 0,
+				Y = 0,
+				Width = Dim.Fill(),
+				Height = Dim.Fill(1),
+			};
+			treeView.KeyPress += TreeView_KeyPress;
+			
+			Win.Add(treeView);
+
+			var statusBar = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
+				new StatusItem(Key.CtrlMask | Key.C, "~^C~ Add Child", () => AddChildNode()),
+				new StatusItem(Key.CtrlMask | Key.T, "~^T~ Add Root", () => AddRootNode()),
+				new StatusItem(Key.CtrlMask | Key.R, "~^R~ Rename Node", () => RenameNode()),
+			});
+			Top.Add (statusBar);
+
+		}
+
+		private void TreeView_KeyPress (View.KeyEventEventArgs obj)
+		{
+			if(obj.KeyEvent.Key == Key.DeleteChar) {
+
+				var toDelete = treeView.SelectedObject;
+
+				if(toDelete == null)
+					return;
+				
+				obj.Handled = true;
+
+				// if it is a root object remove it
+				if(treeView.Objects.Contains(toDelete)) {
+					treeView.Remove(toDelete);
+				}
+				else {
+					var parent = treeView.GetParent(toDelete);
+
+					if(parent == null)
+						MessageBox.ErrorQuery("Could not delete",$"Parent of '{toDelete}' was unexpectedly null","Ok");
+					else {
+						//update the model
+						parent.Children.Remove(toDelete);
+
+						//refresh the tree
+						treeView.RefreshObject(parent);
+					}
+				}
+			}
+		}
+
+		private void RenameNode ()
+		{
+			var node = treeView.SelectedObject;
+
+			if(node != null) {
+				if(GetText("Text","Enter text for node:",node.Text,out string entered)) {
+					node.Text = entered;
+					treeView.RefreshObject(node);
+				}
+			}
+		}
+
+		private void AddRootNode ()
+		{
+			if(GetText("Text","Enter text for node:","",out string entered)) {
+				treeView.AddObject(new TreeNode(entered));
+			}
+		}
+
+		private void AddChildNode()
+		{
+			var node = treeView.SelectedObject;
+
+			if(node != null) {
+				if(GetText("Text","Enter text for node:","",out string entered)) {
+					node.Children.Add(new TreeNode(entered));
+					treeView.RefreshObject(node);
+				}
+			}
+		}
+
+		private bool GetText(string title, string label, string initialText, out string enteredText)
+		{
+			bool okPressed = false;
+
+			var ok = new Button ("Ok", is_default: true);
+			ok.Clicked += () => { okPressed = true; Application.RequestStop (); };
+			var cancel = new Button ("Cancel");
+			cancel.Clicked += () => { Application.RequestStop (); };
+			var d = new Dialog (title, 60, 20, ok, cancel);
+
+			var lbl = new Label() {
+				X = 0,
+				Y = 1,
+				Text = label
+			};
+
+			var tf = new TextField()
+				{
+					Text = initialText,
+					X = 0,
+					Y = 2,
+					Width = Dim.Fill()
+				};
+			
+			d.Add (lbl,tf);
+			tf.SetFocus();
+
+			Application.Run (d);
+
+			enteredText = okPressed? tf.Text.ToString() : null;
+			return okPressed;
+		}
+
+		private void Quit ()
+		{
+			Application.RequestStop ();
+		}
+	}
+}

+ 2 - 6
UICatalog/Scenarios/TreeUseCases.cs

@@ -43,7 +43,7 @@ namespace UICatalog.Scenarios {
         }
 
         // Your data class
-		private class House : ITreeNode {
+		private class House : TreeNode {
 
 
             // Your properties
@@ -59,14 +59,10 @@ namespace UICatalog.Scenarios {
 				return Address;
 			}
 		}
-		private class Room : ITreeNode{
+		private class Room : TreeNode{
             
             public string Name {get;set;}
 
-
-            // Rooms have no sub objects
-			public IList<ITreeNode> Children => new List<ITreeNode>();
-
 			public override string ToString ()
 			{
 				return Name;

+ 2 - 2
docfx/articles/treeview.md

@@ -34,7 +34,7 @@ Having to create a bunch of TreeNode objects can be a pain especially if you alr
 
 ```csharp
 // Your data class
-private class House : ITreeNode {
+private class House : TreeNode {
 
 
     // Your properties
@@ -52,7 +52,7 @@ private class House : ITreeNode {
 }
 
 // Your other data class
-private class Room : ITreeNode{
+private class Room : TreeNode{
     
     public string Name {get;set;}