Re: Accessibility in custom NSControl subclasses
Re: Accessibility in custom NSControl subclasses
- Subject: Re: Accessibility in custom NSControl subclasses
- From: Stephen Blinkhorn <email@hidden>
- Date: Mon, 28 Feb 2011 14:41:01 -0600
On 28 Feb 2011, at 12:00, James Dempsey wrote:
On Feb 28, 2011, at 9:16 AM, Stephen Blinkhorn wrote:
Hello, first post to this list.
I make extensive use of custom NSControls in the GUIs of my audio
software products. Recently I ran into a problem whilst trying to
implement accessibility features in these controls.
I have added the test methods below which work perfectly for custom
NSView classes but are not working as expected with custom
NSControl classes. With custom NSControl classes voice over reads
out the application name instead of the value, role and description
details.
Can anyone shed any light on why this is happening? Maybe it is
worth mentioning that none of my controls use NSCell classes at
this time.
I'm not sure why that is the symptom you are seeing, but here are a
few things that should help:
The accessibility implementation in NSControl is written with a cell
in mind, so you may see various odd behaviors when no cell is present.
This was indeed the case. In my test control I had omitted the
following method:
+(Class)cellClass
{
return [NSActionCell class];
}
This method is required for a custom control to be able to send action
messages. It is the control's cell that is expected to implement the
accessibilityAttributeNames: and accessibilityAttributeValue: methods.
I created a subclass of NSActionCell and implemented the above methods
in the new cell class and now the Accessibility Inspector is correctly
reporting the attributes I have set for the control. Still some work
to achieve parity with the standard NSSlider and NSButton classes etc
but we're on the right path.
Thanks for the advice James,
Stephen
The behavior can all be overridden, of course. For instance, you
will probably need to override -accessibilityHitTest: and -
accessibilityFocusedUIElement.
Try running your app with -NSAccessibilityDebugLogLevel 1 set as an
argument from Xcode or gdb, this turns on logging and may help
pinpoint issues. You will probably see a number of 'Encountered nil
cell/child of single celled control" logs due to the above.
Since your custom control is an AXSlider, you should make it appear
and behave just like any other AXSlider - and if you do, VoiceOver
should treat it like any other AXSlider. I'd recommend using
Accessibility Inspector to inspect a stock slider (there are
numerous in the various System Preferences, or just create a
throwaway nib in IB and test the interface), locking on the element,
and copying/pasting the list of attributes and actions into a text
file for future reference. Then work towards having your control
report the same way (for instance an AXSlider has an AXMinValue and
an AXMaxValue, but it doesn't look like your slider does).
Another example is that an AXSlider has a single item in its
AXChildren, which is an AXValueIndicator. VoiceOver may or may not
use the value indicator, but other AX clients might depend on it.
Since you likely don't have a separate object for your value
indicator, you can use a faux UI element object to report it to
accessibility.
The following articles talk about Accessibility Inspector in more
detail, as well as using a faux UI element.
http://developer.apple.com/ue/accessibility/accessibilityincocoa.html
http://developer.apple.com/ue/accessibility/accessibilitycustomviews.html
The ImageMap sample code contains a FauxUIElement class available
for resue. The articles above explain the code sample in some detail.
http://developer.apple.com/library/mac/#samplecode/ImageMap/
Introduction/Intro.html
-James
-(BOOL)accessibilityIsIgnored {
return NO;
}
-(NSArray*)accessibilityAttributeNames
{
NSArray* attributes = [super accessibilityAttributeNames];
NSMutableArray* mutable_attributes = [[NSMutableArray alloc]
initWithCapacity:[attributes count]];
[mutable_attributes addObjectsFromArray:attributes];
[mutable_attributes addObject:NSAccessibilityValueAttribute];
[mutable_attributes
addObject:NSAccessibilityValueDescriptionAttribute];
return (NSArray*)mutable_attributes;
}
-(id)accessibilityAttributeValue:(NSString *)attribute
{
if([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
return NSAccessibilitySliderRole;
} else if([attribute
isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
return NSAccessibilityRoleDescriptionForUIElement(self);
} else if([attribute
isEqualToString:NSAccessibilityValueAttribute]) {
return [NSNumber numberWithFloat:50.0];
} else if([attribute
isEqualToString:NSAccessibilityValueDescriptionAttribute]) {
return @"50%";
} else {
return [super accessibilityAttributeValue:attribute];
};
}
Thanks,
Stephen
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Accessibility-dev mailing list (email@hidden
)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
--------------------------------------------------
James Dempsey
AppKit Engineering
Apple
email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Accessibility-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden