Browse Source

added docs on generic treeview

tznind 4 years ago
parent
commit
518e58d90d

+ 84 - 0
UICatalog/Scenarios/TreeUseCases.cs

@@ -25,6 +25,8 @@ namespace UICatalog.Scenarios {
 				new MenuBarItem ("_Scenarios", new MenuItem [] {
 					new MenuItem ("_Simple Nodes", "", () => LoadSimpleNodes()),
 					new MenuItem ("_Rooms", "", () => LoadRooms()),
+					new MenuItem ("_Armies With Builder", "", () => LoadArmies(false)),
+					new MenuItem ("_Armies With Delegate", "", () => LoadArmies(true)),
 				}),
 			});
 			
@@ -101,6 +103,88 @@ namespace UICatalog.Scenarios {
             currentTree = tree;
 		}
 
+
+
+        private abstract class GameObject
+        {
+
+        }
+        private class Army : GameObject
+        {
+            public string Designation {get;set;}
+            public List<Unit> Units {get;set;}
+
+
+			public override string ToString ()
+			{
+				return Designation;
+			}
+        }
+
+        private class Unit : GameObject
+        {
+            public string Name {get;set;}
+			public override string ToString ()
+			{
+				return Name;
+			}
+        }
+
+		private class GameObjectTreeBuilder : ITreeBuilder<GameObject> {
+			public bool SupportsCanExpand => true;
+
+			public bool CanExpand (GameObject model)
+			{
+				return model is Army;
+			}
+
+			public IEnumerable<GameObject> GetChildren (GameObject model)
+			{
+                if(model is Army a)
+                    return a.Units;
+
+				return Enumerable.Empty<GameObject>();
+			}
+		}
+
+
+		private void LoadArmies(bool useDelegate)
+		{
+            var army1 = new Army()
+            {
+                Designation = "3rd Infantry",
+                Units = new List<Unit>{
+                    new Unit(){Name = "Orc"},
+                    new Unit(){Name = "Troll"},
+                    new Unit(){Name = "Goblin"},
+                }
+            };
+
+            if(currentTree != null)
+                Win.Remove(currentTree);
+
+			var tree = new TreeView<GameObject>()
+			{
+                X = 0,
+                Y = 0,
+				Width = 40,
+				Height = 20
+			};
+
+            if(useDelegate){
+                tree.TreeBuilder = new DelegateTreeBuilder<GameObject>((o)=>o is Army a ? a.Units : Enumerable.Empty<GameObject>());
+            }
+            else{
+                tree.TreeBuilder = new GameObjectTreeBuilder();
+            }
+
+            Win.Add(tree);
+
+            tree.AddObject(army1);
+
+            currentTree = tree;
+		}
+
 		private void Quit ()
 		{
 			Application.RequestStop ();

+ 12 - 0
UICatalog/Scenarios/TreeViewFileSystem.cs

@@ -26,6 +26,7 @@ namespace UICatalog.Scenarios {
 		private MenuItem miColoredSymbols;
 		private MenuItem miInvertSymbols;
 		private MenuItem miUnicodeSymbols;
+		private MenuItem miFullPaths;
 		private Terminal.Gui.Attribute green;
 		private Terminal.Gui.Attribute red;
 
@@ -52,6 +53,7 @@ namespace UICatalog.Scenarios {
 					null /*separator*/,
 					miColoredSymbols = new MenuItem ("_ColoredSymbols", "", () => ShowColoredExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
 					miInvertSymbols = new MenuItem ("_InvertSymbols", "", () => InvertExpandableSymbols()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
+					miFullPaths = new MenuItem ("_FullPaths", "", () => SetFullName()){Checked = false, CheckType = MenuItemCheckStyle.Checked},
 				}),
 			});
 			Top.Add (menu);
@@ -171,6 +173,16 @@ namespace UICatalog.Scenarios {
 			treeViewNodes.SetNeedsDisplay();
 		}
 
+		private void SetFullName()
+		{
+			miFullPaths.Checked = !miFullPaths.Checked;
+
+			if(miFullPaths.Checked)
+				treeViewFiles.AspectGetter = (f)=>f.FullName;
+			else
+				treeViewFiles.AspectGetter = (f)=>f.Name;
+		}
+
 
 		private ITreeNode CreateSimpleRoot ()
 		{

+ 104 - 3
docfx/articles/treeview.md

@@ -96,10 +96,111 @@ tree.AddObject(myHouse);
 
 ```
 
-Alternatively you can simply tell the tree how the objects relate to one another by implementing `ITreeBuilder`.  This is a good option if you don't have control of the data objects you are working with:
+Alternatively you can simply tell the tree how the objects relate to one another by implementing `ITreeBuilder<T>`.  This is a good option if you don't have control of the data objects you are working with.
+
+## TreeView<T>
+
+The generic `Treeview<T>` allows you to store any object hierarchy where nodes implement Type T.  For example if you are working with `DirectoryInfo` and `FileInfo` objects then you could create a `TreeView<FileSystemInfo>`.  If you don't have a shared interface/base class for all nodes you can still declare a `TreeView<object>`.
+
+In order to use `TreeView<T>` you need to tell the tree how objects relate to one another (who are children of who).  To do this you must provide an `ITreeBuilder<T>`.
+
+
+### Implementing ITreeBuilder<T>
+
+Consider a simple data model that already exists in your program:
+
+```csharp
+private abstract class GameObject
+{
+
+}
+private class Army : GameObject
+{
+    public string Designation {get;set;}
+    public List<Unit> Units {get;set;}
+
+
+    public override string ToString ()
+    {
+        return Designation;
+    }
+}
+
+private class Unit : GameObject
+{
+    public string Name {get;set;}
+    public override string ToString ()
+    {
+        return Name;
+    }
+}
 
 ```
-TODO
+
+An `ITreeBuilder<T>` for these classes might look like:
+
+```csharp
+
+private class GameObjectTreeBuilder : ITreeBuilder<GameObject> {
+    public bool SupportsCanExpand => true;
+
+    public bool CanExpand (GameObject model)
+    {
+        return model is Army;
+    }
+
+    public IEnumerable<GameObject> GetChildren (GameObject model)
+    {
+        if(model is Army a)
+            return a.Units;
+
+        return Enumerable.Empty<GameObject>();
+    }
+}
 ```
 
-## TreeView<T>
+To use the builder in a tree you would use:
+
+```
+var army1 = new Army()
+{
+    Designation = "3rd Infantry",
+    Units = new List<Unit>{
+        new Unit(){Name = "Orc"},
+        new Unit(){Name = "Troll"},
+        new Unit(){Name = "Goblin"},
+    }
+};
+
+var tree = new TreeView<GameObject>()
+{
+    X = 0,
+    Y = 0,
+    Width = 40,
+    Height = 20,
+    TreeBuilder = new GameObjectTreeBuilder()
+};
+
+
+tree.AddObject(army1);
+```
+
+Alternatively you can use `DelegateTreeBuilder<T>` instead of implementing your own `ITreeBuilder<T>`.  For example:
+
+```
+tree.TreeBuilder = new DelegateTreeBuilder<GameObject>(
+    (o)=>o is Army a ? a.Units 
+        : Enumerable.Empty<GameObject>());
+```
+
+## Node Text and ToString
+
+The default behaviour of TreeView is to use the `ToString` method on the objects for rendering.  You can customise this by changing the `AspectGetter`.  For example:
+
+```
+treeViewFiles.AspectGetter = (f)=>f.FullName;
+```
+
+
+
+