From bec0397a81e8877886d19e95ce24fee2e78e6830 Mon Sep 17 00:00:00 2001 From: Sean Budd Date: Tue, 3 Dec 2024 16:12:50 +1100 Subject: [PATCH 1/4] Allow associating ComboBoxes to labels --- source/gui/guiHelper.py | 72 +++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/source/gui/guiHelper.py b/source/gui/guiHelper.py index eb8a05ed1bf..e6656e4ba02 100644 --- a/source/gui/guiHelper.py +++ b/source/gui/guiHelper.py @@ -124,12 +124,30 @@ 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) +# horizontal controls where the label should go first visually, and the control should go after +_HorizontalCtrlT = TypeVar( + "_HorizontalCtrlT", + wx.Button, + wx.Choice, + wx.ComboBox, + wx.Slider, + wx.SpinCtrl, + wx.TextCtrl, +) + + +def associateElements( + firstElement: wx.StaticText | wx.StaticText | wx.StaticText | wx.Button | wx.TextCtrl, + secondElement: _HorizontalCtrlT | wx.CheckBox | _VerticalCtrlT | wx.CheckBox | wx.Button, +) -> 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 _HorizontalCtrlT - Horizontal layout + wx.StaticText and wx.CheckBox - Horizontal layout, control first, label second + wx.StaticText and _VerticalCtrlT - Vertical layout wx.Button and wx.CheckBox - Horizontal layout wx.TextCtrl and wx.Button - Horizontal layout """ @@ -140,35 +158,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): + 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): sizer = wx.BoxSizer(wx.HORIZONTAL) From ffc8c1b6892c6e55f1f8250338667df182f7af3d Mon Sep 17 00:00:00 2001 From: Sean Budd Date: Tue, 10 Dec 2024 16:07:22 +1100 Subject: [PATCH 2/4] use overload --- source/gui/guiHelper.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/source/gui/guiHelper.py b/source/gui/guiHelper.py index e6656e4ba02..d17367fb77b 100644 --- a/source/gui/guiHelper.py +++ b/source/gui/guiHelper.py @@ -52,6 +52,7 @@ def __init__(self, parent): TypeVar, Union, cast, + overload, ) import wx @@ -138,9 +139,21 @@ def addButton(self, *args, **kwargs): ) +@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: wx.StaticText | wx.StaticText | wx.StaticText | wx.Button | wx.TextCtrl, - secondElement: _HorizontalCtrlT | wx.CheckBox | _VerticalCtrlT | wx.CheckBox | wx.Button, + firstElement: wx.StaticText | wx.Button | wx.TextCtrl, + secondElement: _HorizontalCtrlT | wx.CheckBox | _VerticalCtrlT | wx.Button, ) -> wx.BoxSizer: """Associates two GUI elements together. Handles choosing a layout and appropriate spacing. Abstracts away common pairings used in the NVDA GUI. From 532f55a6865a43c5aa1450646573b17168bf0fe3 Mon Sep 17 00:00:00 2001 From: Sean Budd Date: Wed, 11 Dec 2024 10:23:22 +1100 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> --- source/gui/guiHelper.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/source/gui/guiHelper.py b/source/gui/guiHelper.py index d17367fb77b..cdcf9cb0689 100644 --- a/source/gui/guiHelper.py +++ b/source/gui/guiHelper.py @@ -151,16 +151,13 @@ def associateElements(firstElement: wx.Button, secondElement: wx.CheckBox) -> wx def associateElements(firstElement: wx.TextCtrl, secondElement: wx.Button) -> wx.BoxSizer: ... -def associateElements( - firstElement: wx.StaticText | wx.Button | wx.TextCtrl, - secondElement: _HorizontalCtrlT | wx.CheckBox | _VerticalCtrlT | 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 _HorizontalCtrlT - Horizontal layout + wx.StaticText and :const:`_HorizontalCtrlT` - Horizontal layout wx.StaticText and wx.CheckBox - Horizontal layout, control first, label second - wx.StaticText and _VerticalCtrlT - Vertical layout + wx.StaticText and :const:`_VerticalCtrlT` - Vertical layout wx.Button and wx.CheckBox - Horizontal layout wx.TextCtrl and wx.Button - Horizontal layout """ From ca0c7e196f8121c6ea977723d056b07a9e0159dd Mon Sep 17 00:00:00 2001 From: Sean Budd Date: Wed, 11 Dec 2024 11:19:57 +1100 Subject: [PATCH 4/4] add changelog entry --- user_docs/en/changes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/user_docs/en/changes.md b/user_docs/en/changes.md index 36af04e82f0..806d51a7aa0 100644 --- a/user_docs/en/changes.md +++ b/user_docs/en/changes.md @@ -111,6 +111,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) #### API Breaking Changes