Adds CollectionNavigator to enable searching ListView/TreeView with keyboard#2132
Adds CollectionNavigator to enable searching ListView/TreeView with keyboard#2132tig merged 37 commits intogui-cs:developfrom
Conversation
|
This is cool! It would be good if we had the same behaviour in both places. I like the ability to search on more than just first letter but I also like being able to loop through. I notice that Windows Explorer seems to support both at the same time. It must detect that there is nothing starting 'bb' and therefore instead take you to the second 'b' entry. Given this feature could be useful in TreeView, ListView and other places (e.g. RadioView), I think we should make it a standalone class not tied to the Something like /// <summary>
/// Changes the index in a collection based on a letter key pressed
/// and the current state
/// </summary>
class LetterBasedCollectionNavigator : ICollectionNavigator
{
string state;
DateTime lastKeystroke;
public StringComparer Comparer { get; set; } = StringComparer.InvariantCultureIgnoreCase;
int CalculateNewIndex(IEnumerable<string> collection, int currentIndex, ConsoleKey newKey)
{
// TODO: append/replace
throw new NotImplementedException ();
}
}This would also handily centralise the "timer and history logic" (currently in |
Digging into this... wow, it can be complicated. And everyone does it differently. The tree views in Visual Studio (e.g. Solution Explorer):
The VS Code list:
The Windows ListBox control (e.g. Explorer) (and I think the windows Tree uses same logic)
It seems the Windows & VS Code implementations work like my draft code does: Sets a timer when the user starts typing capturing the search string. However, Windows does do what @tznind suggested above with "t", "t", "t". The VSCode implementation is I definitely prefer the VS implementation, as it somehow does exactly what you'd want. It is sophisticated, likely recognizing the current search string matches multiple items until a pause in typing is detected. I sure wish VisualStudio was open source ;-). |
|
I've had a little look tonight into writing an algorithm that behaves the same as Windows Explorer example. Here is a gist containing it: https://gist.github.com/tznind/d7ecaa5156a63a0a66dee03c29102b7d Its only a first stab but I've included tests for it and can add some more tomorrow. Might look into adding the whole "tex", "tex" bit but that is definitely a step up in terms of complexity. |
Freaking awesome. I've been thinking about this all day. This is the kind of thing that gives me joy relative to this project; a great excuse to get seme intellectual stimulation I'd not normally be getting ;-). Thoughts: "letter-based collection navigator" ain't quite the right term. If the collection includes "@ckindel", the user should be able to type the How about "keystroke-based collection navigtor" or "keyboard collection navigator"? On which keys to monitor: My code was >= 32 && < 127. I think 32-255 is probably right. Using For Terminal.Gui we have the I really, really, like the way VS behaves; the Windows behavior just feels lame in comparison. I'm curious what Finder on the Mac does. |
How about "unicode-based collection navigator"
How to deal with other unicode characters like, Chinese, Korean, etc...? |
Me too! I love nice self contained problems!
Good point, in the light of day its a bit janky. I've renamed it
I have switched to using
Definetly need to think about that! I'd like to start with getting the algorithm right then we can worry about porting to |
|
@tznind at bar at airport now for a few hours. Wanna submit your gist as a PR to my branch so I can party on it? |
|
Ok I think I have done this right: |
Add SearchCollectionNavigator
It basically works. You can see I started adding TreeView as well (to the new Scnenario). But then my flight was landing ;-) Let me know what you think. |
|
@tig I see this strange behavior on a disabled menu item after clicked on it and moving the mouse. It stay selected and it shouldn't. |
I think that's a bug in Menu where it's not clearing correctly? |
|
Ok, more updates... I still haven't made TreeView work, but in testing the Scenario list in UI Catalog I realized THAT implementation of This actually simplifies the code in UI Catalog and negates the need for Check it out! |
For sure it is. It must maintain the last menu item selected until the mouse moves to a enabled menu item. I'll open a new issue. |
|
@tznind Wanna take a look at modifying TreeView to use this now. Note the scenario I added has a TreeView in it that you can use to make progress... ;-) |
|
@BDisp and @tznind (and anyone else paying attention), this PR is ready for review! @tznind - I think the weirdness you were seeing with regards to repeated chars is addressed. I took a slightly different approach (before I saw your PR). I've beat on this a ton, and I think it works well. But the more eyes the better! |
|
I don't like the behavior when quitting a scenario it not preserve the last selected item. It's a regression on the |
|
I think it may have a little more time to search for a word. While I'm typing faster sometimes starts a new search. For e.g. I tried typing |
I agree. Its currently 250ms. I think we could increase it to 500ms or more maybe. Also I think we should allow for customising if possible, its just a polite thing to do. Also potentially handy for accessibility use cases.
One thing that it currently does that is different from Explorer is that as soon as you hit a wrong key then it jumps to that index. So if you type We might be able to update the behaviour so that a 'wrong' keypress ( Let me know if that wall of text was confusing ;)
This should already be the case. There are several calls to |
In my opinion if the user typed before the elapsed time is reached, then the should be restarted to the default value and waiting for the user input. If the elapsed time is reached it means that the user doesn't type anything and clear the search for start a new searching. Increment a lot can force user to wait to the elapsed time is reached to start typing a new search. I think restarting the timer with the current word id the better solution.
I meaning if we are typing the right word. If we type another character that is find the behavior must another. For e.g. if the word doesn't exist before the elapsed time is reached then the last found is remained. If the user type after the elapsed time, then a new search is started.
A little :-)
Ok let me know when done. Thanks both for yours great work. |
This is already how it works. There is no 'incrementing'. Every keystroke resets |
Yea, I fixed this an then somehow broke it again. I'll fix it later. |
|
Delay is now 500ms and TypingDelay is public |
I think you are right and I'd like to fix this before we merge. VS2022 (Solution Explorer) does the right thing IMO. |
Now I remember: #2140 needs to be fixed and then this will work correctly. I'm working on a PR for it now. |
|
Ok, I think I fixed the 'wrong' key behavior! Give her a whirl! |
Very much better. Congrats. Thanks. |
|
This is working great, very natural feeling! Love the new Label showing the search too, very nice. |


I've wanted this forever...
With this PR users can now start typing with any ListView in focus and the first item that matches what they are typing is selected.
The core code I put in ProcessKeystroke was generated by GitHub CoPilot. Blew me away. I'm guessing someone else already did this in a fork or app.
@BDisp and @tznind - I'd love your feedback on this. Especially the new
IListDataSoruceSearchableinterface:I also re-wrote much of the API documentation to be more clear.
I've not written any unit tests for it yet. But will.
Cheers!