-
Notifications
You must be signed in to change notification settings - Fork 696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Struggling to understand the new TabStop functionality along with new Scrolling behavior #3831
Comments
First, thank you for posting all this! I'm eager to both help you and ensure that the new design actually works and makes devs happy. It's entirely possible you've found real issues that need to be addressed!! The tab order in v2 is very simple: The order is the order in which the Views exist in the
I'm a bit confused by the base/derived stuff going on here. Perhaps your issue is you should be using composition instead of inheritance. I'd have:
All focusable views must have |
Please see #3820, which will likely be merged to v2_develop today. It completely revamps ScrollBar and scrolling and the new examples (and
Why do you need to know if a control is visible or not? Assuming there's actually a good reason, the algo would be something like this: bool isVisible = Viewport.Contains(isVisibleView.Frame.Location) && Viewport.Contains(isVisibleView.Location with { X = isVisibleView.X + isVisibleView.Width, Y = isVisibleView.Y + isVisibleView.Height); This would be true IFF the entire subview was visible. The algo for determining if just a part is visible is much tricker. I'd use the new HOWEVER, there is a TON of complexity in doing something USEFUL with this info. That complexity is what has prevented me from investing in an API. It's a really hard problem to make it completely general purpose. ... which brings me back to WHY? Why do you think you need such functionality? |
thank you for the reply! I don't need to know if the control is visible or not if the underlying scrolling mechanism detects that a control which just received focus is not visible (because it is above/below the current visible area of the screen, and automatically scrolls to make that control visible. I do need to know that if i have to control the scrolling myself, so i know whether or not i needs to scroll the view so that the control is visible. |
Thank you for that insight. I will think about using a composite methodology to construct the overall detail view. Basically, each detail view "inherits" some common properties from the parent. For example, every item which can be saved in the application has an "Item Name", so i have a base I need to think about where i might use that common view type (the base class) in other parts of the application, but a composite pattern might work. |
I just ported your code to the latest v2_develop. Would you like a PR? Not sure everything is working because I can't get past login, but it should help. |
Before you go rearchitecting, lets get to the point where I can actually run the thing and poke around. This is a great opportunity for me to ensure I understand how a "real" dev (not one of us maintainers) does things naturally! |
Hi - sure, i have some test credentials that you can use. The app is in a tricky state right now, but you should be able to see the two issues on one of the detail forms. What you should do it go to Vault - Connect and put these credentials in "[email protected]" with password "otGZkrC7kWPd6g" (both without quotes). You should then see the vault screen loaded with some test items. The top one should be highlighted and you can press 'F3' to edit that item. Since that is a item of type "Login", the detail form that is loaded is a LoginDetailView. You will see that the first control to get focus is the combo box for "Folder". Pressing Tab will move the focus back to Item Name text field, etc. After 3-4 tabs, the cursor will disappear. That is because Focus has skipped all the middle controls and gone down past the bottom of the view port, to the button for "New Custom Field". Then it goes to "Save", then "Cancel", then back up to the "Folder" combobox. All of the controls in the middle are never given focus. |
Sure that would be great! |
I now have a bitwarden account and I've installed the Windows bitwarden client. What file do I point your app at when it first starts and shows the Open File Dialog? |
haha sorry about that - forgot about the setup part. The file is bw.exe. you need to download the CLI application from Bitwarden Help CLI |
With the new FileDialog you can actually place a restriction on what user can pick class BwDotExe : IAllowedType
{
/// <inheritdoc />
public bool IsAllowed (string path)
{
return Path.GetFileName (path).Equals ("bw.exe");
}
/// <inheritdoc />
public override string ToString () { return "bw.exe"; }
}
private void CreateDialog ()
{
var ofd = new FileDialog ()
{
MustExist = true,
AllowedTypes = [new BwDotExe ()]
};
Application.Run (ofd);
if (!ofd.Canceled)
{
MessageBox.Query ("you picked", ofd.Path, "Ok");
} |
Thank you for that suggestion - I will integrate that! |
What font do you have in your Terminal setup? |
Cascadia Mono - 12pt |
@tznind - I'm trying to figure out why you're not getting the right glyphs for buttons. With that font, I get: |
I am sorry about that. That will happen if the app crashes - I haven't fixed that yet. For now, you can go to a command prompt and type Pressing escape to exit the app also doesn't fire the logic to make sure the user session is cleaned up. To properly close the application choose Vault --> Quit |
@dasien perhaps this will be easier with a smaller sample app? Could you whip up an app that uses your infrastructure that demos the focus/scrolling you want to achieve? One thing I noticed in your code is you use a ton of absolute layout, where you' are specifying absolute values for locations/sizes of views. You will simplify your overall solution and reduce a ton of fragility by changing to using computed layout. |
@tig hmm let me see if I can just get some dummy data loaded in those detail views and make one of them a separate project. Once you are logged in, it should just be a matter of pressing F3 to edit the first selected item in the list view and from there the scrolling and tabbing behavior is apparent. I do use computed layout some on the main form, where I have very few control which end up filling the parent form. Where I have a lot of input controls, however, I am not sure that computed layout is going to be helpful, but I could experiment with that. Are you having issues getting to the detail form now? |
I am going to create a "Debug" Give me the evening to create this and the way to put the application in Debug mode and that should make it much easier to not have to worry about the CLI/Bitwarden parts and just navigate around the UI. |
@tig Ok i pushed an update that makes it so you don't need to use the CLI. In the I will clean up this debug mode so things can be temporarily written, but this should be enough to show what we are trying to see. |
I never really answered this, but this is effectively what is happening. The "base" view has the header and footer controls and a variable called "_subView" that is assigned the appropriate detail view.
Circling back to this. I think I have solved 1 of the 3 problems I had. The "Custom Detail View" is now receiving tabs. The issue was in my code. I was not setting I still have two issues - one is the tab order of controls and the other is scrolling. For the first one, "The tab order in v2 is very simple: The order is the order in which the Views exist in the When the The 3rd problem is the scrolling to a control with focus so that it is in the visible part of the |
I created a simple test view to illustrate the issue i am having with the Visually, it should go This is using 2.0.0-v2-develop.2329
|
It should not be re-ordering the As part of fixing I want to refactor It may be possible to implement a short-term fix though. Opening a new issue to track... |
Thank you for that update - good to know I wasn't going crazy with adding things and them not being in the order in which I added them! I cleaned up some of my code in this area as well, to make the add order clearer. @tig Could you point me to an example for how to implement scrolling based on the OP above? Am I correct that the appropriate place to do that is AdvanceFocus()? I am trying to determine if the control that is about to get focus is in the Viewable area of the screen and if not, move the viewable area so that it is visible. Basically, as I am tabbing through the controls on a |
I've been noodling on this... Would you be willing to submit a PR that does this:
if (SuperView?.ViewportSettings.HasFlag(ViewportSettings.ScrollToMakeFocusedViewVisible)
{
SuperView?.ScrollToMakeSubViewVisible(this);
} The
I think this should work pretty well! We can then work on edge-cases like if the subview in question is too big to be scrolled fully into view. |
Yes i will work on that, sounds like fun and the solution makes sense. It's Thanksgiving week and i have all my kids in town, so it may be a slow week for hobby coding :) |
@tig I have the code staged to commit, but i wanted to make sure i put some kind of tests in. Is |
Yes. |
Hello,
I recently converted my application Retrowarden to the v2 Terminal GUI. Many improvements so i am very excited to see v2 continue to develop.
One major area of confusion i have is tab behavior and scrolling. I removed all the old
ScrollBar
code i had, but i am struggling to make scrolling work in the application. It would seem that in order to be compliant with "Keyboard Required" tenet, the appropriate place for me to handle the need to scroll to the control which is about to receive focus is theAdvanceFocus
method? I want to make sure that the intention is for the developer to manage this viaAdvanceFocus
(or some other method/event), and not have it just be default behavior of the underlying system to make sure that the control with focus is visible. If the intention is for the developer to manage making sure the control that receives focus is viewable, I would really appreciate an example if possible, as i am struggling with making this work in v2.As a precursor to that, however, is an understanding of how the new
TabStop
functionality is supposed to work. I have gone through my application'sViews
and setTabStop
appropriately for all of them (I think). I have added them in the order in which i wanted them to be tabbed, even though there is no longer a way to set tab order directly. I still do not understand how the underlying system isdetermining the order of tab navigation for views. Whenever i Tab through the controls, many are skipped and the order is not Top Left to Bottom Right as you would expect. To take advantage of the fact that my application has several common controls across detail input forms, i created the following structure.
At runtime, depending on which type of item the user wants to add/edit, i swap in a "Detail View" of the appropriate type in the middle of the common header and footer controls. The Views contained in this Detail View never receive focus via a Tab key press. I suppose i could just create separate views for each item type and duplicate the common controls to get rid of the hierarchy, but i would prefer not to do that. I had a similar problem in V1, and the solution was for me to sprinkle in some calls to
FocusFirst
along with setting theTabOrder
custom after the Views had all been assigned. I cannot setTabOrder
any longer (the code is currently commented out in my project), so i am not sure how to get the application to consistently tab through the controls in the order that a user would expect. Even for those that it tabs to, the order kind of bounces around and is not in an order a user would expect.Describe the solution you'd like
I would like to either understand how to make the current v2 tabbing system work, or have fine-grained control over the order in which the controls i place on the screen are tabbed. On the surface, the v1 solution of
TabOrder
made sense, but the underlying view composition didn't seem to respect those when you set them before the views were added at runtime, hence the need for me to go back with a custom method and override whatever the order was. I appreciate the newTabStop
style, but without any way to directly influence the order in which the controls get focus, I don't know how to make that work.For scrolling, just an example of how it is intended to work with keyboard events would be helpful. I don't see any other method in v2 that would be the appropriate place to check to see if a control is visible based on is x/y relative to the
ViewPort
other thanAdvanceFocus
(e.g. noEnter
orGotFocus
). An example that shows the intended behavior for an application to check a View's position relative to the visible part of the screen and what to call to advance the scrolling so that the control is visible would be great.Thank you for all the great work!
The text was updated successfully, but these errors were encountered: