/* |
|
Copyright (C) 2014 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
|
Abstract: |
An example demonstrating adding accessibility to an NSView subclass that behaves like a checkbox by implementing the NSAccessibilityCheckBox protocol. |
|
*/ |
|
#import "AAPLTicTacToeCheckboxView.h" |
|
static NSString * const AAPLCheckboxSelected = @"CustomCheckboxSelected"; |
static NSString * const AAPLCheckboxUnselected = @"CustomCheckboxUnselected"; |
static const CGFloat AAPLCheckboxWidth = 12.0; |
static const CGFloat AAPLCheckboxHeight = AAPLCheckboxWidth; |
static const CGFloat AAPLCheckboxTextSpacing = 8.0; // spacing between box and text |
|
@interface AAPLTicTacToeCheckboxView () |
|
@property (nonatomic, strong) NSString *checkboxText; |
@property (nonatomic) BOOL checked; |
|
@end |
|
@implementation AAPLTicTacToeCheckboxView |
|
- (instancetype)initWithFrame:(NSRect)frame |
{ |
self = [super initWithFrame:frame]; |
|
if ( self != nil ) |
{ |
self.checkboxText = NSLocalizedString(@"AI opponent", "text of checkbox"); |
} |
|
return self; |
} |
|
- (BOOL)acceptsFirstResponder |
{ |
return YES; |
} |
|
- (BOOL)becomeFirstResponder |
{ |
BOOL didBecomeFirstResponder = [super becomeFirstResponder]; |
[self setNeedsDisplay:YES]; |
return didBecomeFirstResponder; |
} |
|
- (BOOL)resignFirstResponder |
{ |
BOOL didResignFirstResponder = [super resignFirstResponder]; |
[self setNeedsDisplay:YES]; |
return didResignFirstResponder; |
} |
|
- (void)mouseUp:(NSEvent *)mouseEvent |
{ |
[self toggleCheckedState]; |
} |
|
- (void)toggleCheckedState |
{ |
self.checked = !self.checked; |
[self.delegate checkboxCheckedStateChanged:self]; |
|
// Whenever the value of the checkbox changes, let accessibility clients know |
NSAccessibilityPostNotification(self, NSAccessibilityValueChangedNotification); |
|
[self setNeedsDisplay:YES]; |
} |
|
- (void)keyDown:(NSEvent *)keyEvent |
{ |
int spacebarKeyCode = 49; |
|
if ( [keyEvent keyCode] == spacebarKeyCode ) |
{ |
[self toggleCheckedState]; |
} |
else |
{ |
[super keyDown:keyEvent]; |
} |
} |
|
- (void)drawRect:(NSRect)dirtyRect |
{ |
NSRect bounds = self.bounds; |
NSRect boxRect = NSMakeRect(bounds.origin.x, |
bounds.origin.y + 5, |
AAPLCheckboxWidth, |
AAPLCheckboxHeight); |
|
NSRect textRect = NSMakeRect(bounds.origin.x + AAPLCheckboxWidth + AAPLCheckboxTextSpacing, |
bounds.origin.y, |
bounds.size.width, |
bounds.size.height); |
|
// Draw the checkbox box |
NSBundle *bundle = [NSBundle mainBundle]; |
NSImage *boxImage = nil; |
|
if ( self.checked ) |
{ |
boxImage = [bundle imageForResource:AAPLCheckboxSelected]; |
} |
else |
{ |
boxImage = [bundle imageForResource:AAPLCheckboxUnselected]; |
} |
|
[boxImage drawInRect:boxRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; |
|
// Draw the checkbox text |
NSDictionary *textAttributes = @{ NSFontAttributeName : [NSFont fontWithName:@"Andale Mono" size:16.0f], |
NSForegroundColorAttributeName : [NSColor blackColor] }; |
[self.checkboxText drawInRect:textRect withAttributes:textAttributes]; |
|
// Draw the focus ring |
BOOL isFirstResponder = [[[NSApp mainWindow] firstResponder] isEqual:self]; |
if ( isFirstResponder ) |
{ |
[NSGraphicsContext saveGraphicsState]; |
NSSetFocusRingStyle(NSFocusRingOnly); |
[[NSBezierPath bezierPathWithRect:boxRect] fill]; |
[NSGraphicsContext restoreGraphicsState]; |
} |
} |
|
#pragma mark Accessibility |
|
- (NSString *)accessibilityLabel |
{ |
return self.checkboxText; |
} |
|
- (NSNumber *)accessibilityValue |
{ |
return self.checked ? @YES : @NO; |
} |
|
- (BOOL)accessibilityPerformPress |
{ |
[self toggleCheckedState]; |
return YES; |
} |
|
@end |