浏览代码

Add SearchCollectionNavigator to TreeView

tznind 2 年之前
父节点
当前提交
79f82d1c4c
共有 3 个文件被更改,包括 51 次插入14 次删除
  1. 12 0
      Terminal.Gui/Core/SearchCollectionNavigator.cs
  2. 1 1
      Terminal.Gui/Views/ListView.cs
  3. 38 13
      Terminal.Gui/Views/TreeView.cs

+ 12 - 0
Terminal.Gui/Core/SearchCollectionNavigator.cs

@@ -129,5 +129,17 @@ namespace Terminal.Gui {
 			lastKeystroke = DateTime.MinValue;
 
 		}
+
+		/// <summary>
+		/// Returns true if <paramref name="kb"/> is a searchable key
+		/// (e.g. letters, numbers etc) that is valid to pass to to this
+		/// class for search filtering
+		/// </summary>
+		/// <param name="kb"></param>
+		/// <returns></returns>
+		public static bool IsCompatibleKey (KeyEvent kb)
+		{
+			return !kb.IsAlt && !kb.IsCapslock && !kb.IsCtrl && !kb.IsScrolllock && !kb.IsNumlock;
+		}
 	}
 }

+ 1 - 1
Terminal.Gui/Views/ListView.cs

@@ -437,7 +437,7 @@ namespace Terminal.Gui {
 			}
 
 			// Enable user to find & select an item by typing text
-			if (!kb.IsAlt && !kb.IsCapslock && !kb.IsCtrl && !kb.IsScrolllock && !kb.IsNumlock) {
+			if (SearchCollectionNavigator.IsCompatibleKey(kb)) {
 				if (navigator == null) {
 					// BUGBUG: If items change this needs to be recreated.
 					navigator = new SearchCollectionNavigator (source.ToList ().Cast<object> ());

+ 38 - 13
Terminal.Gui/Views/TreeView.cs

@@ -140,12 +140,12 @@ namespace Terminal.Gui {
 		/// <value></value>
 		public MouseFlags? ObjectActivationButton { get; set; } = MouseFlags.Button1DoubleClicked;
 
-		
+
 		/// <summary>
 		/// Delegate for multi colored tree views.  Return the <see cref="ColorScheme"/> to use
 		/// for each passed object or null to use the default.
 		/// </summary>
-		public Func<T,ColorScheme> ColorGetter {get;set;}
+		public Func<T, ColorScheme> ColorGetter { get; set; }
 
 		/// <summary>
 		/// Secondary selected regions of tree when <see cref="MultiSelect"/> is true
@@ -220,6 +220,7 @@ namespace Terminal.Gui {
 		public AspectGetterDelegate<T> AspectGetter { get; set; } = (o) => o.ToString () ?? "";
 
 		CursorVisibility desiredCursorVisibility = CursorVisibility.Invisible;
+		private SearchCollectionNavigator searchCollectionNavigator;
 
 		/// <summary>
 		/// Get / Set the wished cursor when the tree is focused.
@@ -227,7 +228,7 @@ namespace Terminal.Gui {
 		/// Defaults to <see cref="CursorVisibility.Invisible"/>
 		/// </summary>
 		public CursorVisibility DesiredCursorVisibility {
-			get { 
+			get {
 				return MultiSelect ? desiredCursorVisibility : CursorVisibility.Invisible;
 			}
 			set {
@@ -576,19 +577,43 @@ namespace Terminal.Gui {
 				return false;
 			}
 
-			// if it is a single character pressed without any control keys
-			if (keyEvent.KeyValue > 0 && keyEvent.KeyValue < 0xFFFF) {
+			try {
+
+				// First of all deal with any registered keybindings
+				var result = InvokeKeybindings (keyEvent);
+				if (result != null) {
+					return (bool)result;
+				}
+
+				// If not a keybinding, is the key a searchable key press?
+				if (SearchCollectionNavigator.IsCompatibleKey (keyEvent) && AllowLetterBasedNavigation) {
+
+					IReadOnlyCollection<Branch<T>> map;
+
+					// If there has been a call to InvalidateMap since the last time we allocated a 
+					// SearchCollectionNavigator then we need a new one to reflect the new exposed
+					// tree state
+					if (cachedLineMap == null || searchCollectionNavigator == null) {
+						 map = BuildLineMap ();
+						searchCollectionNavigator = new SearchCollectionNavigator (map.Select (b => AspectGetter (b.Model)).ToArray ());
+					}
+					else {
+						// we still need the map, handily its the cached one which means super fast access
+						map = BuildLineMap ();
+					}
+					
+					// Find the current selected object within the tree
+					var current = map.IndexOf (b => b.Model == SelectedObject);
+					var newIndex = searchCollectionNavigator.CalculateNewIndex (current, (char)keyEvent.KeyValue);
+
+					if (newIndex != -1) {
+						SelectedObject = map.ElementAt (newIndex).Model;
+						SetNeedsDisplay ();
+					}
 
-				if (char.IsLetterOrDigit ((char)keyEvent.KeyValue) && AllowLetterBasedNavigation && !keyEvent.IsShift && !keyEvent.IsAlt && !keyEvent.IsCtrl) {
-					AdjustSelectionToNextItemBeginningWith ((char)keyEvent.KeyValue);
 					return true;
 				}
-			}
 
-			try {
-				var result = InvokeKeybindings (keyEvent);
-				if (result != null)
-					return (bool)result;
 			} finally {
 
 				PositionCursor ();
@@ -626,7 +651,7 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// <param name="toFind"></param>
 		/// <returns></returns>
-		public int? GetObjectRow(T toFind)
+		public int? GetObjectRow (T toFind)
 		{
 			var idx = BuildLineMap ().IndexOf (o => o.Model.Equals (toFind));