Browse Source

Fixed listView issue.
Added ability to mark/unmark all to ListView

Tig 9 months ago
parent
commit
b766e4efdd
2 changed files with 61 additions and 12 deletions
  1. 55 2
      Terminal.Gui/Views/ListView.cs
  2. 6 10
      UnitTests/Views/ListViewTests.cs

+ 55 - 2
Terminal.Gui/Views/ListView.cs

@@ -147,7 +147,7 @@ public class ListView : View, IDesignable
 
                                         if (OnOpenSelectedItem ())
                                         {
-                                                return true;
+                                            return true;
                                         }
 
                                         return false;
@@ -189,6 +189,7 @@ public class ListView : View, IDesignable
                                         return !SetFocus ();
                                     });
 
+        AddCommand (Command.SelectAll, (ctx) => MarkAll((bool)ctx.KeyBinding?.Context!));
 
         // Default keybindings for all ListViews
         KeyBindings.Add (Key.CursorUp, Command.Up);
@@ -205,6 +206,13 @@ public class ListView : View, IDesignable
         KeyBindings.Add (Key.Home, Command.Start);
 
         KeyBindings.Add (Key.End, Command.End);
+
+        // Key.Space is already bound to Command.Select; this gives us select then move down
+        KeyBindings.Add (Key.Space.WithShift, [Command.Select, Command.Down]);
+
+        // Use the form of Add that lets us pass context to the handler
+        KeyBindings.Add (Key.A.WithCtrl, new KeyBinding ([Command.SelectAll], KeyBindingScope.Focused, true));
+        KeyBindings.Add (Key.U.WithCtrl, new KeyBinding ([Command.SelectAll], KeyBindingScope.Focused, false));
     }
 
     /// <summary>Gets or sets whether this <see cref="ListView"/> allows items to be marked.</summary>
@@ -370,6 +378,31 @@ public class ListView : View, IDesignable
         }
     }
 
+    /// <summary>
+    ///     If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
+    ///     marks all items.
+    /// </summary>
+    /// <param name="mark"><see langword="true"/> marks all items; otherwise unmarks all items.</param>
+    /// <returns><see langword="true"/> if marking was successful.</returns>
+    public bool MarkAll (bool mark)
+    {
+        if (!_allowsMarking)
+        {
+            return false;
+        }
+
+        if (AllowsMultipleSelection)
+        {
+            for (var i = 0; i < Source.Count; i++)
+            {
+                Source.SetMark (i, mark);
+            }
+            return true;
+        }
+
+        return false;
+    }
+
     /// <summary>
     ///     If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
     ///     unmarks all marked items other than <see cref="SelectedItem"/>.
@@ -805,8 +838,28 @@ public class ListView : View, IDesignable
     /// <inheritdoc/>
     protected override bool OnKeyDown (Key a)
     {
+        // If marking is enabled and the user presses the space key don't let CollectionNavigator
+        // at it
+        if (AllowsMarking)
+        {
+            var keys = KeyBindings.GetKeysFromCommands (Command.Select);
+
+            if (keys.Contains (a))
+            {
+                return false;
+            }
+
+            keys = KeyBindings.GetKeysFromCommands ([Command.Select, Command.Down]);
+
+            if (keys.Contains (a))
+            {
+                return false;
+            }
+
+        }
+
         // Enable user to find & select an item by typing text
-        if (CollectionNavigatorBase.IsCompatibleKey (a) || (!AllowsMarking && a == Key.Space))
+        if (CollectionNavigatorBase.IsCompatibleKey (a))
         {
             int? newItem = KeystrokeNavigator?.GetNextMatchingItem (SelectedItem, (char)a);
 

+ 6 - 10
UnitTests/Views/ListViewTests.cs

@@ -522,7 +522,7 @@ Item 6",
     }
 
     [Fact]
-    public void ListViewSelectThenDown ()
+    public void AllowsMarking_True_SpaceWithShift_SelectsThenDown ()
     {
         var lv = new ListView { Source = new ListWrapper<string> (["One", "Two", "Three"]) };
         lv.AllowsMarking = true;
@@ -537,12 +537,8 @@ Item 6",
         Assert.False (lv.Source.IsMarked (1));
         Assert.False (lv.Source.IsMarked (2));
 
-        lv.KeyBindings.Add (Key.Space.WithShift, Command.Select, Command.Down);
-
-        Key key = Key.Space.WithShift;
-
         // view should indicate that it has accepted and consumed the event
-        Assert.True (lv.NewKeyDownEvent (key));
+        Assert.True (lv.NewKeyDownEvent (Key.Space.WithShift));
 
         // first item should now be selected
         Assert.Equal (0, lv.SelectedItem);
@@ -553,7 +549,7 @@ Item 6",
         Assert.False (lv.Source.IsMarked (2));
 
         // Press key combo again
-        Assert.True (lv.NewKeyDownEvent (key));
+        Assert.True (lv.NewKeyDownEvent (Key.Space.WithShift));
 
         // second item should now be selected
         Assert.Equal (1, lv.SelectedItem);
@@ -564,21 +560,21 @@ Item 6",
         Assert.False (lv.Source.IsMarked (2));
 
         // Press key combo again
-        Assert.True (lv.NewKeyDownEvent (key));
+        Assert.True (lv.NewKeyDownEvent (Key.Space.WithShift));
         Assert.Equal (2, lv.SelectedItem);
         Assert.True (lv.Source.IsMarked (0));
         Assert.True (lv.Source.IsMarked (1));
         Assert.False (lv.Source.IsMarked (2));
 
         // Press key combo again
-        Assert.True (lv.NewKeyDownEvent (key));
+        Assert.True (lv.NewKeyDownEvent (Key.Space.WithShift));
         Assert.Equal (2, lv.SelectedItem); // cannot move down any further
         Assert.True (lv.Source.IsMarked (0));
         Assert.True (lv.Source.IsMarked (1));
         Assert.True (lv.Source.IsMarked (2)); // but can toggle marked
 
         // Press key combo again 
-        Assert.True (lv.NewKeyDownEvent (key));
+        Assert.True (lv.NewKeyDownEvent (Key.Space.WithShift));
         Assert.Equal (2, lv.SelectedItem); // cannot move down any further
         Assert.True (lv.Source.IsMarked (0));
         Assert.True (lv.Source.IsMarked (1));