TicTacToe/AAPLTicTacToeCheckboxView.m
/* |
Copyright (C) 2016 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) IBInspectable NSString *checkboxText; |
@property (nonatomic) BOOL checked; |
@end |
@implementation AAPLTicTacToeCheckboxView |
- (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 |
// Obtain the bundle based on our class in order to support `IB_DESIGNABLE`. |
NSBundle *bundle = [NSBundle bundleForClass:[self class]]; |
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 |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-02-18