beeware / beeware/toga

Control Widgets Tab Focus Order Via Code

Open
#1,650 6 comments 0 reactions 0 assignees View on GitHub
enhancement gtk linux macOS qt
Dominant language
Python
Stars
5.4k
Forks
827
Avg merge
15h 39m
Merged PRs (30d)
40

Description

Is your feature request related to a problem? Please describe.
========================================

*TL;DR - one should be able to control the tab focus order of widgets in a window.*

Assume you have a window with two buttons in a line named `button1` and `button2`.

If you insert `button3` between those two buttons, the tab order of the buttons will be the **order of insertion**, i.e. `button1`, `button2`, `button3`. You might want to change that order to be the **order of appearance on the screen**, i.e. `button1`, `button3`, `button2`.

This is a not bug, in my opinon. However, we would like to let our users have a way to control the tab order manually via code.

Describe the solution you'd like
====================
The way I see it, I can think of 3 possible APIs for that abbility:

Option I - `widget.next_tab` and `widget.prev_tab`
------------------------------------------------------
With this API, for each widget one should be able to define the next tab or prev tab. For example:
```python
widget1.next_tab = widget2
widget1.prev_tab = widget3
```

The problem with this approach is that it introduces a way in which one can jump between windows if we set the next tab of a widget to be a widget from another window. We can simply raise an exception if someone does that.

Option II - `widget.tab_index`
--------------------------------
another approach should be to set the tab index of a widget. In that way, the tab order will be selected for each window by the order of tab index. This is similar to the way the tab order is handled in [.Net](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.tabindex?view=windowsdesktop-6.0). For example:
```python
widget1.tab_index = 0
widget2.tab_index = 10
widget3.tab_index = 100
```

The problem with this approach that we have to keep track of the index of other widgets in order to decied which index to use for our widget.

Another problem happens in the case where we choose the tab index to be an index we already chose for another widget. We can solve this problem by bumping by 1 the index for every widget with our index or above.

Option III - `window.set_tab_index(widget, index)`
------------------------------------------------------
Another approach is to control the widgets order from the `window` class. In that way we can make sure that we do not set the index of a widget to be the same as another widget and we can make sure that we order the tab index of widgets which are only from our window.

The downside of this approach is that we cannot simply set the "next widget" or "previous widget" , we have to do this using the `window` instance.

Summary
============
I don't have a favorite approach, but I tend towards option II. We can also choose to implement more than one of those APIs.

I think this is an important feature and I can think of many use cases where one might need it.
Let me know what you think.

Contributor guide

Open the contributing guide

Research direction

No files, tests, or implementation entry points are named. Start by locating the widget and window focus-traversal code, then resolve which of the three proposed APIs should be supported and define behavior for duplicate indices and cross-window navigation. Done means a documented API with tests covering the requested tab order.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
desktop
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.