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

Ensure settings are scrolled to using tab navigation #12300

Merged
merged 9 commits into from
Apr 21, 2021
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
52 changes: 44 additions & 8 deletions source/gui/nvdaControls.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
# -*- coding: UTF-8 -*-
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2016-2018 NV Access Limited, Derek Riemer
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2016-2021 NV Access Limited, Derek Riemer
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

from ctypes.wintypes import BOOL
from typing import Any, Tuple, Optional
import wx
from comtypes import GUID
from wx.lib import scrolledpanel
from wx.lib.mixins import listctrl as listmix
from .dpiScalingHelper import DpiScalingHelperMixin
from . import guiHelper
import oleacc
import winUser
import winsound

from collections.abc import Callable


class AutoWidthColumnListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
"""
A list control that allows you to specify a column to resize to take up the remaining width of a wx.ListCtrl.
Expand Down Expand Up @@ -355,3 +354,40 @@ def onSliderChar(self, evt):
evt.Skip()
return
self.SetValue(newValue)


class TabbableScrolledPanel(scrolledpanel.ScrolledPanel):
"""
This class was created to ensure a ScrolledPanel scrolls to nested children of the panel when navigating
with tabs (#12224). A PR to wxPython implementing this fix can be tracked on
https://github.com/wxWidgets/Phoenix/pull/1950
"""
def GetChildRectRelativeToSelf(self, child: wx.Window) -> wx.Rect:
"""
window.GetRect returns the size of a window, and its position relative to its parent.
When calculating ScrollChildIntoView, the position relative to its parent is not relevant unless the
parent is the ScrolledPanel itself. Instead, calculate the position relative to scrolledPanel
"""
childRectRelativeToScreen = child.GetScreenRect()
scrolledPanelScreenPosition = self.GetScreenPosition()
return wx.Rect(
childRectRelativeToScreen.x - scrolledPanelScreenPosition.x,
childRectRelativeToScreen.y - scrolledPanelScreenPosition.y,
childRectRelativeToScreen.width,
childRectRelativeToScreen.height
)

def ScrollChildIntoView(self, child: wx.Window) -> None:
"""
Overrides child.GetRect with `GetChildRectRelativeToSelf` before calling
`super().ScrollChildIntoView`. `super().ScrollChildIntoView` incorrectly uses child.GetRect to
navigate scrolling, which is relative to the parent, where it should instead be relative to this
ScrolledPanel.
"""
oldChildGetRectFunction = child.GetRect
child.GetRect = lambda: self.GetChildRectRelativeToSelf(child)
try:
super().ScrollChildIntoView(child)
finally:
# ensure child.GetRect is reset properly even if super().ScrollChildIntoView throws an exception
child.GetRect = oldChildGetRectFunction
Comment on lines +388 to +393
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I avoided suggesting this because it's a little dangerous. If any of the other method calls within super().ScrollChildIntoView rely on the absolute value for rect for the child, this will be broken in a subtle way.
Worse, by the time we update wxPython, we may have forgotten about this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

child is only used once in super().ScrollChildIntoView, and that is to calculate the incorrect child.GetRect https://github.com/wxWidgets/Phoenix/blob/wxPython-4.1.1/wx/lib/scrolledpanel.py#L190. Do we only update wxPython with compatibility breaking releases? That way I can mark this as deprecated for 2022.1 so it won't get lost.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense that we only update on compat breaking releases. Let's mark it as deprecated.

3 changes: 1 addition & 2 deletions source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import typing
import wx
from vision.providerBase import VisionEnhancementProviderSettings
from wx.lib import scrolledpanel
from wx.lib.expando import ExpandoTextCtrl
import wx.lib.newevent
import winUser
Expand Down Expand Up @@ -483,7 +482,7 @@ def makeSettings(self, settingsSizer):
# The provided column header is just a placeholder, as it is hidden due to the wx.LC_NO_HEADER style flag.
self.catListCtrl.InsertColumn(0,categoriesLabelText)

self.container = scrolledpanel.ScrolledPanel(
self.container = nvdaControls.TabbableScrolledPanel(
parent = self,
style = wx.TAB_TRAVERSAL | wx.BORDER_THEME,
size=containerDim
Expand Down