Browse Source

Added ObjectActivated event

tznind 4 years ago
parent
commit
ec85340285
2 changed files with 154 additions and 10 deletions
  1. 64 0
      Terminal.Gui/Views/TreeView.cs
  2. 90 10
      UnitTests/TreeViewTests.cs

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

@@ -332,6 +332,17 @@ namespace Terminal.Gui {
 			}
 		}
 
+
+		/// <summary>
+		/// This event is raised when an object is activated e.g. by double clicking or pressing <see cref="ObjectActivationKey"/>
+		/// </summary>
+		public event Action<ObjectActivatedEventArgs<T>> ObjectActivated;
+
+		/// <summary>
+		/// Key which when pressed triggers <see cref="TreeView{T}.ObjectActivated"/>.  Defaults to Enter
+		/// </summary>
+		public Key ObjectActivationKey {get;set;} = Key.Enter;
+
 		/// <summary>
 		/// Secondary selected regions of tree when <see cref="MultiSelect"/> is true
 		/// </summary>
@@ -648,7 +659,20 @@ namespace Terminal.Gui {
 		/// <inheritdoc/>
 		public override bool ProcessKey (KeyEvent keyEvent)
 		{
+			if(keyEvent.Key == ObjectActivationKey)
+			{
+				 var o = SelectedObject;
+
+				 if(o != null){
+				 	OnObjectActivated(new ObjectActivatedEventArgs<T>(this,o));
+					
+					PositionCursor ();
+					return true;
+				 }				
+			}
+
 			switch (keyEvent.Key) {
+				
 				case Key.CursorRight:
 					Expand(SelectedObject);
 				break;
@@ -696,6 +720,15 @@ namespace Terminal.Gui {
 			return true;
 		}
 
+		/// <summary>
+		/// Raises the <see cref="ObjectActivated"/> event
+		/// </summary>
+		/// <param name="e"></param>
+		protected void OnObjectActivated(ObjectActivatedEventArgs<T> e)
+		{
+			ObjectActivated?.Invoke(e);
+		}
+
 		///<inheritdoc/>
 		public override bool MouseEvent (MouseEvent me)
 		{
@@ -1124,6 +1157,37 @@ namespace Terminal.Gui {
 		}
 	}
 
+	/// <summary>
+	/// Event args for the <see cref="TreeView{T}.ObjectActivated"/> event
+	/// </summary>
+	/// <typeparam name="T"></typeparam>
+	public class ObjectActivatedEventArgs<T> where T : class {
+
+		/// <summary>
+		/// The tree in which the activation occurred
+		/// </summary>
+		/// <value></value>
+		public TreeView<T> Tree {get;}
+
+		/// <summary>
+		/// The object that was selected at the time of activation
+		/// </summary>
+		/// <value></value>
+		public T ActivatedObject {get;}
+
+
+		/// <summary>
+		/// Creates a new instance documenting activation of the <paramref name="activated"/> object
+		/// </summary>
+		/// <param name="tree">Tree in which the activation is happening</param>
+		/// <param name="activated">What object is being activated</param>
+		public ObjectActivatedEventArgs(TreeView<T> tree, T activated)
+		{
+			Tree = tree;
+			ActivatedObject = activated;
+		}
+	}
+
 	class TreeSelection<T> where T : class {
 
 		public Branch<T> Origin {get;}

+ 90 - 10
UnitTests/TreeViewTests.cs

@@ -103,9 +103,7 @@ namespace UnitTests {
 			var tree = CreateTree(out Factory f, out Car car1, out _);
 			tree.Bounds = new Rect(0,0,10,10);
 			
-			var driver = new FakeDriver ();
-			Application.Init (driver, new FakeMainLoop (() => FakeConsole.ReadKey (true)));
-			driver.Init (() => { });
+			InitFakeDriver();
 
 			//-+Factory
 			Assert.Equal(9,tree.GetContentWidth(true));
@@ -129,9 +127,7 @@ namespace UnitTests {
 			// control only allows 1 row to be viewed at once
 			tree.Bounds = new Rect(0,0,20,1);
 			
-			var driver = new FakeDriver ();
-			Application.Init (driver, new FakeMainLoop (() => FakeConsole.ReadKey (true)));
-			driver.Init (() => { });
+			InitFakeDriver();
 
 			//-+Factory
 			Assert.Equal(9,tree.GetContentWidth(true));
@@ -449,14 +445,12 @@ namespace UnitTests {
 
 			tree.SelectedObject = root;
 
-			Assert.Equal(1,tree.GetAllSelectedObjects().Count());
-			Assert.Contains(root,tree.GetAllSelectedObjects());
+			Assert.Single(tree.GetAllSelectedObjects(),root);
 
 			// move selection down 1
 			tree.AdjustSelection(1,false);
 
-			Assert.Equal(1,tree.GetAllSelectedObjects().Count());
-			Assert.Contains(l1,tree.GetAllSelectedObjects());
+			Assert.Single(tree.GetAllSelectedObjects(),l1);
 
 			// expand selection down 2 (e.g. shift down twice)
 			tree.AdjustSelection(1,true);
@@ -473,6 +467,85 @@ namespace UnitTests {
 			Assert.Empty(tree.GetAllSelectedObjects());
 		}
 
+		[Fact]
+		public void ObjectActivated_Called()
+		{
+			var tree = CreateTree(out Factory f, out Car car1, out _);
+
+			InitFakeDriver();
+
+			object activated = null;
+			bool called = false;
+
+			// register for the event
+			tree.ObjectActivated += (s)=>
+			{
+				activated = s.ActivatedObject;
+				called = true;
+			};
+
+			Assert.False(called);
+			
+			// no object is selected yet so no event should happen
+			tree.ProcessKey(new KeyEvent(Key.Enter,new KeyModifiers()));
+
+			Assert.Null(activated);
+			Assert.False(called);
+
+			// down to select factory
+			tree.ProcessKey(new KeyEvent(Key.CursorDown,new KeyModifiers()));
+
+			tree.ProcessKey(new KeyEvent(Key.Enter,new KeyModifiers()));
+			
+			Assert.True(called);
+			Assert.Same(f,activated);			
+		}
+
+
+		[Fact]
+		public void ObjectActivated_CustomKey()
+		{
+			var tree = CreateTree(out Factory f, out Car car1, out _);
+			
+			InitFakeDriver();
+
+			tree.ObjectActivationKey = Key.Delete;
+			object activated = null;
+			bool called = false;
+
+			// register for the event
+			tree.ObjectActivated += (s)=>
+			{
+				activated = s.ActivatedObject;
+				called = true;
+			};
+
+			Assert.False(called);
+			
+			// no object is selected yet so no event should happen
+			tree.ProcessKey(new KeyEvent(Key.Enter,new KeyModifiers()));
+
+			Assert.Null(activated);
+			Assert.False(called);
+
+			// down to select factory
+			tree.ProcessKey(new KeyEvent(Key.CursorDown,new KeyModifiers()));
+
+			tree.ProcessKey(new KeyEvent(Key.Enter,new KeyModifiers()));
+			
+			// Enter is not the activation key in this unit test
+			Assert.Null(activated);
+			Assert.False(called);
+
+			// Delete is the activation key in this test so should result in activation occurring
+			tree.ProcessKey(new KeyEvent(Key.Delete,new KeyModifiers()));
+
+			Assert.True(called);
+			Assert.Same(f,activated);
+			
+		}
+
+
 
 		/// <summary>
 		/// Simulates behind the scenes changes to an object (which children it has) and how to sync that into the tree using <see cref="TreeView.RefreshObject(object, bool)"/>
@@ -527,5 +600,12 @@ namespace UnitTests {
 				return obj is EqualityTestObject eto && Equals(Name, eto.Name);
 			}
 		}
+
+		private void InitFakeDriver()
+		{
+			var driver = new FakeDriver ();
+			Application.Init (driver, new FakeMainLoop (() => FakeConsole.ReadKey (true)));
+			driver.Init (() => { });
+		}
 	}
 }