Skip to content
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

Allow associating ComboBoxes to labels #17476

Merged
merged 5 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 50 additions & 32 deletions source/gui/guiHelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def __init__(self, parent):
TypeVar,
Union,
cast,
overload,
)

import wx
Expand Down Expand Up @@ -124,12 +125,39 @@ def addButton(self, *args, **kwargs):
return wxButton


def associateElements(firstElement: wx.Control, secondElement: wx.Control) -> wx.BoxSizer:
# vertical controls where the label should go above visually, and the control should go below
_VerticalCtrlT = TypeVar("_VerticalCtrlT", wx.ListCtrl, wx.ListBox, wx.TreeCtrl)
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
# horizontal controls where the label should go first visually, and the control should go after
_HorizontalCtrlT = TypeVar(
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
"_HorizontalCtrlT",
wx.Button,
wx.Choice,
wx.ComboBox,
wx.Slider,
wx.SpinCtrl,
wx.TextCtrl,
)


@overload
def associateElements(firstElement: wx.StaticText, secondElement: _HorizontalCtrlT) -> wx.BoxSizer: ...
@overload
def associateElements(firstElement: wx.StaticText, secondElement: wx.CheckBox) -> wx.BoxSizer: ...
@overload
def associateElements(firstElement: wx.StaticText, secondElement: _VerticalCtrlT) -> wx.BoxSizer: ...
@overload
def associateElements(firstElement: wx.Button, secondElement: wx.CheckBox) -> wx.BoxSizer: ...
@overload
def associateElements(firstElement: wx.TextCtrl, secondElement: wx.Button) -> wx.BoxSizer: ...


def associateElements(firstElement, secondElement) -> wx.BoxSizer:
"""Associates two GUI elements together. Handles choosing a layout and appropriate spacing. Abstracts away common
pairings used in the NVDA GUI.
Currently handles:
wx.StaticText and (wx.Choice, wx.TextCtrl, wx.Slider, wx.Button or wx.SpinCtrl) - Horizontal layout
wx.StaticText and (wx.ListCtrl or wx.ListBox or wx.TreeCtrl ) - Vertical layout
wx.StaticText and :const:`_HorizontalCtrlT` - Horizontal layout
wx.StaticText and wx.CheckBox - Horizontal layout, control first, label second
wx.StaticText and :const:`_VerticalCtrlT` - Vertical layout
wx.Button and wx.CheckBox - Horizontal layout
wx.TextCtrl and wx.Button - Horizontal layout
"""
Expand All @@ -140,35 +168,25 @@ def associateElements(firstElement: wx.Control, secondElement: wx.Control) -> wx

# staticText and input control
# likely a labelled control from LabeledControlHelper
if isinstance(firstElement, wx.StaticText) and isinstance(
secondElement,
(
wx.Button,
wx.Choice,
wx.Slider,
wx.SpinCtrl,
wx.TextCtrl,
),
):
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(firstElement, flag=wx.ALIGN_CENTER_VERTICAL)
sizer.AddSpacer(SPACE_BETWEEN_ASSOCIATED_CONTROL_HORIZONTAL)
sizer.Add(secondElement)
elif isinstance(firstElement, wx.StaticText) and isinstance(secondElement, wx.CheckBox):
# checkbox should go first, and label should go after
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(secondElement)
sizer.AddSpacer(SPACE_BETWEEN_ASSOCIATED_CONTROL_HORIZONTAL)
sizer.Add(firstElement, flag=wx.ALIGN_CENTER_VERTICAL)
# staticText and (ListCtrl, ListBox or TreeCtrl)
elif isinstance(firstElement, wx.StaticText) and isinstance(
secondElement,
(wx.ListCtrl, wx.ListBox, wx.TreeCtrl),
):
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(firstElement)
sizer.AddSpacer(SPACE_BETWEEN_ASSOCIATED_CONTROL_VERTICAL)
sizer.Add(secondElement, flag=wx.EXPAND, proportion=1)
if isinstance(firstElement, wx.StaticText):
# Horizontal layout, label first, control second
if isinstance(secondElement, _HorizontalCtrlT.__constraints__):
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(firstElement, flag=wx.ALIGN_CENTER_VERTICAL)
sizer.AddSpacer(SPACE_BETWEEN_ASSOCIATED_CONTROL_HORIZONTAL)
sizer.Add(secondElement)
# Horizontal layout, control first, label second
elif isinstance(secondElement, wx.CheckBox):
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(secondElement)
sizer.AddSpacer(SPACE_BETWEEN_ASSOCIATED_CONTROL_HORIZONTAL)
sizer.Add(firstElement, flag=wx.ALIGN_CENTER_VERTICAL)
# Vertical layout, label above, control below
elif isinstance(secondElement, _VerticalCtrlT.__constraints__):
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(firstElement)
sizer.AddSpacer(SPACE_BETWEEN_ASSOCIATED_CONTROL_VERTICAL)
sizer.Add(secondElement, flag=wx.EXPAND, proportion=1)
# button and checkBox
elif isinstance(firstElement, wx.Button) and isinstance(secondElement, wx.CheckBox):
seanbudd marked this conversation as resolved.
Show resolved Hide resolved
sizer = wx.BoxSizer(wx.HORIZONTAL)
Expand Down
1 change: 1 addition & 0 deletions user_docs/en/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Add-ons will need to be re-tested and have their manifest updated.
* Retrieving the `labeledBy` property now works for:
* objects in applications implementing the `labelled-by` IAccessible2 relation. (#17436, @michaelweghorn)
* UIA elements supporting the corresponding `LabeledBy` UIA property. (#17442, @michaelweghorn)
* Added the ability to associate `wx.ComboBox` and a label `wx.StaticText` using `gui.guiHelper.associateElements`. (#17476)
* Added the following extension points (#17428, @ctoth):
* `inputCore.decide_handleRawKey`: called on each keypress
* `speech.extensions.post_speechPaused`: called when speech is paused or unpaused
Expand Down
Loading