The focus location provided to assistive technology by GridAx::GetLocation() does not take into account horizontal or vertical scrolling. So if there is any scrolling in either the Metadata or Labels editor, the focus location provided to assistive technology is not the same as the focus location shown by wxWidgets.
If the grid is empty or does not have a selected cell, the current
row and column must still maintain these class invariants:
-1 <= current_row < rows
-1 <= current_column < columns
if either current_row or current_column is -1, then the other
shall also be -1
wxGrid uses wxGridNoCellCoords to test for current_row == -1 &&
current_column == -1. We treat the case where only one
of the coordinates is -1 as if both are -1.
Problem: this affects NVDA and Narrator, but not Jaws. If a user moves to the Delete button and presses it to delete a label, a label is incorrectly read as the new focus - the focus remains on the Delete button.
GridAx::SetCurrentCell() can be called when the Grid is not the focus, and send a focus event.
Fix: In GridAx::SetCurrentCell() only send an focus event if the Grid is the focus.
... Unnecessary because transitively included.
But each .cpp file still includes its own .h file near the top to ensure
that it compiles indenendently, even if it is reincluded transitively later.
Problem:
Using the Narrator screen reader on Windows 10:
1. Narrator does not read the uneditable cells in the tag column of the Metadata editor.
2. In one or more versions of Windows 10 prior to 1809, Narrator's focus was incorrect after editing a cell.
Fixes:
1. Fixed by adding wxACC_STATE_SYSTEM_FOCUSED to the state.
2. Corrected GridAx::GetFocus().
... except Audacity.h
This forces us to make each header contain all forward declarations or nested
headers that it requires, rather than depend on context.
... instead use the utility make_iterator_range and its index() or contains()
method. This generic utility works with any container defining begin() and
end().
This further lessens dependency on wxWidgets container idioms.
... which will make it easier to change the types of those containers to
std::vectors of other string-like classes
for wxString,
IsEmpty => empty
Clear => clear
Alloc => reserve
for wxArrayString,
Count => size
GetCount => size
IsEmpty => empty
Add => push_back
Clear => clear
Empty => clear
Sort => std::sort (only with default comparator)
SetCount => resize
Last => back
Item => operator []
Alloc => reserve
The main change in wx accessibility is this:
7dab555f71 (diff-04f5191d86f95b1c4d5d9c979da65878)
However wxWindowAccessible has not been updated to take into account of that change. In particular wxWindowAccessible::GetParent() was always wrong, but it was consistent with the rest of the framework. Now it's wrong and inconsistent. This function should return an object with role window, and which has the same name.
The fix is to introduce class WindowAccessible, which is effectively our own version of wxWindowAccessible. This class does not override GetParent(), and so just relies on a standard accessible object to to the right thing in wxIAccessible::get_accParent() (which is does). This class also allows us to have our own version of GetName(), which allows us to set the accessibility names of buttons.
These changes will break the accessibility of Audacity if it is built with wxWidgets 3.0.X. If this is a problem, then there could be some #if stuff in WindowAccessible.h to turn the WindowAccessible class into one which simply inherits from wxWindowAccessible, and doesn't override anything.
In commit 9c687f0, TimeEditors etc were generalized to handle both times and frequencies.
This fixes the accessibility names of cells to handle frequencies.
0017: Encapsulation of reference type returned by wxString::operator[]
0018: Interface change for classes deriving from wxGridTableBase
0017
----
The NumericTextCtrl relies on the fact that the value returned by
wxString::operator[] is a "wxChar&". However, in wxWidgets 3.0 it is a
wxUniCharRef (encapsulation of a reference to characters, to improve unicode
handling).
wxString::reference provides the correct type in both wx2.8 and wx3.0 and can be
used as writable reference in both cases. However, for the case of an update of
the reference itself (instead of the value), there is no common syntax. In this
case the character position within the string has to be used as reference.
0018
----
With wx3.0, different methods have to be implemented (EndEdit with new signature
and ApplyEdit) than with wx2.8 (only EndEdit with old signature). Now both
versions are implemented in parallel in the classes TimeEditor and ChoiceEditor
(one version essentially being a wrapper of the other one).
Note: Superseding the previous solution of the issue (committed in r13403) by one
that avoids code duplication. This should avoid problems with missed changes in
code that isn't used with the wxWidgets version that the developer tests with
(like just happened in r13557).
We can't go to 3.0.1 yet as there are still build issues on
Linux and OSX. You can get Windows to build, but there's
still some display issues.
These changes should work with wxWidgets 2.8.12 as well, so
we can take our time to get things working properly before
switching over.
Completes James' TimeConverter work
This completes the work that James started. It moves most of the non-GUI
related processing from TimeTextCtrl to James' TimeConverter class.
Other changes include:
1) TimeTextCtrl now expects the format name instead of the format string to be
passed when creating a new instance. I found that almost all cases created the
instance with a blank format string and then set the string after creation.
2) To simplify maintenance and prevent a possible discrepancy between the two,
Increase() and Decrease() were merged into a single routine.
As a result:
1) All cases where a TimeTextCtrl was being used to extract information and
not actually display a control have been changed to use TimeConverter instead.
2) All cases where TimeTextCtrl was being created with an empty format and
then immediately followed by something like this:
tt.SetFormatString(tt.GetBuiltinFormat(c->GetFormat()))
have been changed to pass the format name instead of the format string when
creating the TimeTextCtrl instance.