1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Accessibility: Multiple table fixes

- Fixes an off-by-one error when navigating by rows, caused by treating
  the table header as a row. The table header now has the header
  accessibility role.
- Fixes a bug where reordering table columns would cause the table to
  become inaccessible.
- Fixes a bug where the screen reader would try to navigate hidden table
  columns.
- Fixes an issue where moving the VoiceOver cursor to a partially hidden
  cell would cause the focus to move to the table itself, rather than to
  the cell.
This commit is contained in:
reuk 2022-06-28 12:51:03 +01:00
parent 5e626e1c2b
commit 707767fa4c
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
8 changed files with 233 additions and 187 deletions

View file

@ -49,6 +49,21 @@ public:
nullptr if there is no cell at the specified position.
*/
virtual const AccessibilityHandler* getCellHandler (int row, int column) const = 0;
/** Returns the AccessibilityHandler for a row in the table, or nullptr if there is
no row at this index.
The row component should have a child component for each column in the table.
*/
virtual const AccessibilityHandler* getRowHandler (int row) const = 0;
/** Returns the AccessibilityHandler for the header, or nullptr if there is
no header.
If you supply a header, it must have exactly the same number of children
as there are columns in the table.
*/
virtual const AccessibilityHandler* getHeaderHandler() const = 0;
};
} // namespace juce

View file

@ -116,9 +116,7 @@ private:
addMethod (@selector (accessibilitySelectedRows), getAccessibilitySelectedRows);
addMethod (@selector (setAccessibilitySelectedRows:), setAccessibilitySelectedRows);
addMethod (@selector (accessibilityColumnCount), getAccessibilityColumnCount);
addMethod (@selector (accessibilityColumns), getAccessibilityColumns);
addMethod (@selector (accessibilitySelectedColumns), getAccessibilitySelectedColumns);
addMethod (@selector (setAccessibilitySelectedColumns:), setAccessibilitySelectedColumns);
addMethod (@selector (accessibilityHeader), getAccessibilityHeader);
addMethod (@selector (accessibilityRowIndexRange), getAccessibilityRowIndexRange);
addMethod (@selector (accessibilityColumnIndexRange), getAccessibilityColumnIndexRange);
@ -166,26 +164,30 @@ private:
return selected;
}
static void setSelected (id item, bool selected)
{
auto* handler = getHandler (item);
if (handler == nullptr)
return;
const auto currentState = handler->getCurrentState();
if (isSelectable (currentState))
{
if (currentState.isSelected() != selected)
handler->getActions().invoke (AccessibilityActionType::toggle);
}
else if (currentState.isFocusable())
{
[item setAccessibilityFocused: selected];
}
}
static void setSelectedChildren (NSArray* children, NSArray* selected)
{
for (id child in children)
{
if (auto* handler = getHandler (child))
{
const auto currentState = handler->getCurrentState();
const BOOL isSelected = [selected containsObject: child];
if (isSelectable (currentState))
{
if (currentState.isSelected() != isSelected)
handler->getActions().invoke (AccessibilityActionType::toggle);
}
else if (currentState.isFocusable())
{
[child setAccessibilityFocused: isSelected];
}
}
}
setSelected (child, [selected containsObject: child]);
}
//==============================================================================
@ -218,15 +220,15 @@ private:
if (auto* modalHandler = modal->getAccessibilityHandler())
{
if (auto* focusChild = modalHandler->getChildFocus())
return (id) focusChild->getNativeImplementation();
return static_cast<id> (focusChild->getNativeImplementation());
return (id) modalHandler->getNativeImplementation();
return static_cast<id> (modalHandler->getNativeImplementation());
}
}
}
if (auto* focusChild = handler->getChildFocus())
return (id) focusChild->getNativeImplementation();
return static_cast<id> (focusChild->getNativeImplementation());
}
return nil;
@ -237,7 +239,7 @@ private:
if (auto* handler = getHandler (self))
{
if (auto* child = handler->getChildAt (roundToIntPoint (flippedScreenPoint (point))))
return (id) child->getNativeImplementation();
return static_cast<id> (child->getNativeImplementation());
return self;
}
@ -250,9 +252,9 @@ private:
if (auto* handler = getHandler (self))
{
if (auto* parentHandler = handler->getParent())
return NSAccessibilityUnignoredAncestor ((id) parentHandler->getNativeImplementation());
return NSAccessibilityUnignoredAncestor (static_cast<id> (parentHandler->getNativeImplementation()));
return NSAccessibilityUnignoredAncestor ((id) handler->getComponent().getWindowHandle());
return NSAccessibilityUnignoredAncestor (static_cast<id> (handler->getComponent().getWindowHandle()));
}
return nil;
@ -267,7 +269,7 @@ private:
auto* accessibleChildren = [NSMutableArray arrayWithCapacity: (NSUInteger) children.size()];
for (auto* childHandler : children)
[accessibleChildren addObject: (id) childHandler->getNativeImplementation()];
[accessibleChildren addObject: static_cast<id> (childHandler->getNativeImplementation())];
return accessibleChildren;
}
@ -581,27 +583,29 @@ private:
//==============================================================================
static NSArray* getAccessibilityRows (id self, SEL)
{
NSMutableArray* rows = [[NSMutableArray new] autorelease];
if (auto* tableInterface = getTableInterface (self))
{
for (int row = 0; row < tableInterface->getNumRows(); ++row)
auto* rows = [[NSMutableArray new] autorelease];
for (int row = 0, numRows = tableInterface->getNumRows(); row < numRows; ++row)
{
if (auto* handler = tableInterface->getCellHandler (row, 0))
if (auto* rowHandler = tableInterface->getRowHandler (row))
{
[rows addObject: (id) handler->getNativeImplementation()];
[rows addObject: static_cast<id> (rowHandler->getNativeImplementation())];
}
else
{
[rows addObject: [NSAccessibilityElement accessibilityElementWithRole: NSAccessibilityRowRole
frame: NSZeroRect
label: @"Offscreen Row"
parent: self]];
frame: NSZeroRect
label: @"Offscreen Row"
parent: self]];
}
}
return rows;
}
return rows;
return nil;
}
static NSArray* getAccessibilitySelectedRows (id self, SEL)
@ -614,39 +618,13 @@ private:
setSelectedChildren ([self accessibilityRows], selected);
}
static NSArray* getAccessibilityColumns (id self, SEL)
static id getAccessibilityHeader (id self, SEL)
{
NSMutableArray* columns = [[NSMutableArray new] autorelease];
if (auto* tableInterface = getTableInterface (self))
{
for (int column = 0; column < tableInterface->getNumColumns(); ++column)
{
if (auto* handler = tableInterface->getCellHandler (0, column))
{
[columns addObject: (id) handler->getNativeImplementation()];
}
else
{
[columns addObject: [NSAccessibilityElement accessibilityElementWithRole: NSAccessibilityColumnRole
frame: NSZeroRect
label: @"Offscreen Column"
parent: self]];
}
}
}
if (auto* handler = tableInterface->getHeaderHandler())
return static_cast<id> (handler->getNativeImplementation());
return columns;
}
static NSArray* getAccessibilitySelectedColumns (id self, SEL)
{
return getSelectedChildren ([self accessibilityColumns]);
}
static void setAccessibilitySelectedColumns (id self, SEL, NSArray* selected)
{
setSelectedChildren ([self accessibilityColumns], selected);
return nil;
}
//==============================================================================
@ -743,8 +721,7 @@ private:
@selector (accessibilityRows),
@selector (accessibilitySelectedRows),
@selector (accessibilityColumnCount),
@selector (accessibilityColumns),
@selector (accessibilitySelectedColumns) })
@selector (accessibilityHeader) })
{
if (selector == tableSelector)
return handler->getTableInterface() != nullptr;
@ -881,7 +858,7 @@ static void sendHandlerNotification (const AccessibilityHandler& handler,
if (@available (macOS 10.9, *))
{
if (id accessibilityElement = (id) handler.getNativeImplementation())
if (id accessibilityElement = static_cast<id> (handler.getNativeImplementation()))
{
sendAccessibilityEvent (accessibilityElement, notification,
(notification == NSAccessibilityLayoutChangedNotification
@ -966,7 +943,7 @@ void AccessibilityHandler::postAnnouncement (const String& announcementString, A
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
}();
sendAccessibilityEvent ((id) [NSApp mainWindow],
sendAccessibilityEvent (static_cast<id> ([NSApp mainWindow]),
NSAccessibilityAnnouncementRequestedNotification,
@{ NSAccessibilityAnnouncementKey: juceStringToNS (announcementString),
NSAccessibilityPriorityKey: @(nsPriority) });

View file

@ -46,7 +46,9 @@ public:
using Holder = std::unique_ptr<Base, AccessibleObjCClassDeleter>;
protected:
AccessibleObjCClass() : ObjCClass<Base> ("JUCEAccessibilityElement_")
AccessibleObjCClass() : AccessibleObjCClass ("JUCEAccessibilityElement_") {}
explicit AccessibleObjCClass (const char* name) : ObjCClass<Base> (name)
{
ObjCClass<Base>::template addIvar<AccessibilityHandler*> ("handler");
}

View file

@ -246,12 +246,7 @@ public:
int getRowIndex() const override
{
const auto index = handler.rowComponent.row;
if (handler.rowComponent.owner.hasAccessibleHeaderComponent())
return index + 1;
return index;
return handler.rowComponent.row;
}
int getRowSpan() const override { return 1; }
@ -300,23 +295,14 @@ public:
setViewedComponent (content.release());
}
RowComponent* getComponentForRow (int row) const noexcept
{
if (isPositiveAndBelow (row, rows.size()))
return rows[row];
return nullptr;
}
RowComponent* getComponentForRowWrapped (int row) const noexcept
{
return rows[row % jmax (1, rows.size())];
}
int getIndexOfFirstVisibleRow() const { return jmax (0, firstIndex - 1); }
RowComponent* getComponentForRowIfOnscreen (int row) const noexcept
{
return (row >= firstIndex && row < firstIndex + rows.size())
? getComponentForRowWrapped (row) : nullptr;
const auto startIndex = getIndexOfFirstVisibleRow();
return (startIndex <= row && row < startIndex + rows.size())
? rows[row % jmax (1, rows.size())] : nullptr;
}
int getRowNumberOfComponent (Component* const rowComponent) const noexcept
@ -384,17 +370,20 @@ public:
firstWholeIndex = (y + rowH - 1) / rowH;
lastWholeIndex = (y + getMaximumVisibleHeight() - 1) / rowH;
auto startIndex = jmax (0, firstIndex - 1);
const auto startIndex = getIndexOfFirstVisibleRow();
const auto lastIndex = startIndex + rows.size();
for (int i = 0; i < numNeeded; ++i)
for (auto row = startIndex; row < lastIndex; ++row)
{
const int row = i + startIndex;
if (auto* rowComp = getComponentForRowWrapped (row))
if (auto* rowComp = getComponentForRowIfOnscreen (row))
{
rowComp->setBounds (0, row * rowH, w, rowH);
rowComp->update (row, owner.isRowSelected (row));
}
else
{
jassertfalse;
}
}
}
@ -1155,15 +1144,8 @@ std::unique_ptr<AccessibilityHandler> ListBox::createAccessibilityHandler()
{
listBox.checkModelPtrIsValid();
if (listBox.model == nullptr)
return 0;
const auto numRows = listBox.model->getNumRows();
if (listBox.hasAccessibleHeaderComponent())
return numRows + 1;
return numRows;
return listBox.model != nullptr ? listBox.model->getNumRows()
: 0;
}
int getNumColumns() const override
@ -1171,24 +1153,7 @@ std::unique_ptr<AccessibilityHandler> ListBox::createAccessibilityHandler()
return 1;
}
const AccessibilityHandler* getCellHandler (int row, int) const override
{
if (auto* headerHandler = getHeaderHandler())
{
if (row == 0)
return headerHandler;
--row;
}
if (auto* rowComponent = listBox.viewport->getComponentForRow (row))
return rowComponent->getAccessibilityHandler();
return nullptr;
}
private:
const AccessibilityHandler* getHeaderHandler() const
const AccessibilityHandler* getHeaderHandler() const override
{
if (listBox.hasAccessibleHeaderComponent())
return listBox.headerComponent->getAccessibilityHandler();
@ -1196,6 +1161,20 @@ std::unique_ptr<AccessibilityHandler> ListBox::createAccessibilityHandler()
return nullptr;
}
const AccessibilityHandler* getRowHandler (int row) const override
{
if (auto* rowComponent = listBox.viewport->getComponentForRowIfOnscreen (row))
return rowComponent->getAccessibilityHandler();
return nullptr;
}
const AccessibilityHandler* getCellHandler (int, int) const override
{
return nullptr;
}
private:
ListBox& listBox;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableInterface)

View file

@ -50,6 +50,7 @@ public:
//==============================================================================
TableHeaderComponent::TableHeaderComponent()
{
setFocusContainerType (FocusContainerType::focusContainer);
}
TableHeaderComponent::~TableHeaderComponent()
@ -86,7 +87,7 @@ int TableHeaderComponent::getNumColumns (const bool onlyCountVisibleColumns) con
String TableHeaderComponent::getColumnName (const int columnId) const
{
if (auto* ci = getInfoForId (columnId))
return ci->name;
return ci->getTitle();
return {};
}
@ -95,9 +96,9 @@ void TableHeaderComponent::setColumnName (const int columnId, const String& newN
{
if (auto* ci = getInfoForId (columnId))
{
if (ci->name != newName)
if (ci->getTitle() != newName)
{
ci->name = newName;
ci->setTitle (newName);
sendColumnsChanged();
}
}
@ -116,7 +117,7 @@ void TableHeaderComponent::addColumn (const String& columnName,
jassert (width > 0);
auto ci = new ColumnInfo();
ci->name = columnName;
ci->setTitle (columnName);
ci->id = columnId;
ci->width = width;
ci->lastDeliberateWidth = width;
@ -125,7 +126,11 @@ void TableHeaderComponent::addColumn (const String& columnName,
jassert (ci->maximumWidth >= ci->minimumWidth);
ci->propertyFlags = propertyFlags;
columns.insert (insertIndex, ci);
auto* added = columns.insert (insertIndex, ci);
addChildComponent (added);
added->setVisible ((propertyFlags & visible) != 0);
resized();
sendColumnsChanged();
}
@ -197,6 +202,7 @@ void TableHeaderComponent::setColumnWidth (const int columnId, const int newWidt
}
}
resized();
repaint();
columnsResized = true;
triggerAsyncUpdate();
@ -340,6 +346,7 @@ void TableHeaderComponent::resizeColumnsToFit (int firstColumnIndex, int targetT
if (newWidth != ci->width)
{
ci->width = newWidth;
resized();
repaint();
columnsResized = true;
triggerAsyncUpdate();
@ -354,11 +361,7 @@ void TableHeaderComponent::setColumnVisible (const int columnId, const bool shou
{
if (shouldBeVisible != ci->isVisible())
{
if (shouldBeVisible)
ci->propertyFlags |= visible;
else
ci->propertyFlags &= ~visible;
ci->setVisible (shouldBeVisible);
sendColumnsChanged();
resized();
}
@ -409,6 +412,7 @@ bool TableHeaderComponent::isSortedForwards() const
void TableHeaderComponent::reSortTable()
{
sortChanged = true;
resized();
repaint();
triggerAsyncUpdate();
}
@ -485,7 +489,7 @@ void TableHeaderComponent::addMenuItems (PopupMenu& menu, const int /*columnIdCl
{
for (auto* ci : columns)
if ((ci->propertyFlags & appearsOnColumnMenu) != 0)
menu.addItem (ci->id, ci->name,
menu.addItem (ci->id, ci->getTitle(),
(ci->propertyFlags & (sortedForwards | sortedBackwards)) == 0,
isColumnVisible (ci->id));
}
@ -502,28 +506,42 @@ void TableHeaderComponent::paint (Graphics& g)
lf.drawTableHeaderBackground (g, *this);
auto clip = g.getClipBounds();
for (auto* ci : columns)
{
if (ci->isVisible() && ci->getWidth() > 0)
{
Graphics::ScopedSaveState ss (g);
g.setOrigin (ci->getX(), ci->getY());
g.reduceClipRegion (0, 0, ci->getWidth(), ci->getHeight());
lf.drawTableHeaderColumn (g, *this, ci->getTitle(), ci->id, ci->width, getHeight(),
ci->id == columnIdUnderMouse,
ci->id == columnIdUnderMouse && isMouseButtonDown(),
ci->propertyFlags);
}
}
}
void TableHeaderComponent::resized()
{
auto clip = getBounds();
int x = 0;
for (auto* ci : columns)
ci->setBounds (0, 0, 0, 0);
for (auto* ci : columns)
{
if (ci->isVisible())
{
if (x + ci->width > clip.getX()
&& (ci->id != columnIdBeingDragged
|| dragOverlayComp == nullptr
|| ! dragOverlayComp->isVisible()))
&& (ci->id != columnIdBeingDragged
|| dragOverlayComp == nullptr
|| ! dragOverlayComp->isVisible()))
{
Graphics::ScopedSaveState ss (g);
g.setOrigin (x, 0);
g.reduceClipRegion (0, 0, ci->width, getHeight());
lf.drawTableHeaderColumn (g, *this, ci->name, ci->id, ci->width, getHeight(),
ci->id == columnIdUnderMouse,
ci->id == columnIdUnderMouse && isMouseButtonDown(),
ci->propertyFlags);
ci->setBounds (x, 0, ci->width, getHeight());
}
x += ci->width;
@ -540,6 +558,7 @@ void TableHeaderComponent::mouseExit (const MouseEvent&) { setColumnUnderMou
void TableHeaderComponent::mouseDown (const MouseEvent& e)
{
resized();
repaint();
columnIdBeingResized = 0;
columnIdBeingDragged = 0;
@ -716,6 +735,7 @@ void TableHeaderComponent::endDrag (const int finalIndex)
moveColumn (columnIdBeingDragged, finalIndex);
columnIdBeingDragged = 0;
resized();
repaint();
for (int i = listeners.size(); --i >= 0;)
@ -735,6 +755,7 @@ void TableHeaderComponent::mouseUp (const MouseEvent& e)
c->lastDeliberateWidth = c->width;
columnIdBeingResized = 0;
resized();
repaint();
endDrag (getIndexOfColumnId (columnIdBeingDragged, true));
@ -756,10 +777,6 @@ MouseCursor TableHeaderComponent::getMouseCursor()
}
//==============================================================================
bool TableHeaderComponent::ColumnInfo::isVisible() const
{
return (propertyFlags & TableHeaderComponent::visible) != 0;
}
TableHeaderComponent::ColumnInfo* TableHeaderComponent::getInfoForId (int id) const
{
@ -793,6 +810,7 @@ void TableHeaderComponent::sendColumnsChanged()
if (stretchToFit && lastDeliberateWidth > 0)
resizeAllColumnsToFit (lastDeliberateWidth);
resized();
repaint();
columnsChanged = true;
triggerAsyncUpdate();
@ -903,4 +921,9 @@ std::unique_ptr<AccessibilityHandler> TableHeaderComponent::createAccessibilityH
return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::tableHeader);
}
std::unique_ptr<AccessibilityHandler> TableHeaderComponent::ColumnInfo::createAccessibilityHandler()
{
return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::tableHeader);
}
} // namespace juce

View file

@ -403,6 +403,8 @@ public:
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
void mouseMove (const MouseEvent&) override;
/** @internal */
void mouseEnter (const MouseEvent&) override;
@ -421,13 +423,13 @@ public:
virtual void showColumnChooserMenu (int columnIdClicked);
private:
struct ColumnInfo
struct ColumnInfo : public Component
{
String name;
ColumnInfo() { setInterceptsMouseClicks (false, false); }
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;
int id, propertyFlags, width, minimumWidth, maximumWidth;
double lastDeliberateWidth;
bool isVisible() const;
};
OwnedArray<ColumnInfo> columns;

View file

@ -26,6 +26,9 @@
namespace juce
{
static const Identifier tableColumnProperty { "_tableColumnId" };
static const Identifier tableAccessiblePlaceholderProperty { "_accessiblePlaceholder" };
class TableListBox::RowComp : public Component,
public TooltipClient
{
@ -48,7 +51,7 @@ public:
for (int i = 0; i < numColumns; ++i)
{
if (columnComponents[i] == nullptr)
if (columnComponents[(size_t) i]->getProperties().contains (tableAccessiblePlaceholderProperty))
{
auto columnRect = headerComp.getColumnPosition (i).withHeight (getHeight());
@ -86,33 +89,48 @@ public:
if (tableModel != nullptr && row < owner.getNumRows())
{
const Identifier columnProperty ("_tableColumnId");
auto numColumns = owner.getHeader().getNumColumns (true);
const auto numColumns = owner.getHeader().getNumColumns (true);
columnComponents.resize ((size_t) numColumns);
for (int i = 0; i < numColumns; ++i)
{
auto columnId = owner.getHeader().getColumnIdOfIndex (i, true);
auto* comp = columnComponents[i];
auto originalComp = std::move (columnComponents[(size_t) i]);
auto oldCustomComp = originalComp != nullptr && ! originalComp->getProperties().contains (tableAccessiblePlaceholderProperty)
? std::move (originalComp)
: nullptr;
auto compToRefresh = oldCustomComp != nullptr && columnId == static_cast<int> (oldCustomComp->getProperties()[tableColumnProperty])
? std::move (oldCustomComp)
: nullptr;
auto newCustomComp = rawToUniquePtr (tableModel->refreshComponentForCell (row, columnId, isSelected, compToRefresh.release()));
if (comp != nullptr && columnId != static_cast<int> (comp->getProperties() [columnProperty]))
auto columnComp = [&]
{
columnComponents.set (i, nullptr);
comp = nullptr;
}
// We got a result from refreshComponentForCell, so use that
if (newCustomComp != nullptr)
return std::move (newCustomComp);
comp = tableModel->refreshComponentForCell (row, columnId, isSelected, comp);
columnComponents.set (i, comp, false);
// There was already a placeholder component for this column
if (originalComp != nullptr)
return std::move (originalComp);
if (comp != nullptr)
{
comp->getProperties().set (columnProperty, columnId);
// Create a new placeholder component to use
auto comp = std::make_unique<Component>();
comp->setInterceptsMouseClicks (false, false);
comp->getProperties().set (tableAccessiblePlaceholderProperty, true);
return comp;
}();
addAndMakeVisible (comp);
resizeCustomComp (i);
}
// In order for navigation to work correctly on macOS, the number of child
// accessibility elements on each row must match the number of header accessibility
// elements.
columnComp->setFocusContainerType (FocusContainerType::focusContainer);
columnComp->getProperties().set (tableColumnProperty, columnId);
addAndMakeVisible (*columnComp);
columnComponents[(size_t) i] = std::move (columnComp);
resizeCustomComp (i);
}
columnComponents.removeRange (numColumns, columnComponents.size());
}
else
{
@ -122,15 +140,19 @@ public:
void resized() override
{
for (int i = columnComponents.size(); --i >= 0;)
for (auto i = (int) columnComponents.size(); --i >= 0;)
resizeCustomComp (i);
}
void resizeCustomComp (int index)
{
if (auto* c = columnComponents.getUnchecked (index))
c->setBounds (owner.getHeader().getColumnPosition (index)
.withY (0).withHeight (getHeight()));
if (auto& c = columnComponents[(size_t) index])
{
c->setBounds (owner.getHeader()
.getColumnPosition (index)
.withY (0)
.withHeight (getHeight()));
}
}
void mouseDown (const MouseEvent& e) override
@ -220,7 +242,12 @@ public:
Component* findChildComponentForColumn (int columnId) const
{
return columnComponents [owner.getHeader().getIndexOfColumnId (columnId, true)];
const auto index = (size_t) owner.getHeader().getIndexOfColumnId (columnId, true);
if (isPositiveAndBelow (index, columnComponents.size()))
return columnComponents[index].get();
return nullptr;
}
std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
@ -298,7 +325,7 @@ public:
//==============================================================================
TableListBox& owner;
OwnedArray<Component> columnComponents;
std::vector<std::unique_ptr<Component>> columnComponents;
int row = -1;
bool isSelected = false, isDragging = false, selectRowOnMouseUp = false;
@ -567,17 +594,28 @@ std::unique_ptr<AccessibilityHandler> TableListBox::createAccessibilityHandler()
return tableListBox.getHeader().getNumColumns (false);
}
const AccessibilityHandler* getCellHandler (int row, int column) const override
const AccessibilityHandler* getRowHandler (int row) const override
{
if (isPositiveAndBelow (row, getNumRows()))
{
if (isPositiveAndBelow (column, getNumColumns()))
if (auto* cellComponent = tableListBox.getCellComponent (tableListBox.getHeader().getColumnIdOfIndex (column, false), row))
return cellComponent->getAccessibilityHandler();
if (auto* rowComp = tableListBox.getComponentForRowNumber (row))
return rowComp->getAccessibilityHandler();
}
return nullptr;
}
const AccessibilityHandler* getCellHandler (int row, int column) const override
{
if (isPositiveAndBelow (row, getNumRows()) && isPositiveAndBelow (column, getNumColumns()))
if (auto* cellComponent = tableListBox.getCellComponent (tableListBox.getHeader().getColumnIdOfIndex (column, false), row))
return cellComponent->getAccessibilityHandler();
return nullptr;
}
const AccessibilityHandler* getHeaderHandler() const override
{
if (tableListBox.hasAccessibleHeaderComponent())
return tableListBox.headerComponent->getAccessibilityHandler();
return nullptr;
}

View file

@ -1448,7 +1448,12 @@ std::unique_ptr<AccessibilityHandler> TreeView::createAccessibilityHandler()
int getNumRows() const override { return treeView.getNumRowsInTree(); }
int getNumColumns() const override { return 1; }
const AccessibilityHandler* getCellHandler (int row, int) const override
const AccessibilityHandler* getHeaderHandler() const override
{
return nullptr;
}
const AccessibilityHandler* getRowHandler (int row) const override
{
if (auto* itemComp = treeView.getItemComponent (treeView.getItemOnRow (row)))
return itemComp->getAccessibilityHandler();
@ -1456,6 +1461,11 @@ std::unique_ptr<AccessibilityHandler> TreeView::createAccessibilityHandler()
return nullptr;
}
const AccessibilityHandler* getCellHandler (int, int) const override
{
return nullptr;
}
private:
TreeView& treeView;