AccessibilityUIExamples: Version 3.0, 2017-09-12
Rewritten in Swift 4. This sample contains examples of several common control elements with various implementations and code to make them accessible, including using the accessibility methods of NSControl subclasses and implementing accessibility protocols for custom elements. Signed-off-by: Liu Lantao <liulantao@gmail.com>
|
@ -0,0 +1,10 @@
|
|||
# See LICENSE folder for this sample’s licensing information.
|
||||
#
|
||||
# Apple sample code gitignore configuration.
|
||||
|
||||
# Finder
|
||||
.DS_Store
|
||||
|
||||
# Xcode - User files
|
||||
xcuserdata/
|
||||
*.xcworkspace
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<array/>
|
||||
</plist>
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
This sample's application delegate.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Helpful extension to Character.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension Character {
|
||||
init?(_ ascii: Int) {
|
||||
guard let scalar = UnicodeScalar(ascii) else {
|
||||
return nil
|
||||
}
|
||||
self = Character(scalar)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Encompassing view that holds the detail view controller's content.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class DetailView: NSView {
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
This sample's detail view controller showing the accessibility examples.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
import MediaLibrary
|
||||
|
||||
class DetailViewController: NSViewController {
|
||||
|
||||
@IBOutlet var descriptionField: NSTextField!
|
||||
@IBOutlet var exampleArea: NSView!
|
||||
|
||||
var detailItemRecord: Example! {
|
||||
didSet {
|
||||
// Remove the old child view controller, if any exists.
|
||||
if !childViewControllers.isEmpty {
|
||||
let vc = childViewControllers[0]
|
||||
vc.view.isHidden = true
|
||||
vc.removeFromParentViewController()
|
||||
}
|
||||
|
||||
descriptionField.stringValue = ""
|
||||
|
||||
guard detailItemRecord != nil else { return }
|
||||
|
||||
// Update the description of the example.
|
||||
descriptionField.stringValue = detailItemRecord.desc
|
||||
|
||||
// Check if this sample actually has a valid view controller to display.
|
||||
guard !detailItemRecord.viewControllerIdentifier.characters.isEmpty else { return }
|
||||
|
||||
// Load the example storyboard and embed.
|
||||
let storyboard: NSStoryboard =
|
||||
NSStoryboard(name: NSStoryboard.Name(rawValue: detailItemRecord.viewControllerIdentifier), bundle: nil)
|
||||
|
||||
let sceneIdentifier = NSStoryboard.SceneIdentifier(rawValue: detailItemRecord.viewControllerIdentifier)
|
||||
|
||||
guard let buttonViewController =
|
||||
storyboard.instantiateController(withIdentifier: sceneIdentifier) as? NSViewController else { return }
|
||||
|
||||
insertChildViewController(buttonViewController, at: 0)
|
||||
|
||||
buttonViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
view.addSubview(buttonViewController.view)
|
||||
|
||||
// Add the proper constraints to the detail view controller so it embeds properly with it's parent view controller.
|
||||
let top = NSLayoutConstraint(item: buttonViewController.view,
|
||||
attribute: .top,
|
||||
relatedBy: .equal,
|
||||
toItem: exampleArea,
|
||||
attribute: .top,
|
||||
multiplier: 1,
|
||||
constant: 0)
|
||||
let left = NSLayoutConstraint(item: buttonViewController.view,
|
||||
attribute: .left,
|
||||
relatedBy: .equal,
|
||||
toItem: exampleArea,
|
||||
attribute: .left,
|
||||
multiplier: 1,
|
||||
constant: 0)
|
||||
let height = NSLayoutConstraint(item: buttonViewController.view,
|
||||
attribute: .height,
|
||||
relatedBy: .equal,
|
||||
toItem: exampleArea,
|
||||
attribute: .height,
|
||||
multiplier: 1,
|
||||
constant: 0)
|
||||
let width = NSLayoutConstraint(item: buttonViewController.view,
|
||||
attribute: .width,
|
||||
relatedBy: .equal,
|
||||
toItem: exampleArea,
|
||||
attribute: .width,
|
||||
multiplier: 1,
|
||||
constant: 0)
|
||||
view.addConstraints([top, left, height, width])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Object to describe an accessibility example.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
class Example: NSObject {
|
||||
var name = ""
|
||||
var desc = ""
|
||||
var viewControllerIdentifier = ""
|
||||
|
||||
init(name: String, description: String, viewControllerIdentifier: String) {
|
||||
self.name = name
|
||||
self.desc = description
|
||||
self.viewControllerIdentifier = viewControllerIdentifier
|
||||
super.init()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Encompassing view that holds the master view controller's content.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class MasterView: NSView {
|
||||
|
||||
}
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
This sample's master view controller listing all the Accessibility examples.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class MasterViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// The array controller data source of Examples.
|
||||
@IBOutlet var examplesArrayController: NSArrayController!
|
||||
|
||||
// The data source for "examplesArrayController".
|
||||
@objc var examplesArrayBacking = [Example]()
|
||||
|
||||
// So we can inform the delegate of table selection changes (from the user or from the array controller).
|
||||
weak var delegate: MasterViewControllerDelegate?
|
||||
|
||||
// MARK: - View Controller Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
addButtonTests()
|
||||
addTextTests()
|
||||
addSwitchesTests()
|
||||
addImagesTests()
|
||||
addOtherTests()
|
||||
addRotorTests()
|
||||
|
||||
// Changing the backed array alone won't update the array controller, so set the array controller content.
|
||||
let indexes = IndexSet(integersIn: 0...examplesArrayBacking.count)
|
||||
examplesArrayController.willChange(.setting, valuesAt: indexes, forKey: "content")
|
||||
examplesArrayController.content = examplesArrayBacking
|
||||
examplesArrayController.didChange(.setting, valuesAt: indexes, forKey: "content")
|
||||
|
||||
// Listen for when the array controller changes it's selection.
|
||||
examplesArrayController.addObserver(self,
|
||||
forKeyPath: "selectionIndexes",
|
||||
options: NSKeyValueObservingOptions.new,
|
||||
context: nil)
|
||||
}
|
||||
|
||||
// MARK: - NSTableViewDataSource
|
||||
|
||||
public func numberOfRows(in tableView: NSTableView) -> Int {
|
||||
return (examplesArrayController.arrangedObjects as AnyObject).count
|
||||
}
|
||||
|
||||
public func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
|
||||
var result = false
|
||||
if let example = (examplesArrayController.arrangedObjects as AnyObject).object(at: row) as? Example {
|
||||
// A group row has no view controller.
|
||||
result = example.viewControllerIdentifier.characters.isEmpty
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// MARK: - NSTableViewDelegate
|
||||
|
||||
public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
||||
guard let example = (examplesArrayController.arrangedObjects as AnyObject).object(at: row) as? Example else { return nil }
|
||||
|
||||
// A group row has no view controller.
|
||||
if example.viewControllerIdentifier.characters.isEmpty {
|
||||
guard let cell =
|
||||
tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "GroupCell"),
|
||||
owner: self) as? NSTextField else { return nil }
|
||||
cell.stringValue = example.name
|
||||
return cell
|
||||
} else {
|
||||
guard let cell =
|
||||
tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "MainCell"),
|
||||
owner: self) as? NSTableCellView else { return nil }
|
||||
cell.textField?.stringValue = example.name
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - KVO
|
||||
|
||||
/**
|
||||
Used for observing for NSArrayController selection changes:
|
||||
(selection changes as a result of filtering (user search) will not send NSTableViewSelectionDidChangeNotification),
|
||||
so we handle it right here to help target our detail view controller.
|
||||
*/
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?,
|
||||
change: [NSKeyValueChangeKey : Any]?,
|
||||
context: UnsafeMutableRawPointer?) {
|
||||
if keyPath! == "selectionIndexes" {
|
||||
// Obtain the selection index from our array controller.
|
||||
if let arrayController = object as? NSArrayController {
|
||||
if arrayController.selectionIndex == NSNotFound {
|
||||
delegate!.didChangeExampleSelection(masterViewController: self, selection: nil)
|
||||
} else {
|
||||
if delegate != nil {
|
||||
let viewControllers = examplesArrayController.arrangedObjects as AnyObject
|
||||
if let example =
|
||||
viewControllers.object(at: arrayController.selectionIndex) as? Example {
|
||||
delegate!.didChangeExampleSelection(masterViewController: self, selection: example)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Table Configuration
|
||||
|
||||
fileprivate func addButtonTests() {
|
||||
examplesArrayBacking.append(Example(name: NSLocalizedString("Buttons", comment: "Buttons group name"),
|
||||
description: "",
|
||||
viewControllerIdentifier: ""))
|
||||
|
||||
examplesArrayBacking.append(Example(name: NSLocalizedString("NSButton", comment: "NSButton example name"),
|
||||
description: NSLocalizedString("NSButtonDescription", comment: "NSButton example description"),
|
||||
viewControllerIdentifier: "ButtonViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("NSButton with image", comment: "NSButton with image"),
|
||||
description: NSLocalizedString("NSButtonWithImageDescription", comment: "NSButton with image example description"),
|
||||
viewControllerIdentifier: "ButtonWithImageViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("NSButton subclass", comment: "NSButton subclass"),
|
||||
description: NSLocalizedString("NSButtonSubclassDescription", comment: "NSButton subclass example description"),
|
||||
viewControllerIdentifier: "ButtonSubclassViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("NSView subclass", comment: "NSView subclass"),
|
||||
description: NSLocalizedString("NSViewSubclassButtonDescription", comment: "NSView subclass button example description"),
|
||||
viewControllerIdentifier: "ButtonViewSubclassViewController"))
|
||||
}
|
||||
|
||||
fileprivate func addTextTests() {
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Text", comment: "Text group name"),
|
||||
description: "",
|
||||
viewControllerIdentifier: ""))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Protected", comment: "Protected title"),
|
||||
description: NSLocalizedString("ProtectedDescription", comment: "Protected example description"),
|
||||
viewControllerIdentifier: "ProtectedTextViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("CoreText", comment: "CoreText title"),
|
||||
description: NSLocalizedString("CoreTextDescription", comment: "CoreText example description"),
|
||||
viewControllerIdentifier: "CoreTextViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Columns", comment: "Columns title"),
|
||||
description: NSLocalizedString("ColumnDescription", comment: "Column example description"),
|
||||
viewControllerIdentifier: "CoreTextColumnViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Text Attributes", comment: "TextAttributes title"),
|
||||
description: NSLocalizedString("TextAttributesDescription", comment: "Text Attributes description"),
|
||||
viewControllerIdentifier: "TextAttributesViewController"))
|
||||
}
|
||||
|
||||
fileprivate func addSwitchesTests() {
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Switches", comment: "Switches group name"),
|
||||
description: "",
|
||||
viewControllerIdentifier: ""))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("TwoPositionTitle", comment: "Two position example name"),
|
||||
description: NSLocalizedString("TwoPositionDescription", comment: "Two position example description"),
|
||||
viewControllerIdentifier: "TwoPositionSwitchViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("ThreePositionTitle", comment: "Three position example name"),
|
||||
description: NSLocalizedString("ThreePositionDescription", comment: "Three position example description"),
|
||||
viewControllerIdentifier: "ThreePositionSwitchViewController"))
|
||||
}
|
||||
|
||||
fileprivate func addImagesTests() {
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Images", comment: "Images group name"),
|
||||
description: "",
|
||||
viewControllerIdentifier: ""))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("NSImageView subclass", comment: "NSImageView subclass example name"),
|
||||
description: NSLocalizedString("NSImageViewSubclassDescription", comment: "NSImageView subclass example description"),
|
||||
viewControllerIdentifier: "ImageViewSubclassViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("NSView subclass", comment: "NSView subclass example name"),
|
||||
description: NSLocalizedString("NSViewSubclassImageDescription", comment: "NSView subclass image example description"),
|
||||
viewControllerIdentifier: "ViewImageSubclassViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("CALayer subclass", comment: "CALayer subclass example name"),
|
||||
description: NSLocalizedString("CALayerSubclassImageDescription", comment: "CALayer subclass image example description"),
|
||||
viewControllerIdentifier: "ImageViewLayerImageViewController"))
|
||||
}
|
||||
|
||||
fileprivate func addOtherTests() {
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Other Elements", comment: "Other elements group name"),
|
||||
description: "",
|
||||
viewControllerIdentifier: ""))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Radio Button", comment: "Radio button example name"),
|
||||
description: NSLocalizedString("RadioButtonDescription", comment: "Radio button example description"),
|
||||
viewControllerIdentifier: "CustomRadioButtonsViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Checkbox", comment: "Checkbox example name"),
|
||||
description: NSLocalizedString("CheckboxDescription", comment: "Checkbox example description"),
|
||||
viewControllerIdentifier: "CustomCheckBoxViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Slider", comment: "Slider example name"),
|
||||
description: NSLocalizedString("SliderDescription", comment: "Slider example description"),
|
||||
viewControllerIdentifier: "CustomSliderViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Layout Area", comment: "Layout area example name"),
|
||||
description: NSLocalizedString("LayoutAreaDescription", comment: "Layout area example description"),
|
||||
viewControllerIdentifier: "CustomLayoutAreaViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Outline", comment: "Outline example name"),
|
||||
description: NSLocalizedString("OutlineDescription", comment: "Outline example description"),
|
||||
viewControllerIdentifier: "CustomOutlineViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Table", comment: "Table example name"),
|
||||
description: NSLocalizedString("TableDescription", comment: "Table example description"),
|
||||
viewControllerIdentifier: "CustomTableViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Stepper", comment: "Stepper example name"),
|
||||
description: NSLocalizedString("StepperDescription", comment: "Stepper example description"),
|
||||
viewControllerIdentifier: "CustomStepperViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Transient UI", comment: "Transient UI example name"),
|
||||
description: NSLocalizedString("TransientUIDescription", comment: "Transient UI example description"),
|
||||
viewControllerIdentifier: "TransientUIViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Search Field", comment: "Search field example name"),
|
||||
description: NSLocalizedString("SearchFieldDescription", comment: "Search field example description"),
|
||||
viewControllerIdentifier: "CustomSearchFieldViewController"))
|
||||
}
|
||||
|
||||
fileprivate func addRotorTests () {
|
||||
if #available(OSX 10.13, *) {
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Custom Rotors", comment: "Custom Rotors group name"),
|
||||
description: "",
|
||||
viewControllerIdentifier: ""))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Element Rotors", comment: "Element rotors example name"),
|
||||
description: NSLocalizedString("ElementRotorsDescription", comment: "Element rotors example description"),
|
||||
viewControllerIdentifier: "CustomRotorsElementViewController"))
|
||||
|
||||
examplesArrayBacking.append(
|
||||
Example(name: NSLocalizedString("Text Rotors", comment: "Text rotors example name"),
|
||||
description: NSLocalizedString("TextRotorsDescription", comment: "Text rotors example description"),
|
||||
viewControllerIdentifier: "CustomRotorsTextViewController"))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Used for informing the delegate of the array controller selection change (as a result of filtering from the search field).
|
||||
protocol MasterViewControllerDelegate : class {
|
||||
func didChangeExampleSelection(masterViewController: MasterViewController, selection: Example?)
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
This sample's split view managing both the master and detail view controllers.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class SplitViewController: NSSplitViewController, MasterViewControllerDelegate {
|
||||
|
||||
var masterViewController: MasterViewController!
|
||||
var detailViewController: DetailViewController!
|
||||
|
||||
// MARK: - View Controller Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Note: we keep the left split view item from growing as the window grows by setting its hugging priority to 200,
|
||||
// and the right to 199. The view with the lowest priority will be the first to take on additional width if the
|
||||
// split view grows or shrinks.
|
||||
//
|
||||
splitView.adjustSubviews()
|
||||
|
||||
masterViewController = splitViewItems[0].viewController as? MasterViewController
|
||||
masterViewController.delegate = self // Listen for table view selection changes
|
||||
|
||||
if let detailViewController = splitViewItems[1].viewController as? DetailViewController {
|
||||
self.detailViewController = detailViewController
|
||||
} else {
|
||||
fatalError("SplitViewController is not configured correctly.")
|
||||
}
|
||||
|
||||
splitView.autosaveName = NSSplitView.AutosaveName(rawValue: "SplitViewAutoSave") // Remember the split view position.
|
||||
}
|
||||
|
||||
// MARK: - MasterViewControllerDelegate
|
||||
|
||||
func didChangeExampleSelection(masterViewController: MasterViewController, selection: Example?) {
|
||||
detailViewController.detailItemRecord = selection
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
The sample's main window controller.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
import Foundation
|
||||
|
||||
class WindowController: NSWindowController {
|
||||
override func windowDidLoad() {
|
||||
super.windowDidLoad()
|
||||
|
||||
// Let the window accept (and distribute) mouse-moved events.
|
||||
window?.acceptsMouseMovedEvents = true
|
||||
|
||||
// Window is not transparent to mouse events.
|
||||
window?.ignoresMouseEvents = false
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ButtonSubclassViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ButtonSubclassViewController" id="BJj-AK-Or5" userLabel="ButtonSubclassViewController" customClass="ButtonSubclassViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw" userLabel="View">
|
||||
<rect key="frame" x="0.0" y="0.0" width="129" height="72"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WEw-Zi-mU6">
|
||||
<rect key="frame" x="-2" y="54" width="133" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Press Count" id="5ic-DW-A4h">
|
||||
<font key="font" metaFont="system" size="14"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tQy-8g-bOp" customClass="CustomButton" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="129" height="46"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="xMv-9U-ibI">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="pressButton:" target="BJj-AK-Or5" id="iQp-pe-EC7"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="button" destination="tQy-8g-bOp" id="JhH-l1-oep"/>
|
||||
<outlet property="pressCountTextField" destination="WEw-Zi-mU6" id="D46-8o-Via"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="585.5" y="1082"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ButtonViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ButtonViewController" id="BJj-AK-Or5" userLabel="ButtonViewController" customClass="ButtonViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="130" height="55"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZeC-FC-Anu">
|
||||
<rect key="frame" x="-3" y="37" width="134" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Press Count" id="yTe-E0-hsJ">
|
||||
<font key="font" metaFont="system" size="14"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<outlet property="nextKeyView" destination="ark-tc-VDT" id="dtP-xE-0Mz"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ark-tc-VDT">
|
||||
<rect key="frame" x="3" y="1" width="129" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Play" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="0VH-1k-P0U">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="pressButton:" target="BJj-AK-Or5" id="tck-H7-hAL"/>
|
||||
<outlet property="nextKeyView" destination="ZeC-FC-Anu" id="9Rl-TE-NPH"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="button" destination="ark-tc-VDT" id="ykr-6o-avJ"/>
|
||||
<outlet property="pressCountTextField" destination="ZeC-FC-Anu" id="zKx-RZ-Pau"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="502" y="1041.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ButtonViewSubclassViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ButtonViewSubclassViewController" id="BJj-AK-Or5" userLabel="ButtonViewSubclassViewController" customClass="ButtonViewSubclassViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw" userLabel="View">
|
||||
<rect key="frame" x="0.0" y="0.0" width="129" height="72"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WEw-Zi-mU6">
|
||||
<rect key="frame" x="-2" y="54" width="133" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Press Count" id="5ic-DW-A4h">
|
||||
<font key="font" metaFont="system" size="14"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="d7m-7i-oT9" customClass="CustomButtonView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="129" height="46"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="customButton" destination="d7m-7i-oT9" id="1HG-Oq-pZ6"/>
|
||||
<outlet property="pressCountTextField" destination="WEw-Zi-mU6" id="D46-8o-Via"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="585.5" y="1082"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ButtonWithImageViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ButtonWithImageViewController" id="BJj-AK-Or5" userLabel="ButtonWithImageViewController" customClass="ButtonWithImageViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="129" height="72"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dew-wf-5RT">
|
||||
<rect key="frame" x="-2" y="54" width="133" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Press Count" id="eRL-Qq-S9b">
|
||||
<font key="font" metaFont="system" size="14"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RiL-hx-058">
|
||||
<rect key="frame" x="0.0" y="0.0" width="129" height="46"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="bevel" bezelStyle="regularSquare" image="CustomButtonUp" imagePosition="overlaps" alignment="center" alternateImage="CustomButtonDown" imageScaling="proportionallyDown" inset="2" id="Us2-lu-vZk">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<accessibility description="Play"/>
|
||||
<connections>
|
||||
<action selector="pressButton:" target="BJj-AK-Or5" id="wh0-Wd-c3Z"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="button" destination="RiL-hx-058" id="YIl-wj-I5J"/>
|
||||
<outlet property="pressCountTextField" destination="dew-wf-5RT" id="UeH-1j-HhH"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="429.5" y="904"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="CustomButtonDown" width="129" height="46"/>
|
||||
<image name="CustomButtonUp" width="129" height="46"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CoreTextColumnViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CoreTextColumnViewController" id="BJj-AK-Or5" userLabel="CoreTextColumnViewController" customClass="CoreTextColumnViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="275" height="175"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3yv-mZ-RDZ" customClass="CoreTextColumnView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="275" height="175"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="574.5" y="1101.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CoreTextViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CoreTextViewController" id="BJj-AK-Or5" userLabel="CoreTextViewController" customClass="CoreTextViewController" customModule="AccessibilityUIExamples" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="396" height="140"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ib2-VN-Qgc" customClass="CoreTextView" customModule="AccessibilityUIExamples">
|
||||
<rect key="frame" x="0.0" y="0.0" width="396" height="140"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="635" y="1084"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomCheckBoxViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomCheckBoxViewController" id="BJj-AK-Or5" userLabel="CustomCheckBoxViewController" customClass="CustomCheckBoxViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="156" height="46"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mZ4-Bm-OSA">
|
||||
<rect key="frame" x="-2" y="24" width="160" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" id="opR-er-Z7J">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="krx-cO-it1" customClass="CustomCheckBoxView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="156" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<accessibility description="asdfsdf" help="asdfsdaf"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="currentValueLabel" destination="mZ4-Bm-OSA" id="NEw-Lr-udo"/>
|
||||
<outlet property="customCheckbox" destination="krx-cO-it1" id="ZQh-jC-uYN"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="108" y="347"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomLayoutAreaViewController-->
|
||||
<scene sceneID="hKU-qV-ATb">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="CustomLayoutAreaViewController" id="c52-Xj-hbh" userLabel="CustomLayoutAreaViewController" customClass="CustomLayoutAreaViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="9EN-CY-y63">
|
||||
<rect key="frame" x="0.0" y="0.0" width="399" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="ftc-aO-6sZ" customClass="CustomLayoutAreaView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="399" height="300"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="ftc-aO-6sZ" firstAttribute="leading" secondItem="9EN-CY-y63" secondAttribute="leading" id="4A8-j3-LFF"/>
|
||||
<constraint firstAttribute="bottom" secondItem="ftc-aO-6sZ" secondAttribute="bottom" id="63A-5W-S0X"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ftc-aO-6sZ" secondAttribute="trailing" id="Ppn-iQ-aFG"/>
|
||||
<constraint firstItem="ftc-aO-6sZ" firstAttribute="top" secondItem="9EN-CY-y63" secondAttribute="top" id="d5n-Bq-Vh3"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<customObject id="kDp-1D-6wp" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="528.5" y="714"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomOutlineViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomOutlineViewController" id="BJj-AK-Or5" userLabel="CustomOutlineViewController" customClass="CustomOutlineViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="275" height="175"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="zzq-8G-dPT" customClass="CustomOutlineView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="275" height="175"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="zzq-8G-dPT" secondAttribute="bottom" id="BWH-jB-R6p"/>
|
||||
<constraint firstItem="zzq-8G-dPT" firstAttribute="top" secondItem="ugI-Pl-CNw" secondAttribute="top" id="Vl1-dO-9Oe"/>
|
||||
<constraint firstAttribute="trailing" secondItem="zzq-8G-dPT" secondAttribute="trailing" id="gOY-al-fpe"/>
|
||||
<constraint firstItem="zzq-8G-dPT" firstAttribute="leading" secondItem="ugI-Pl-CNw" secondAttribute="leading" id="t5G-ST-nOd"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="574.5" y="1101.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomRadioButtonsViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomRadioButtonsViewController" id="BJj-AK-Or5" userLabel="CustomRadioButtonsViewController" customClass="CustomRadioButtonsViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="156" height="105"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3Yf-L9-TqY" customClass="CustomRadioButtonsView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="125" height="75"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mZ4-Bm-OSA">
|
||||
<rect key="frame" x="-2" y="83" width="160" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" id="opR-er-Z7J">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="currentValueLabel" destination="mZ4-Bm-OSA" id="NEw-Lr-udo"/>
|
||||
<outlet property="customRadios" destination="3Yf-L9-TqY" id="Adh-C5-m2g"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="108" y="376.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,338 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13168.2" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13168.2"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomRotorsElementViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomRotorsElementViewController" id="BJj-AK-Or5" userLabel="CustomRotorsElementViewController" customClass="CustomRotorsElementViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<customView key="view" id="QRw-6Y-XVN" userLabel="View">
|
||||
<rect key="frame" x="0.0" y="0.0" width="560" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<view translatesAutoresizingMaskIntoConstraints="NO" id="Nao-RQ-Aiq" customClass="CustomRotorsContainerView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="93" width="560" height="178"/>
|
||||
<subviews>
|
||||
<view translatesAutoresizingMaskIntoConstraints="NO" id="aVl-nv-Ztd" userLabel="Page 1 View" customClass="CustomRotorsPageView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="7" y="6" width="176" height="166"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="176" id="6Px-IS-MAK"/>
|
||||
<constraint firstAttribute="height" constant="166" id="nPy-vF-mvW"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view translatesAutoresizingMaskIntoConstraints="NO" id="gtS-gW-fhK" userLabel="Page 2 View" customClass="CustomRotorsPageView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="191" y="6" width="176" height="166"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="176" id="YZ9-JT-VZg"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view translatesAutoresizingMaskIntoConstraints="NO" id="2wq-nN-WWj" userLabel="Page 3 View" customClass="CustomRotorsPageView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="375" y="6" width="176" height="166"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="176" id="4J5-Pz-QjJ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="gtS-gW-fhK" firstAttribute="top" secondItem="2wq-nN-WWj" secondAttribute="top" id="0lF-mt-F23"/>
|
||||
<constraint firstItem="aVl-nv-Ztd" firstAttribute="top" secondItem="Nao-RQ-Aiq" secondAttribute="top" constant="6" id="1UN-cD-lCd"/>
|
||||
<constraint firstAttribute="width" constant="560" id="3v3-Uu-P3R"/>
|
||||
<constraint firstItem="aVl-nv-Ztd" firstAttribute="leading" secondItem="Nao-RQ-Aiq" secondAttribute="leading" constant="7" id="Bhi-hi-0gN"/>
|
||||
<constraint firstItem="gtS-gW-fhK" firstAttribute="baseline" secondItem="2wq-nN-WWj" secondAttribute="baseline" id="FIi-1X-Wag"/>
|
||||
<constraint firstItem="2wq-nN-WWj" firstAttribute="leading" secondItem="gtS-gW-fhK" secondAttribute="trailing" constant="8" id="fZ0-SK-nRn"/>
|
||||
<constraint firstAttribute="height" constant="178" id="gIo-EK-a0j"/>
|
||||
<constraint firstItem="aVl-nv-Ztd" firstAttribute="top" secondItem="gtS-gW-fhK" secondAttribute="top" id="h1W-Jm-vi0"/>
|
||||
<constraint firstItem="aVl-nv-Ztd" firstAttribute="baseline" secondItem="gtS-gW-fhK" secondAttribute="baseline" id="h3L-j6-GuM"/>
|
||||
<constraint firstItem="gtS-gW-fhK" firstAttribute="leading" secondItem="aVl-nv-Ztd" secondAttribute="trailing" constant="8" id="krk-RI-Dml"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="sLV-g1-35T">
|
||||
<rect key="frame" x="227" y="279" width="107" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Fruits and Colors" id="7fW-lD-TUQ">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="6Tq-IE-zUv">
|
||||
<rect key="frame" x="193" y="57" width="175" height="28"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lgL-7b-S8P">
|
||||
<rect key="frame" x="-4" y="0.0" width="93" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Previous" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="gfM-aW-05T">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="previousPage:" target="BJj-AK-Or5" id="32k-zh-NqL"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="YCF-zD-Vrk">
|
||||
<rect key="frame" x="85" y="0.0" width="93" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Next" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="tSi-cR-pBf">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="nextPage:" target="BJj-AK-Or5" id="88x-kI-mgn"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="6Tq-IE-zUv" firstAttribute="leading" secondItem="QRw-6Y-XVN" secondAttribute="leading" constant="193" id="4f9-HR-lbm"/>
|
||||
<constraint firstItem="Nao-RQ-Aiq" firstAttribute="centerX" secondItem="sLV-g1-35T" secondAttribute="centerX" id="8WZ-et-XYe"/>
|
||||
<constraint firstAttribute="bottom" secondItem="6Tq-IE-zUv" secondAttribute="bottom" constant="57" id="Ca4-4d-q9N"/>
|
||||
<constraint firstItem="6Tq-IE-zUv" firstAttribute="top" secondItem="Nao-RQ-Aiq" secondAttribute="bottom" constant="8" symbolic="YES" id="UCR-qC-RLt"/>
|
||||
<constraint firstItem="Nao-RQ-Aiq" firstAttribute="top" secondItem="QRw-6Y-XVN" secondAttribute="top" constant="29" id="Up1-Cp-ecA"/>
|
||||
<constraint firstItem="Nao-RQ-Aiq" firstAttribute="leading" secondItem="QRw-6Y-XVN" secondAttribute="leading" id="UrY-e1-Fcr"/>
|
||||
<constraint firstItem="Nao-RQ-Aiq" firstAttribute="centerX" secondItem="6Tq-IE-zUv" secondAttribute="centerX" id="byy-J7-37f"/>
|
||||
<constraint firstItem="Nao-RQ-Aiq" firstAttribute="top" secondItem="sLV-g1-35T" secondAttribute="bottom" constant="8" symbolic="YES" id="oNd-LS-ebM"/>
|
||||
<constraint firstItem="6Tq-IE-zUv" firstAttribute="top" secondItem="Nao-RQ-Aiq" secondAttribute="bottom" constant="8" id="ub3-Aj-fbC"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
<connections>
|
||||
<outlet property="containerView" destination="Nao-RQ-Aiq" id="1ol-ut-hjF"/>
|
||||
<outlet property="contentView1" destination="T6C-IV-a4L" id="Xyl-Qt-gTW"/>
|
||||
<outlet property="contentView2" destination="54k-5f-kvE" id="SQm-TX-0VM"/>
|
||||
<outlet property="contentView3" destination="qd0-Qf-qIH" id="0Bx-Ve-D2h"/>
|
||||
<outlet property="pageView1" destination="aVl-nv-Ztd" id="LpX-5S-MWV"/>
|
||||
<outlet property="pageView2" destination="gtS-gW-fhK" id="g1l-ya-kj3"/>
|
||||
<outlet property="pageView3" destination="2wq-nN-WWj" id="fsY-qS-o5w"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<view id="qd0-Qf-qIH" userLabel="View 3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="176" height="166"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kgQ-Oc-mn6">
|
||||
<rect key="frame" x="1" y="83" width="108" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Purple Figs" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="bw6-I8-fgt">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nDF-jQ-i3C">
|
||||
<rect key="frame" x="2" y="117" width="107" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Strawberry" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="18q-k5-gE6">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="yQJ-jw-g75">
|
||||
<rect key="frame" x="44" y="46" width="65" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Kiwi" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="eXX-8g-ola">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4eA-XM-ptG">
|
||||
<rect key="frame" x="109" y="92" width="44" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Purple" id="gnZ-KO-MTT">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.54260993000000002" green="0.092973388729999995" blue="0.55200314520000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jHa-S7-P9q">
|
||||
<rect key="frame" x="109" y="22" width="49" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Orange" id="0d6-H4-Y2c">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="1" green="0.57810515169999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="OPa-E7-yuh">
|
||||
<rect key="frame" x="109" y="127" width="28" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Red" id="lfQ-Ek-fZB">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="csR-B9-eW4">
|
||||
<rect key="frame" x="109" y="55" width="41" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Green" id="4ec-mE-mHd">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.30840110780000002" green="0.5618229508" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8qn-Hn-by6">
|
||||
<rect key="frame" x="27" y="13" width="82" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Mango" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ChQ-a1-FRL">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<view id="T6C-IV-a4L" userLabel="View 1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="176" height="166"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RdC-RY-Yfb">
|
||||
<rect key="frame" x="32" y="83" width="77" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Grape" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="JFp-v8-ewH">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="S9n-QT-0R7">
|
||||
<rect key="frame" x="34" y="117" width="75" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Apple" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="JbV-jp-sJI">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7sZ-xI-9sn">
|
||||
<rect key="frame" x="39" y="46" width="70" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Lime" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="NGE-g6-oBW">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="B0t-C4-h95">
|
||||
<rect key="frame" x="109" y="92" width="44" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Purple" id="U0m-t2-khR">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.54260993000000002" green="0.092973388729999995" blue="0.55200314520000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="r8o-qW-E3Y">
|
||||
<rect key="frame" x="109" y="22" width="49" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Orange" id="Hz0-wE-hRx">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="1" green="0.57810515169999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2yT-rk-9Tb">
|
||||
<rect key="frame" x="109" y="127" width="28" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Red" id="hPL-uJ-obk">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="laG-oP-Vtv">
|
||||
<rect key="frame" x="109" y="55" width="41" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Green" id="SLq-0w-m3D">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.30840110780000002" green="0.5618229508" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ibK-Yu-jh5">
|
||||
<rect key="frame" x="25" y="13" width="84" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Apricot" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="8K3-Cp-dQY">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<view id="54k-5f-kvE" userLabel="View 2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="176" height="166"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gnM-Ab-6f7">
|
||||
<rect key="frame" x="32" y="82" width="77" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Plums" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="zSC-QN-cLh">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fbN-iI-Pmf">
|
||||
<rect key="frame" x="8" y="117" width="101" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Cranberry" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="2yb-cP-vrp">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Ec-Yr-dqZ">
|
||||
<rect key="frame" x="17" y="46" width="92" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Avacado" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Qv7-zl-Gnf">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="MWW-ol-xlF">
|
||||
<rect key="frame" x="109" y="92" width="44" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Purple" id="LRa-Wq-W6U">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.54260993000000002" green="0.092973388729999995" blue="0.55200314520000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZkX-et-o34">
|
||||
<rect key="frame" x="109" y="22" width="49" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Orange" id="LYW-68-C3h">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="1" green="0.57810515169999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DXf-td-iS4">
|
||||
<rect key="frame" x="109" y="127" width="28" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Red" id="Fvh-yM-L4j">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="isf-8E-dSE">
|
||||
<rect key="frame" x="109" y="55" width="41" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Green" id="dsa-f8-sXM">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" red="0.30840110780000002" green="0.5618229508" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0WC-Vl-8Wv">
|
||||
<rect key="frame" x="9" y="13" width="100" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Tangerine" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="zsq-A3-qK9">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="585" y="946"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13168.2" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13168.2"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomRotorsTextViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomRotorsTextViewController" id="BJj-AK-Or5" userLabel="CustomRotorsTextViewController" customClass="CustomRotorsTextViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="260"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hAx-Qa-OEk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="260"/>
|
||||
<clipView key="contentView" id="Wi6-Ui-3KE">
|
||||
<rect key="frame" x="1" y="1" width="238" height="258"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView importsGraphics="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="WaL-5a-fOP" customClass="CustomRotorsTextView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="238" height="258"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<size key="minSize" width="238" height="258"/>
|
||||
<size key="maxSize" width="463" height="10000000"/>
|
||||
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="mR7-eb-Kz6">
|
||||
<rect key="frame" x="-100" y="-100" width="87" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="geh-Px-FZ9">
|
||||
<rect key="frame" x="223" y="1" width="16" height="258"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="hAx-Qa-OEk" firstAttribute="top" secondItem="ugI-Pl-CNw" secondAttribute="top" id="8Yn-if-Yxy"/>
|
||||
<constraint firstAttribute="bottom" secondItem="hAx-Qa-OEk" secondAttribute="bottom" id="Jye-11-dkl"/>
|
||||
<constraint firstAttribute="trailing" secondItem="hAx-Qa-OEk" secondAttribute="trailing" id="wcH-FB-RFq"/>
|
||||
<constraint firstItem="hAx-Qa-OEk" firstAttribute="leading" secondItem="ugI-Pl-CNw" secondAttribute="leading" id="x0X-VF-oZA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="textView" destination="WaL-5a-fOP" id="hPN-yY-fXw"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="403" y="892"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomSearchFieldViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomSearchFieldViewController" id="BJj-AK-Or5" userLabel="CustomSearchFieldViewController" customClass="CustomSearchFieldViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="267" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<searchField wantsLayer="YES" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ltm-uh-mjc" customClass="CustomSearchField" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="267" height="22"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="266.9999998910597" id="2lI-cm-czh"/>
|
||||
</constraints>
|
||||
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="Type a word" bezelStyle="round" id="hei-JM-di4">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</searchFieldCell>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="BJj-AK-Or5" id="UbC-5d-QnD"/>
|
||||
</connections>
|
||||
</searchField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Ltm-uh-mjc" firstAttribute="top" secondItem="ugI-Pl-CNw" secondAttribute="top" id="1NU-1Y-HEN"/>
|
||||
<constraint firstItem="Ltm-uh-mjc" firstAttribute="leading" secondItem="ugI-Pl-CNw" secondAttribute="leading" id="7gv-FG-e6M"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="searchField" destination="Ltm-uh-mjc" id="mg9-JN-Ki1"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="570.5" y="1025"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomSliderViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomSliderViewController" id="BJj-AK-Or5" userLabel="CustomSliderViewController" customClass="CustomSliderViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="191" height="140"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2eb-kD-cpF" customClass="CustomSliderView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="20" height="140"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="c84-3Z-snL" customClass="CustomSliderView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="28" y="60" width="163" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="532.5" y="1084"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13115" systemVersion="17A251a" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13115"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomStepperViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomStepperViewController" id="BJj-AK-Or5" userLabel="CustomStepperViewController" customClass="CustomStepperViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="185" height="72"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="H5M-ew-1dy">
|
||||
<rect key="frame" x="48" y="24" width="135" height="24"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="131" id="amR-Lv-oIg"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Volume: 100%" id="2uz-M8-0Kc">
|
||||
<font key="font" metaFont="system" size="20"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView focusRingType="none" translatesAutoresizingMaskIntoConstraints="NO" id="z8n-Uw-fSF" customClass="CustomStepperView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="42" height="72"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="42" id="K9V-t5-cjf"/>
|
||||
<constraint firstAttribute="height" constant="72" id="cbD-1i-9yl"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="z8n-Uw-fSF" firstAttribute="leading" secondItem="ugI-Pl-CNw" secondAttribute="leading" id="5xB-E7-o8Z"/>
|
||||
<constraint firstItem="z8n-Uw-fSF" firstAttribute="top" secondItem="ugI-Pl-CNw" secondAttribute="top" id="VT8-4s-QMz"/>
|
||||
<constraint firstItem="H5M-ew-1dy" firstAttribute="centerY" secondItem="z8n-Uw-fSF" secondAttribute="centerY" id="cIN-kd-TW3"/>
|
||||
<constraint firstItem="H5M-ew-1dy" firstAttribute="leading" secondItem="z8n-Uw-fSF" secondAttribute="trailing" constant="8" symbolic="YES" id="qm9-0j-23W"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="customStepper" destination="z8n-Uw-fSF" id="Nnv-Mg-VM7"/>
|
||||
<outlet property="volumeLevel" destination="H5M-ew-1dy" id="WJL-pW-CDd"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="386" y="1030"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--CustomTableViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="CustomTableViewController" id="BJj-AK-Or5" userLabel="CustomTableViewController" customClass="CustomTableViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="275" height="175"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Mp4-JF-P2Q" customClass="CustomTableView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="275" height="175"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="574.5" y="1101.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13122.13" systemVersion="17A274" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13122.13"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ImageViewLayerImageViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ImageViewLayerImageViewController" id="BJj-AK-Or5" userLabel="ImageViewLayerImageViewController" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="147" height="134"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8D9-Yg-26i" customClass="ImageViewLayerView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="147" height="134"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="510.5" y="1081"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13122.13" systemVersion="17A274" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13122.13"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ImageViewSubclassViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ImageViewSubclassViewController" id="BJj-AK-Or5" userLabel="ImageViewSubclassViewController" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="75" height="75"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9w1-7W-nv6" customClass="ImageViewSubclass" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="75" height="75"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="Keo-I4-XEX"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
</view>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="474.5" y="1051.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,621 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13168.3" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13168.3"/>
|
||||
<capability name="box content view" minToolsVersion="7.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Application-->
|
||||
<scene sceneID="JPo-4y-FX3">
|
||||
<objects>
|
||||
<application id="hnw-xV-0zn" sceneMemberID="viewController">
|
||||
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="AccessibilityUIExamples" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="AccessibilityUIExamples" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="About AccessibilityUIExamples" id="5kV-Vb-QxS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide AccessibilityUIExamples" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit AccessibilityUIExamples" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="File" id="dMs-cI-mzQ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
||||
<items>
|
||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
||||
<connections>
|
||||
<action selector="newDocument:" target="Ady-hI-5gd" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="Ady-hI-5gd" id="bVn-NM-KNZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="Ady-hI-5gd" id="Daa-9d-B3U"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="Ady-hI-5gd" id="HmO-Ls-i7Q"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
|
||||
<connections>
|
||||
<action selector="saveDocument:" target="Ady-hI-5gd" id="teZ-XB-qJY"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
|
||||
<connections>
|
||||
<action selector="saveDocumentAs:" target="Ady-hI-5gd" id="mDf-zr-I0C"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Revert to Saved" id="KaW-ft-85H">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="revertDocumentToSaved:" target="Ady-hI-5gd" id="iJ3-Pv-kwq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
|
||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
|
||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="runPageLayout:" target="Ady-hI-5gd" id="Din-rz-gC5"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
|
||||
<connections>
|
||||
<action selector="print:" target="Ady-hI-5gd" id="qaZ-4w-aoO"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
||||
<items>
|
||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
||||
<connections>
|
||||
<action selector="undo:" target="Ady-hI-5gd" id="M6e-cu-g7V"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
||||
<connections>
|
||||
<action selector="redo:" target="Ady-hI-5gd" id="oIA-Rs-6OD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
||||
<connections>
|
||||
<action selector="cut:" target="Ady-hI-5gd" id="YJe-68-I9s"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
||||
<connections>
|
||||
<action selector="copy:" target="Ady-hI-5gd" id="G1f-GL-Joy"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
||||
<connections>
|
||||
<action selector="paste:" target="Ady-hI-5gd" id="UvS-8e-Qdg"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="pasteAsPlainText:" target="Ady-hI-5gd" id="cEh-KX-wJQ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="delete:" target="Ady-hI-5gd" id="0Mk-Ml-PaM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
||||
<connections>
|
||||
<action selector="selectAll:" target="Ady-hI-5gd" id="VNm-Mi-diN"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
||||
<menuItem title="Find" id="4EN-yA-p0u">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
||||
<items>
|
||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="cD7-Qs-BN4"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="WD3-Gg-5AJ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="NDo-RZ-v9R"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="HOh-sY-3ay"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
||||
<connections>
|
||||
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="U76-nv-p5D"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
||||
<connections>
|
||||
<action selector="centerSelectionInVisibleArea:" target="Ady-hI-5gd" id="IOG-6D-g5B"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
||||
<items>
|
||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
||||
<connections>
|
||||
<action selector="showGuessPanel:" target="Ady-hI-5gd" id="vFj-Ks-hy3"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
||||
<connections>
|
||||
<action selector="checkSpelling:" target="Ady-hI-5gd" id="fz7-VC-reM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleContinuousSpellChecking:" target="Ady-hI-5gd" id="7w6-Qz-0kB"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleGrammarChecking:" target="Ady-hI-5gd" id="muD-Qn-j4w"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticSpellingCorrection:" target="Ady-hI-5gd" id="2lM-Qi-WAP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
||||
<items>
|
||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="orderFrontSubstitutionsPanel:" target="Ady-hI-5gd" id="oku-mr-iSq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleSmartInsertDelete:" target="Ady-hI-5gd" id="3IJ-Se-DZD"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticQuoteSubstitution:" target="Ady-hI-5gd" id="ptq-xd-QOA"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDashSubstitution:" target="Ady-hI-5gd" id="oCt-pO-9gS"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticLinkDetection:" target="Ady-hI-5gd" id="Gip-E3-Fov"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticDataDetection:" target="Ady-hI-5gd" id="R1I-Nq-Kbl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleAutomaticTextReplacement:" target="Ady-hI-5gd" id="DvP-Fe-Py6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
||||
<items>
|
||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="uppercaseWord:" target="Ady-hI-5gd" id="sPh-Tk-edu"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="lowercaseWord:" target="Ady-hI-5gd" id="iUZ-b5-hil"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="capitalizeWord:" target="Ady-hI-5gd" id="26H-TL-nsh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
||||
<items>
|
||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="startSpeaking:" target="Ady-hI-5gd" id="654-Ng-kyl"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="stopSpeaking:" target="Ady-hI-5gd" id="dX8-6p-jy9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="arrangeInFront:" target="Ady-hI-5gd" id="DRN-fu-gQh"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Help" id="wpr-3q-Mcd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||
<items>
|
||||
<menuItem title="AccessibilityUIExamples Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||
<connections>
|
||||
<action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
|
||||
</connections>
|
||||
</application>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="AccessibilityUIExamples" customModuleProvider="target"/>
|
||||
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="61.5" y="-187"/>
|
||||
</scene>
|
||||
<!--WindowController-->
|
||||
<scene sceneID="R2V-B0-nI4">
|
||||
<objects>
|
||||
<windowController storyboardIdentifier="WindowController" id="B8D-0N-5wS" userLabel="WindowController" customClass="WindowController" customModule="AccessibilityUIExamples" sceneMemberID="viewController">
|
||||
<window key="window" title="AccessibilityUIExamples" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="AccessibilityUIExamples" animationBehavior="default" id="IQv-IB-iLA">
|
||||
<windowStyleMask key="styleMask" titled="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="70" y="867" width="572" height="483"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<value key="minSize" type="size" width="500" height="300"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="B8D-0N-5wS" id="3fD-VY-N9Y"/>
|
||||
</connections>
|
||||
</window>
|
||||
<connections>
|
||||
<segue destination="web-Fo-U34" kind="relationship" relationship="window.shadowedContentViewController" id="HQ2-aq-iqT"/>
|
||||
</connections>
|
||||
</windowController>
|
||||
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="87" y="228.5"/>
|
||||
</scene>
|
||||
<!--SplitViewController-->
|
||||
<scene sceneID="6P2-ye-y1y">
|
||||
<objects>
|
||||
<splitViewController storyboardIdentifier="SplitViewController" id="web-Fo-U34" userLabel="SplitViewController" customClass="SplitViewController" customModule="AccessibilityUIExamples" sceneMemberID="viewController">
|
||||
<splitViewItems>
|
||||
<splitViewItem holdingPriority="200" id="zW2-rn-Q8n"/>
|
||||
<splitViewItem holdingPriority="199" id="bhx-lm-FZk"/>
|
||||
</splitViewItems>
|
||||
<splitView key="splitView" autosaveName="" vertical="YES" id="nfe-9g-Bpu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="web-Fo-U34" id="dpE-pY-Z51"/>
|
||||
</connections>
|
||||
</splitView>
|
||||
<connections>
|
||||
<outlet property="splitView" destination="nfe-9g-Bpu" id="A0S-ss-5re"/>
|
||||
<segue destination="vUr-xI-gvP" kind="relationship" relationship="splitItems" id="3pj-XS-aKz"/>
|
||||
<segue destination="F3c-yd-mpy" kind="relationship" relationship="splitItems" id="rzQ-nf-Ahf"/>
|
||||
</connections>
|
||||
</splitViewController>
|
||||
<customObject id="jH7-qD-UFX" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="87" y="750"/>
|
||||
</scene>
|
||||
<!--MasterViewController-->
|
||||
<scene sceneID="nNE-Au-36z">
|
||||
<objects>
|
||||
<viewController identifier="MasterViewController" storyboardIdentifier="MasterViewController" id="vUr-xI-gvP" userLabel="MasterViewController" customClass="MasterViewController" customModule="AccessibilityUIExamples" sceneMemberID="viewController">
|
||||
<view key="view" id="9Ui-rp-aCs">
|
||||
<rect key="frame" x="0.0" y="0.0" width="220" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="bt4-pu-9gO">
|
||||
<rect key="frame" x="-12" y="-14" width="251" height="327"/>
|
||||
<subviews>
|
||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="22" horizontalPageScroll="10" verticalLineScroll="22" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RT0-lX-XyC">
|
||||
<rect key="frame" x="21" y="20" width="209" height="287"/>
|
||||
<clipView key="contentView" id="Stg-O9-kxK">
|
||||
<rect key="frame" x="1" y="1" width="207" height="285"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="20" viewBased="YES" id="foP-a2-PWh">
|
||||
<rect key="frame" x="0.0" y="0.0" width="207" height="285"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn identifier="" width="204" minWidth="100" maxWidth="1000" id="wgM-8u-Glb">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Examples">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="33t-PA-F77">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView identifier="MainCell" id="bCC-v1-shG">
|
||||
<rect key="frame" x="1" y="1" width="204" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ld1-hl-XVg">
|
||||
<rect key="frame" x="6" y="1" width="197" height="17"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="17" id="aHv-dI-96k"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="5Wm-6L-5oq">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="ld1-hl-XVg" firstAttribute="centerY" secondItem="bCC-v1-shG" secondAttribute="centerY" constant="-0.5" id="Lgw-tq-bLc"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ld1-hl-XVg" secondAttribute="trailing" constant="3" id="ld1-59-vW0"/>
|
||||
<constraint firstItem="ld1-hl-XVg" firstAttribute="leading" secondItem="bCC-v1-shG" secondAttribute="leading" constant="8" id="y6C-zF-Pvu"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="textField" destination="ld1-hl-XVg" id="Yla-iR-Nhk"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
<textField identifier="GroupCell" verticalHuggingPriority="750" tag="1" id="Mcc-81-B8H">
|
||||
<rect key="frame" x="1" y="20" width="204" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" truncatesLastVisibleLine="YES" sendsActionOnEndEditing="YES" alignment="left" title="Group" id="HPq-qo-aAK">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
<connections>
|
||||
<binding destination="6dO-1e-dD4" name="selectionIndexes" keyPath="selectionIndexes" id="Zyh-rS-Ql0"/>
|
||||
<outlet property="dataSource" destination="vUr-xI-gvP" id="rI6-6q-x03"/>
|
||||
<outlet property="delegate" destination="vUr-xI-gvP" id="zb5-3z-dPu"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="XIr-9a-XQ4">
|
||||
<rect key="frame" x="1" y="216" width="207" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="c9a-jq-1Eb">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="RT0-lX-XyC" firstAttribute="centerX" secondItem="bt4-pu-9gO" secondAttribute="centerX" id="L3q-S8-0ee"/>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="251" id="PdZ-fp-2NS"/>
|
||||
<constraint firstItem="RT0-lX-XyC" firstAttribute="leading" secondItem="bt4-pu-9gO" secondAttribute="leading" constant="21" id="aJl-K1-SeR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="RT0-lX-XyC" secondAttribute="bottom" constant="20" symbolic="YES" id="cap-U3-snE"/>
|
||||
<constraint firstItem="RT0-lX-XyC" firstAttribute="top" secondItem="bt4-pu-9gO" secondAttribute="top" constant="20" symbolic="YES" id="uNs-ix-wuf"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="bt4-pu-9gO" firstAttribute="top" secondItem="9Ui-rp-aCs" secondAttribute="top" constant="-13" id="BXT-Wt-OCr"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bt4-pu-9gO" secondAttribute="trailing" constant="-19" id="CsE-4g-0VT"/>
|
||||
<constraint firstAttribute="bottom" secondItem="bt4-pu-9gO" secondAttribute="bottom" constant="-14" id="KHi-aF-yMk"/>
|
||||
<constraint firstItem="bt4-pu-9gO" firstAttribute="leading" secondItem="9Ui-rp-aCs" secondAttribute="leading" constant="-12" id="kT3-Gc-35g"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="examplesArrayController" destination="6dO-1e-dD4" id="f5Y-2k-Xt3"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<customObject id="IzE-NO-72S" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<arrayController objectClassName="Example" selectsInsertedObjects="NO" avoidsEmptySelection="NO" automaticallyRearrangesObjects="YES" id="6dO-1e-dD4" userLabel="ExamplesArrayController">
|
||||
<connections>
|
||||
<binding destination="vUr-xI-gvP" name="contentArray" keyPath="self.examplesArrayBacking" id="vxx-O7-XfN"/>
|
||||
</connections>
|
||||
</arrayController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="87" y="1182"/>
|
||||
</scene>
|
||||
<!--DetailViewController-->
|
||||
<scene sceneID="EuU-Uf-bm9">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="DetailViewController" id="F3c-yd-mpy" userLabel="DetailViewController" customClass="DetailViewController" customModule="AccessibilityUIExamples" sceneMemberID="viewController">
|
||||
<view key="view" id="vpb-p4-eTc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="446" height="400"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<box borderType="line" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="M4u-TD-b2T">
|
||||
<rect key="frame" x="-1" y="2" width="441" height="393"/>
|
||||
<view key="contentView" id="oYb-2L-ees">
|
||||
<rect key="frame" x="1" y="1" width="439" height="391"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="som-5e-Wbh">
|
||||
<rect key="frame" x="18" y="283" width="4" height="98"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="98" id="e1d-k2-uff"/>
|
||||
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="400" id="f70-My-t5t"/>
|
||||
</constraints>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" id="J2k-OR-LDz">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="wCT-Vy-hJX">
|
||||
<rect key="frame" x="20" y="15" width="399" height="265"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="wCT-Vy-hJX" secondAttribute="trailing" constant="20" symbolic="YES" id="2wX-0j-ONC"/>
|
||||
<constraint firstItem="wCT-Vy-hJX" firstAttribute="leading" secondItem="oYb-2L-ees" secondAttribute="leading" constant="20" id="LVy-BU-S6G"/>
|
||||
<constraint firstAttribute="bottom" secondItem="wCT-Vy-hJX" secondAttribute="bottom" constant="15" id="QbI-JX-eIV"/>
|
||||
<constraint firstItem="som-5e-Wbh" firstAttribute="leading" secondItem="oYb-2L-ees" secondAttribute="leading" constant="20" symbolic="YES" id="YKP-eO-gjX"/>
|
||||
<constraint firstItem="wCT-Vy-hJX" firstAttribute="top" secondItem="som-5e-Wbh" secondAttribute="bottom" constant="3" id="Z8U-nl-wSZ"/>
|
||||
<constraint firstItem="som-5e-Wbh" firstAttribute="top" secondItem="oYb-2L-ees" secondAttribute="top" constant="10" id="dOe-NP-uCa"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="435" id="O7a-OR-EV5"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="387" id="ZaJ-h7-R3E"/>
|
||||
</constraints>
|
||||
</box>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="M4u-TD-b2T" secondAttribute="trailing" constant="9" id="8cG-KL-S7A"/>
|
||||
<constraint firstItem="M4u-TD-b2T" firstAttribute="top" secondItem="vpb-p4-eTc" secondAttribute="top" constant="7" id="T5Q-Aj-xKs"/>
|
||||
<constraint firstAttribute="bottom" secondItem="M4u-TD-b2T" secondAttribute="bottom" constant="6" id="Vad-EE-WcC"/>
|
||||
<constraint firstItem="M4u-TD-b2T" firstAttribute="leading" secondItem="vpb-p4-eTc" secondAttribute="leading" constant="2" id="pe9-nS-CuG"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="descriptionField" destination="som-5e-Wbh" id="fe5-zJ-2mb"/>
|
||||
<outlet property="exampleArea" destination="wCT-Vy-hJX" id="KKF-iA-79K"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<customObject id="bMB-1L-3Vi" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="662" y="685.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13122.17" systemVersion="17A263s" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13122.17"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ProtectedTextViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ProtectedTextViewController" id="BJj-AK-Or5" userLabel="ProtectedTextViewController" customClass="ProtectedTextViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="283" height="119"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zhi-Zi-QHt">
|
||||
<rect key="frame" x="-2" y="-2" width="119" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Protect Content" bezelStyle="regularSquare" imagePosition="left" inset="2" id="lby-6W-6Je">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="protectionAction:" target="BJj-AK-Or5" id="gdz-8S-QWw"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1Kz-GD-jIV">
|
||||
<rect key="frame" x="0.0" y="22" width="283" height="97"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." drawsBackground="YES" id="QgF-sy-XQv">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="contentView" destination="1Kz-GD-jIV" id="NI6-zz-5oE"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="578.5" y="1073.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13168.2" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13168.2"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--TextAttributesViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="TextAttributesViewController" id="BJj-AK-Or5" userLabel="TextAttributesViewController" customClass="TextAttributesViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="412" height="206"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<scrollView fixedFrame="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dn7-1Z-Wt1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="307" height="206"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" ambiguous="YES" id="tWg-0h-8tp">
|
||||
<rect key="frame" x="1" y="1" width="305" height="204"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView ambiguous="YES" importsGraphics="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="PhU-6A-UM3" customClass="TextAttributesTextView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="305" height="204"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<size key="minSize" width="305" height="204"/>
|
||||
<size key="maxSize" width="6604" height="10000000"/>
|
||||
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="553-tZ-D6R">
|
||||
<rect key="frame" x="-100" y="-100" width="87" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="FsM-rS-dCH">
|
||||
<rect key="frame" x="290" y="1" width="16" height="204"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8fr-9t-FHp" customClass="LinesView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="412" height="206"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ABs-hg-Elf">
|
||||
<rect key="frame" x="312" y="172" width="88" height="14"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" controlSize="small" sendsActionOnEndEditing="YES" title="Eggplant again?" id="4tj-rC-TCJ">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RCg-os-xxJ">
|
||||
<rect key="frame" x="306" y="7" width="102" height="28"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Buy Apple Pie" bezelStyle="rounded" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="vx1-ma-aiF">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="buyApplePie:" target="BJj-AK-Or5" id="v1Z-QT-A14"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Y6v-g7-O0i">
|
||||
<rect key="frame" x="313" y="115" width="92" height="28"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" controlSize="small" sendsActionOnEndEditing="YES" title="I'll pick some up after work!" id="5qT-3b-Ouf">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="attributedTextView" destination="PhU-6A-UM3" id="eLD-XX-m8y"/>
|
||||
<outlet property="broccoliAnnotation" destination="Y6v-g7-O0i" id="J9F-No-ber"/>
|
||||
<outlet property="buyButton" destination="RCg-os-xxJ" id="FHn-RG-n97"/>
|
||||
<outlet property="eggPlantAnnotation" destination="ABs-hg-Elf" id="LZt-hy-RVp"/>
|
||||
<outlet property="linesView" destination="8fr-9t-FHp" id="i1c-98-7Pj"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="682" y="965"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13122.13" systemVersion="17A274" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13122.13"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ThreePositionSwitchViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ThreePositionSwitchViewController" id="BJj-AK-Or5" userLabel="ThreePositionSwitchViewController" customClass="ThreePositionSwitchViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="133" height="86"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="zwu-DI-0wO" customClass="ThreePositionSwitchView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="133" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="133" id="0a5-a7-zbf"/>
|
||||
<constraint firstAttribute="height" constant="31" id="91A-Iw-xae"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<action selector="changeSwitchValue:" target="BJj-AK-Or5" id="joF-sG-TJm"/>
|
||||
</connections>
|
||||
</customView>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="yA7-zr-odT">
|
||||
<rect key="frame" x="56" y="32" width="22" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="On" id="MAm-ag-eia">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PAd-BZ-yib">
|
||||
<rect key="frame" x="-2" y="32" width="24" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Off" id="yxh-ws-njA">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cwv-DU-mpu">
|
||||
<rect key="frame" x="102" y="32" width="33" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Auto" id="eju-Nb-xkK">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="n8v-Gd-Mdi">
|
||||
<rect key="frame" x="27" y="57" width="79" height="29"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="OFF" id="h3U-C7-ctb">
|
||||
<font key="font" metaFont="systemBold" size="24"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="zwu-DI-0wO" firstAttribute="leading" secondItem="ugI-Pl-CNw" secondAttribute="leading" id="0OO-RY-SyC"/>
|
||||
<constraint firstItem="zwu-DI-0wO" firstAttribute="top" secondItem="ugI-Pl-CNw" secondAttribute="top" constant="55" id="nFs-AD-fp9"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="currentValueLabel" destination="n8v-Gd-Mdi" id="RXe-n5-uhC"/>
|
||||
<outlet property="threePositionSwitch" destination="zwu-DI-0wO" id="RCY-zU-Y1J"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="503.5" y="1057"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13122.13" systemVersion="17A274" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13122.13"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--TransientUIViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="TransientUIViewController" id="BJj-AK-Or5" userLabel="TransientUIViewController" customClass="TransientUIViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<customView key="view" id="dwZ-oK-hjx">
|
||||
<rect key="frame" x="0.0" y="0.0" width="203" height="74"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<view translatesAutoresizingMaskIntoConstraints="NO" id="pbi-oj-x7p" userLabel="TransientUITriggerView" customClass="TransientUITriggerView" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="6" width="203" height="68"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3H4-1p-CN6">
|
||||
<rect key="frame" x="36" y="47" width="131" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="This is page %i of %i" id="Uqv-6b-7dV">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LD7-WV-jmG" userLabel="Transient View">
|
||||
<rect key="frame" x="5" y="6" width="192" height="31"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="WdK-Wx-J7K">
|
||||
<rect key="frame" x="95" y="-2" width="93" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Next" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="lz8-1u-BjV">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="pressNextPageButton:" target="BJj-AK-Or5" id="xFx-cI-D7w"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7FG-4x-aOg">
|
||||
<rect key="frame" x="4" y="-2" width="93" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Previous" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="SDa-Uq-1m5">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="pressPreviousPageButton:" target="BJj-AK-Or5" id="Rg5-fN-Hh6"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</customView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="203" id="PS1-hv-Zjs"/>
|
||||
<constraint firstAttribute="height" constant="68" id="oU4-XN-kAt"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="transientView" destination="LD7-WV-jmG" id="Quk-uc-9yl"/>
|
||||
</connections>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="pbi-oj-x7p" firstAttribute="top" secondItem="dwZ-oK-hjx" secondAttribute="top" id="SyC-Bj-AaU"/>
|
||||
<constraint firstItem="pbi-oj-x7p" firstAttribute="leading" secondItem="dwZ-oK-hjx" secondAttribute="leading" id="U3D-Fr-rBj"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
<connections>
|
||||
<outlet property="nextPageButton" destination="WdK-Wx-J7K" id="cLz-Bb-4QE"/>
|
||||
<outlet property="pageTextField" destination="3H4-1p-CN6" id="Qq3-ls-COc"/>
|
||||
<outlet property="previousPageButton" destination="7FG-4x-aOg" id="wQ4-Zw-zFE"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="409.5" y="930"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--TwoPositionSwitchViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="TwoPositionSwitchViewController" id="BJj-AK-Or5" userLabel="TwoPositionSwitchViewController" customClass="TwoPositionSwitchViewController" customModule="AccessibilityUIExamples" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" id="ugI-Pl-CNw">
|
||||
<rect key="frame" x="0.0" y="0.0" width="187" height="30"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="OMH-67-oTP">
|
||||
<rect key="frame" x="28" y="0.0" width="133" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="31" id="GZY-QK-bt8"/>
|
||||
<constraint firstAttribute="width" constant="133" id="xek-DQ-L1O"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
<textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AT4-bZ-0e2">
|
||||
<rect key="frame" x="167" y="7" width="22" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="On" id="blX-l5-vNz">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mgP-9C-XFw">
|
||||
<rect key="frame" x="-2" y="7" width="24" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Off" id="RVY-OU-sDj">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="OMH-67-oTP" firstAttribute="top" secondItem="ugI-Pl-CNw" secondAttribute="top" constant="-1" id="Oxe-2l-tef"/>
|
||||
<constraint firstItem="OMH-67-oTP" firstAttribute="centerY" secondItem="AT4-bZ-0e2" secondAttribute="centerY" id="ag5-Ym-FO2"/>
|
||||
<constraint firstItem="AT4-bZ-0e2" firstAttribute="leading" secondItem="OMH-67-oTP" secondAttribute="trailing" constant="8" symbolic="YES" id="e4v-8c-CPi"/>
|
||||
<constraint firstItem="OMH-67-oTP" firstAttribute="leading" secondItem="ugI-Pl-CNw" secondAttribute="leading" constant="28" id="ebE-Zd-tSF"/>
|
||||
<constraint firstItem="OMH-67-oTP" firstAttribute="leading" secondItem="mgP-9C-XFw" secondAttribute="trailing" constant="8" symbolic="YES" id="oyK-7l-RqI"/>
|
||||
<constraint firstItem="OMH-67-oTP" firstAttribute="centerY" secondItem="mgP-9C-XFw" secondAttribute="centerY" id="p2T-2N-Wig"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="placeHolderView" destination="OMH-67-oTP" id="7Yl-VO-Hih"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="530.5" y="1029"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13122.13" systemVersion="17A274" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13122.13"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--ViewImageSubclassViewController-->
|
||||
<scene sceneID="lsD-jq-9yG">
|
||||
<objects>
|
||||
<customObject id="SOC-OX-ybn" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
<viewController storyboardIdentifier="ViewImageSubclassViewController" id="BJj-AK-Or5" userLabel="ViewImageSubclassViewController" sceneMemberID="viewController">
|
||||
<view key="view" id="E1o-Sh-RqV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="75" height="75"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nIg-Jd-t3A" customClass="ViewImageSubclass" customModule="AccessibilityUIExamples" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="75" height="75"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
</viewController>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="286.5" y="938.5"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Base view controller for views with a single button and a "Press Count" text field.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ButtonBaseViewController: NSViewController {
|
||||
|
||||
var pressCount = 0
|
||||
|
||||
@IBOutlet var pressCountTextField: NSTextField!
|
||||
@IBOutlet var button: NSView!
|
||||
|
||||
// MARK: - View Controller Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
updatePressCountTextField()
|
||||
}
|
||||
|
||||
fileprivate func updatePressCountTextField () {
|
||||
let formatter = NSLocalizedString("PressCountFormatter", comment: "Press count formatter")
|
||||
let numberString = NumberFormatter.localizedString(from: NSNumber(value: pressCount), number: NumberFormatter.Style.none)
|
||||
pressCountTextField.stringValue = String(format: formatter, numberString)
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction func pressButton(_ sender: Any) {
|
||||
pressCount += 1
|
||||
updatePressCountTextField()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Constants for acessing button images.
|
||||
*/
|
||||
|
||||
struct ButtonImages {
|
||||
static let buttonUp = "CustomButtonUp"
|
||||
static let buttonDown = "CustomButtonDown"
|
||||
static let buttonHighlight = "CustomButtonHighlight"
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
View controller demonstrating an accessible, custom NSButton subclass.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ButtonSubclassViewController: ButtonBaseViewController {
|
||||
|
||||
// MARK: - View Controller Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
button.setAccessibilityLabel(NSLocalizedString("My label", comment: "label to use for this button"))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
View controller demonstrating accessibility provided by AppKit for NSButton.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ButtonViewController: ButtonBaseViewController {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
View controller demonstrating an accessible, custom NSView subclass that behaves like a button.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ButtonViewSubclassViewController: ButtonBaseViewController {
|
||||
|
||||
// MARK: - View Controller Lifecycle
|
||||
|
||||
@IBOutlet var customButton: CustomButtonView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Allow the CustomButtonView to call our own action function.
|
||||
customButton.actionHandler = { self.pressButton(self) }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
View controller demonstrating accessibility provided by AppKit for an NSButton with an image.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ButtonWithImageViewController: ButtonBaseViewController {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating the preferred method of making an accessible,
|
||||
custom button by subclassing NSButton and implementing the NSAccessibilityButton protocol.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
// Note that NSButton already conforms to protocol "NSAccessibilityButton".
|
||||
class CustomButton: NSButton {
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
fileprivate func commonInit() {
|
||||
image = NSImage(named: NSImage.Name(rawValue: ButtonImages.buttonUp))
|
||||
alternateImage = NSImage(named: NSImage.Name(rawValue: ButtonImages.buttonDown))
|
||||
|
||||
// Track the mouse for enter and exit for proper highlighting.
|
||||
let trackingArea = NSTrackingArea(rect: bounds,
|
||||
options: [NSTrackingArea.Options.activeAlways, NSTrackingArea.Options.mouseEnteredAndExited],
|
||||
owner: self,
|
||||
userInfo: nil)
|
||||
addTrackingArea(trackingArea)
|
||||
}
|
||||
|
||||
// MARK: - Mouse events
|
||||
|
||||
override func mouseEntered(with event: NSEvent) {
|
||||
super.mouseEntered(with: event)
|
||||
image = NSImage(named: NSImage.Name(rawValue: ButtonImages.buttonHighlight))
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
super.mouseExited(with: event)
|
||||
image = NSImage(named: NSImage.Name(rawValue: ButtonImages.buttonUp))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - NSAccessibilityButton
|
||||
|
||||
extension CustomButton {
|
||||
|
||||
/// - Tag: accessibilityLabel
|
||||
override func accessibilityLabel() -> String? {
|
||||
return NSLocalizedString("Play", comment: "accessibility label of the Play button")
|
||||
}
|
||||
|
||||
override func accessibilityHelp() -> String {
|
||||
return NSLocalizedString("Increase press count.", comment: "accessibility help of the Play button")
|
||||
}
|
||||
|
||||
// MARK: NSAccessibility
|
||||
|
||||
override func accessibilityPerformPress() -> Bool {
|
||||
// User did control-option-space keyboard shortcut.
|
||||
performClick(nil)
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating adding accessibility to an NSView subclass that behaves like a button by implementing the NSAccessibilityButton protocol.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
/*
|
||||
IMPORTANT: This is not a template for developing a custom control.
|
||||
This sample is intended to demonstrate how to add accessibility to
|
||||
existing custom controls that are not implemented using the preferred methods.
|
||||
For information on how to create custom controls please visit http://developer.apple.com
|
||||
*/
|
||||
|
||||
// Note that CustomButtonView is an NSView subclass and needs to adopt "NSAccessibilityButton" or in this case implement the required functions.
|
||||
/// - Tag: customButtonDeclare
|
||||
class CustomButtonView: NSView {
|
||||
|
||||
// MARK: - Internals
|
||||
|
||||
private var pressed = false
|
||||
private var highlighted = false
|
||||
private var depressed = false
|
||||
|
||||
var actionHandler: (() -> Void)?
|
||||
|
||||
// Set to allow keyDown to be called.
|
||||
override var acceptsFirstResponder: Bool { return true }
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
fileprivate func commonInit() {
|
||||
// Track the mouse for enter and exit for proper highlighting.
|
||||
let trackingArea = NSTrackingArea(rect: bounds,
|
||||
options: [NSTrackingArea.Options.activeAlways, NSTrackingArea.Options.mouseEnteredAndExited],
|
||||
owner: self,
|
||||
userInfo: nil)
|
||||
addTrackingArea(trackingArea)
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
fileprivate func pressDown() {
|
||||
pressed = true
|
||||
depressed = true
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
fileprivate func pressUpInside(inside: Bool, highlight: Bool) {
|
||||
pressed = false
|
||||
depressed = false
|
||||
highlighted = highlight ? inside : false
|
||||
needsDisplay = true
|
||||
|
||||
if inside {
|
||||
// Call our action handler (ultimately winding up in the view controller).
|
||||
if let actionHandler = actionHandler {
|
||||
actionHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func performAfterDelay(delay: Double, onCompletion: @escaping() -> Void) {
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay, execute: {
|
||||
onCompletion()
|
||||
})
|
||||
}
|
||||
|
||||
fileprivate func performPress () {
|
||||
// Set down and release after momentary delay so the button flickers.
|
||||
pressDown()
|
||||
|
||||
let delayInSeconds = 0.1
|
||||
performAfterDelay(delay: delayInSeconds) {
|
||||
self.pressUpInside(inside: true, highlight: false)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Drawing
|
||||
|
||||
override func drawFocusRingMask() {
|
||||
bounds.fill()
|
||||
}
|
||||
|
||||
override var focusRingMaskBounds: NSRect {
|
||||
return bounds
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
let upImage = NSImage(named: NSImage.Name(rawValue: ButtonImages.buttonUp))
|
||||
let downImage = NSImage(named: NSImage.Name(rawValue: ButtonImages.buttonDown))
|
||||
let highlightImage = NSImage(named: NSImage.Name(rawValue: ButtonImages.buttonHighlight))
|
||||
|
||||
var imageToDraw = upImage
|
||||
|
||||
if depressed {
|
||||
imageToDraw = downImage
|
||||
} else if highlighted {
|
||||
imageToDraw = highlightImage
|
||||
}
|
||||
|
||||
imageToDraw?.draw(in: bounds, from: NSRect.zero, operation: NSCompositingOperation.sourceOver, fraction: 1.0)
|
||||
}
|
||||
|
||||
// MARK: - Mouse events
|
||||
|
||||
override func mouseDown(with event: NSEvent) {
|
||||
super.mouseDown(with: event)
|
||||
pressDown()
|
||||
}
|
||||
|
||||
override func mouseUp(with event: NSEvent) {
|
||||
super.mouseUp(with: event)
|
||||
|
||||
let localPoint = convert(event.locationInWindow, from:nil)
|
||||
let isInside = bounds.contains(localPoint)
|
||||
pressUpInside(inside: isInside, highlight: true)
|
||||
}
|
||||
|
||||
override func mouseEntered(with event: NSEvent) {
|
||||
super.mouseEntered(with: event)
|
||||
|
||||
highlighted = true
|
||||
depressed = pressed // Restore pressed state, possibly set before mouseExited.
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
super.mouseExited(with: event)
|
||||
|
||||
highlighted = pressed
|
||||
depressed = false
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
// MARK: - Keyboard Events
|
||||
|
||||
override func keyDown(with event: NSEvent) {
|
||||
guard let charactersIgnoringModifiers = event.charactersIgnoringModifiers, charactersIgnoringModifiers.characters.count == 1,
|
||||
let char = charactersIgnoringModifiers.characters.first
|
||||
else {
|
||||
super.keyDown(with: event)
|
||||
return
|
||||
}
|
||||
if char == " " {
|
||||
performPress()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Accessibility
|
||||
|
||||
extension CustomButtonView {
|
||||
|
||||
override func accessibilityLabel() -> String? {
|
||||
return NSLocalizedString("Play", comment: "accessibility label of the Play button")
|
||||
}
|
||||
|
||||
override func accessibilityHelp() -> String {
|
||||
return NSLocalizedString("Increase press count.", comment: "accessibility help of the Play button")
|
||||
}
|
||||
|
||||
override func accessibilityPerformPress() -> Bool {
|
||||
// User did control-option-space keyboard shortcut.
|
||||
performPress()
|
||||
return true
|
||||
}
|
||||
|
||||
/// - Tag: customButtonAdoption
|
||||
override func accessibilityRole() -> NSAccessibilityRole? {
|
||||
return NSAccessibilityRole.button
|
||||
}
|
||||
|
||||
override func isAccessibilityElement() -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Category for adoption on NSAccessibilityCheckBox.
|
||||
*/
|
||||
|
||||
#import "AccessibilityUIExamples-Swift.h"
|
||||
|
||||
@interface CustomCheckBoxView (Accessibility) <NSAccessibilityCheckBox>
|
||||
@end
|
||||
|
||||
@implementation CustomCheckBoxView (Accessibility)
|
||||
@end
|
||||
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
See LICENSE folder 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 Cocoa
|
||||
|
||||
/*
|
||||
IMPORTANT: This is not a template for developing a custom control.
|
||||
This sample is intended to demonstrate how to add accessibility to
|
||||
existing custom controls that are not implemented using the preferred methods.
|
||||
For information on how to create custom controls please visit http://developer.apple.com
|
||||
*/
|
||||
|
||||
class CustomCheckBoxView: NSView {
|
||||
|
||||
// MARK: - Internals
|
||||
|
||||
fileprivate struct LayoutInfo {
|
||||
static let CheckboxWidth = CGFloat(12.0)
|
||||
static let CheckboxHeight = CheckboxWidth
|
||||
static let CheckboxTextSpacing = CGFloat(4.0) // Spacing between box and text.
|
||||
}
|
||||
|
||||
var checkboxText = NSLocalizedString("Hello World", comment: "text of checkbox")
|
||||
|
||||
var checked: Bool = true {
|
||||
didSet {
|
||||
if let actionHandler = actionHandler {
|
||||
actionHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
|
||||
override open func viewDidMoveToWindow() {
|
||||
super.viewDidMoveToWindow()
|
||||
checked = true // So our actionHandler is called when first added to the window.
|
||||
}
|
||||
|
||||
// MARK: - Events
|
||||
|
||||
var actionHandler: (() -> Void)?
|
||||
|
||||
// MARK: - Mouse Events
|
||||
|
||||
fileprivate func toggleCheckedState () {
|
||||
checked = !checked
|
||||
NSAccessibilityPostNotification(self, NSAccessibilityNotificationName.valueChanged)
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
override func mouseUp(with event: NSEvent) {
|
||||
toggleCheckedState()
|
||||
}
|
||||
|
||||
// MARK: - Key Event
|
||||
|
||||
override func keyDown(with event: NSEvent) {
|
||||
if event.keyCode == 49 {
|
||||
// Space character was types.
|
||||
toggleCheckedState()
|
||||
} else {
|
||||
super.keyDown(with: event)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Drawing
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
// Draw the checkbox box.
|
||||
var boxImage: NSImage
|
||||
let imageName = checked ? "CustomCheckboxSelected" : "CustomCheckboxUnselected"
|
||||
boxImage = NSImage(named: NSImage.Name(rawValue: imageName))!
|
||||
let boxRect = NSRect(x: bounds.origin.x,
|
||||
y: bounds.origin.y + 1,
|
||||
width: LayoutInfo.CheckboxWidth,
|
||||
height: LayoutInfo.CheckboxHeight)
|
||||
boxImage.draw(in: boxRect, from: NSRect.zero, operation: NSCompositingOperation.sourceOver, fraction: 1.0)
|
||||
|
||||
// Draw the checkbox text.
|
||||
let textAttributes = [
|
||||
NSAttributedStringKey.font: NSFont.systemFont(ofSize: NSFont.systemFontSize),
|
||||
NSAttributedStringKey.foregroundColor: NSColor.black
|
||||
]
|
||||
let textRect = NSRect(x: bounds.origin.x + LayoutInfo.CheckboxWidth + LayoutInfo.CheckboxTextSpacing,
|
||||
y: bounds.origin.y,
|
||||
width: bounds.size.width,
|
||||
height: bounds.size.height)
|
||||
checkboxText.draw(in: textRect, withAttributes: textAttributes)
|
||||
|
||||
// Draw the focus ring.
|
||||
NSFocusRingPlacement.only.set()
|
||||
let ovalPath = NSBezierPath(rect: boxRect)
|
||||
ovalPath.fill()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension CustomCheckBoxView {
|
||||
|
||||
// MARK: First Responder
|
||||
|
||||
// Set to allow keyDown to be called.
|
||||
override var acceptsFirstResponder: Bool { return true }
|
||||
|
||||
override func becomeFirstResponder() -> Bool {
|
||||
let didBecomeFirstResponder = super.becomeFirstResponder()
|
||||
needsDisplay = true
|
||||
return didBecomeFirstResponder
|
||||
}
|
||||
|
||||
override func resignFirstResponder() -> Bool {
|
||||
let didResignFirstResponder = super.resignFirstResponder()
|
||||
needsDisplay = true
|
||||
return didResignFirstResponder
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension CustomCheckBoxView {
|
||||
|
||||
// MARK: Accessibility
|
||||
|
||||
override func accessibilityValue() -> Any? {
|
||||
return checked
|
||||
}
|
||||
|
||||
override func accessibilityLabel() -> String? {
|
||||
return checkboxText
|
||||
}
|
||||
|
||||
override func accessibilityPerformPress() -> Bool {
|
||||
// User did control-option-space keyboard shortcut.
|
||||
toggleCheckedState()
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
View controller demonstrating accessibility provided by AppKit for NSButton.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class CustomCheckBoxViewController: NSViewController {
|
||||
|
||||
// MARK: - View Controller Lifecycle
|
||||
@IBOutlet var currentValueLabel: NSTextField!
|
||||
@IBOutlet var customCheckbox: CustomCheckBoxView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Allow the CustomCheckBoxView to call our own action function.
|
||||
customCheckbox.actionHandler = { self.changeCheckBoxValue(self) }
|
||||
}
|
||||
|
||||
func changeCheckBoxValue(_ sender: Any) {
|
||||
currentValueLabel.stringValue = NSString(format: "(State = %@)", customCheckbox.checked ? "checked" : "unchecked") as String
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating setup of an accessibility rotor to search for fruit buttons.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
class CustomRotorsContainerView: NSView {
|
||||
|
||||
weak var delegate: CustomRotorsElementViewDelegate?
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
|
||||
// MARK: - Drawing
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
// Draw the outline background.
|
||||
NSColor.lightGray.set()
|
||||
bounds.fill()
|
||||
}
|
||||
|
||||
// MARK: - Accessibility
|
||||
|
||||
override func isAccessibilityElement() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override func accessibilityRole() -> NSAccessibilityRole? {
|
||||
return NSAccessibilityRole.group
|
||||
}
|
||||
|
||||
override func accessibilityLabel() -> String? {
|
||||
return NSLocalizedString("Fruit to Color", comment: "")
|
||||
}
|
||||
|
||||
override func accessibilityCustomRotors() -> [NSAccessibilityCustomRotor] {
|
||||
return delegate!.createCustomRotors()
|
||||
}
|
||||
}
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
protocol CustomRotorsElementViewDelegate : class {
|
||||
func createCustomRotors() -> [NSAccessibilityCustomRotor]
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An item result with a given item loader and custom label.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class CustomRotorsElementLoadingToken: NSObject, NSCoding, NSSecureCoding {
|
||||
var uniqueIdentifier = ""
|
||||
|
||||
init(identifier: String) {
|
||||
uniqueIdentifier = identifier
|
||||
}
|
||||
|
||||
static var supportsSecureCoding: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
super.init()
|
||||
|
||||
if let identifier = aDecoder.decodeObject(of: NSString.self, forKey: "uniqueIdentifier") as String? {
|
||||
uniqueIdentifier = identifier
|
||||
}
|
||||
}
|
||||
|
||||
func encode(with aCoder: NSCoder) {
|
||||
aCoder.encode(uniqueIdentifier, forKey: "uniqueIdentifier")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating setup of an accessibility rotor to search for fruit buttons.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
/*
|
||||
IMPORTANT: This is not a template for developing a custom control.
|
||||
This sample is intended to demonstrate how to add accessibility to
|
||||
existing custom controls that are not implemented using the preferred methods.
|
||||
For information on how to create custom controls please visit http://developer.apple.com
|
||||
*/
|
||||
|
||||
class CustomRotorsElementView: NSView {
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
fileprivate func commonInit() {
|
||||
//•• needed?
|
||||
}
|
||||
|
||||
// MARK: - Accessibility
|
||||
|
||||
override func isAccessibilityElement() -> Bool {
|
||||
NSLog("CustomRotorsElementView: accessibilityLabel")
|
||||
return true
|
||||
}
|
||||
|
||||
override func accessibilityRole() -> String? {
|
||||
NSLog("CustomRotorsElementView: accessibilityRole")
|
||||
return NSAccessibilityGroupRole
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating setup of an accessibility rotor to search for fruit buttons.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
// Note: To test UIAccessibilityCustomRotor, focus on the CustomRotorsContainerView, and type control+option+u
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
class CustomRotorsElementViewController: NSViewController,
|
||||
NSAccessibilityCustomRotorItemSearchDelegate,
|
||||
NSAccessibilityElementLoading,
|
||||
CustomRotorsElementViewDelegate {
|
||||
|
||||
static let SearchableItemsID = "searchable"
|
||||
static let CustomRotorFruitButtonsName = "Fruit Buttons"
|
||||
static let MaxPageIndex = 2
|
||||
|
||||
var displayPageIndex = 0
|
||||
|
||||
@IBOutlet var containerView: CustomRotorsContainerView!
|
||||
@IBOutlet var pageView1: CustomRotorsPageView!
|
||||
@IBOutlet var pageView2: CustomRotorsPageView!
|
||||
@IBOutlet var pageView3: CustomRotorsPageView!
|
||||
@IBOutlet var contentView1: NSView!
|
||||
@IBOutlet var contentView2: NSView!
|
||||
@IBOutlet var contentView3: NSView!
|
||||
|
||||
// MARK: - View Controller Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
displayPageIndex = 0
|
||||
containerView.delegate = self
|
||||
pageView1.contentView = contentView1
|
||||
pageView2.contentView = contentView2
|
||||
pageView3.contentView = contentView3
|
||||
|
||||
pageView1.addSubview(pageView1.contentView)
|
||||
pageView2.addSubview(pageView2.contentView)
|
||||
pageView3.addSubview(pageView3.contentView)
|
||||
|
||||
pageView2.contentView.isHidden = true
|
||||
pageView3.contentView.isHidden = true
|
||||
|
||||
pageView1.setAccessibilityLabel(NSLocalizedString("Page 1", comment: ""))
|
||||
pageView2.setAccessibilityLabel(NSLocalizedString("Page 2", comment: ""))
|
||||
pageView3.setAccessibilityLabel(NSLocalizedString("Page 3", comment: ""))
|
||||
}
|
||||
|
||||
// Given a fruit name, display the page containing that fruit onscreen and return the button corresponding to that fruit.
|
||||
func showFruit(fruit: String) -> NSAccessibilityElementProtocol {
|
||||
|
||||
var fruitButtonAccessibilityElement: NSAccessibilityElementProtocol?
|
||||
|
||||
for pageView in containerView.subviews {
|
||||
if let pageCheck = pageView as? CustomRotorsPageView {
|
||||
for subView in pageCheck.contentView.subviews where subView is NSButton {
|
||||
if let button = subView as? NSButton {
|
||||
if button.cell?.title == fruit {
|
||||
fruitButtonAccessibilityElement = NSAccessibilityUnignoredDescendant(button) as? NSAccessibilityElementProtocol
|
||||
displayPageIndex = pageIndexForPageView(pageView: pageCheck)
|
||||
updateViews()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fruitButtonAccessibilityElement!
|
||||
}
|
||||
|
||||
// MARK: Page Management
|
||||
|
||||
fileprivate func pageIndexForPageView(pageView: CustomRotorsPageView) -> Int {
|
||||
var pageIndex = 0
|
||||
if pageView == pageView3 {
|
||||
pageIndex = 2
|
||||
} else if pageView == pageView2 {
|
||||
pageIndex = 1
|
||||
}
|
||||
return pageIndex
|
||||
}
|
||||
|
||||
fileprivate func pageViewforPageIndex(pageIndex: Int) -> CustomRotorsPageView {
|
||||
var pageView: CustomRotorsPageView?
|
||||
switch pageIndex {
|
||||
case 0:
|
||||
pageView = pageView1
|
||||
case 1:
|
||||
pageView = pageView2
|
||||
case 2:
|
||||
pageView = pageView3
|
||||
default: break
|
||||
}
|
||||
return pageView!
|
||||
}
|
||||
|
||||
fileprivate func updateViews() {
|
||||
let currentFocusedViewIndex = displayPageIndex
|
||||
for i in 0...CustomRotorsElementViewController.MaxPageIndex {
|
||||
let pageView = pageViewforPageIndex(pageIndex: i)
|
||||
if i == currentFocusedViewIndex {
|
||||
pageView.contentView.isHidden = false
|
||||
} else {
|
||||
pageView.contentView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction func nextPage(_ sender: Any) {
|
||||
if displayPageIndex < CustomRotorsElementViewController.MaxPageIndex {
|
||||
displayPageIndex += 1
|
||||
}
|
||||
updateViews()
|
||||
}
|
||||
|
||||
@IBAction func previousPage(_ sender: Any) {
|
||||
if displayPageIndex > 0 {
|
||||
displayPageIndex -= 1
|
||||
}
|
||||
updateViews()
|
||||
}
|
||||
|
||||
var fruitElements: [NSButton] {
|
||||
var fruitList = [NSButton]()
|
||||
for pageView in containerView.subviews {
|
||||
if let pageCheck = pageView as? CustomRotorsPageView {
|
||||
for subView in pageCheck.contentView.subviews where subView is NSButton {
|
||||
if let button = subView as? NSButton {
|
||||
fruitList.append(button)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fruitList
|
||||
}
|
||||
|
||||
// MARK: - NSAccessibilityElementLoading Token
|
||||
|
||||
func accessibilityElement(withToken token: NSAccessibilityLoadingToken) -> NSAccessibilityElementProtocol? {
|
||||
let fruitToken = token as! CustomRotorsElementLoadingToken
|
||||
let fruitName = fruitToken.uniqueIdentifier
|
||||
return showFruit(fruit: fruitName)
|
||||
}
|
||||
|
||||
// MARK: - CustomRotorsElementViewDelegate
|
||||
|
||||
func createCustomRotors() -> [NSAccessibilityCustomRotor] {
|
||||
// Create the fruit rotor.
|
||||
let buttonRotor =
|
||||
NSAccessibilityCustomRotor(label: CustomRotorsElementViewController.CustomRotorFruitButtonsName,
|
||||
itemSearchDelegate: self as NSAccessibilityCustomRotorItemSearchDelegate)
|
||||
buttonRotor.itemLoadingDelegate = self
|
||||
return [buttonRotor]
|
||||
}
|
||||
|
||||
// MARK: - NSAccessibilityCustomRotorItemSearchDelegate
|
||||
|
||||
public func rotor(_ rotor: NSAccessibilityCustomRotor,
|
||||
resultFor searchParameters: NSAccessibilityCustomRotor.SearchParameters) -> NSAccessibilityCustomRotor.ItemResult? {
|
||||
var searchResult: NSAccessibilityCustomRotor.ItemResult?
|
||||
|
||||
let currentItemResult = searchParameters.currentItem
|
||||
let direction = searchParameters.searchDirection
|
||||
let filterText = searchParameters.filterString
|
||||
let currentItem = currentItemResult?.targetElement
|
||||
|
||||
let children = NSAccessibilityUnignoredChildren(fruitElements)
|
||||
_ = children.filter {
|
||||
if let obj = $0 as? NSButtonCell {
|
||||
return filterText.isEmpty || // Filter based on filter string
|
||||
(obj.accessibilityTitle()?.localizedCaseInsensitiveContains(filterText))!
|
||||
} else if let obj = $0 as? NSTextFieldCell {
|
||||
return filterText.isEmpty || // Filter based on filter string
|
||||
(obj.accessibilityTitle()?.localizedCaseInsensitiveContains(filterText))!
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var currentElementIndex = NSNotFound
|
||||
var targetElement : Any?
|
||||
let loadingToken = currentItemResult?.itemLoadingToken
|
||||
if currentItem == nil && loadingToken != nil {
|
||||
// Find out the corresponding hidden button of the current search position, in order to find the next/previous button.
|
||||
let elementLoadingToken = loadingToken as? CustomRotorsElementLoadingToken
|
||||
if let currentItemIdentifier = elementLoadingToken?.uniqueIdentifier {
|
||||
for case let child as NSButtonCell in children where child.title == currentItemIdentifier {
|
||||
currentElementIndex = (children as NSArray).index(of: child)
|
||||
}
|
||||
}
|
||||
} else if currentItem != nil {
|
||||
currentElementIndex = (children as NSArray).index(of: currentItem!)
|
||||
}
|
||||
|
||||
if currentElementIndex == NSNotFound {
|
||||
// Fetch the first element.
|
||||
if direction == NSAccessibilityCustomRotor.SearchDirection.next {
|
||||
targetElement = children.first
|
||||
}
|
||||
// Fetch the last element.
|
||||
else if direction == NSAccessibilityCustomRotor.SearchDirection.previous {
|
||||
targetElement = children.last
|
||||
}
|
||||
} else {
|
||||
if direction ==
|
||||
NSAccessibilityCustomRotor.SearchDirection.previous && currentElementIndex != 0 {
|
||||
targetElement = children[currentElementIndex - 1]
|
||||
} else if direction ==
|
||||
NSAccessibilityCustomRotor.SearchDirection.next && currentElementIndex < (children.count - 1) {
|
||||
targetElement = children[currentElementIndex + 1]
|
||||
}
|
||||
}
|
||||
|
||||
if targetElement != nil {
|
||||
if let targetButtonCell = targetElement as? NSCell {
|
||||
if let controlView = targetButtonCell.controlView as? NSControl {
|
||||
if controlView.isHiddenOrHasHiddenAncestor {
|
||||
let label = targetButtonCell.title
|
||||
let token = CustomRotorsElementLoadingToken(identifier: label)
|
||||
searchResult =
|
||||
NSAccessibilityCustomRotor.ItemResult(itemLoadingToken: token as NSAccessibilityLoadingToken, customLabel: label)
|
||||
} else {
|
||||
searchResult = NSAccessibilityCustomRotor.ItemResult(targetElement: targetElement as! NSAccessibilityElementProtocol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return searchResult
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating setup of an accessibility rotor to search for fruit buttons..
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
class CustomRotorsPageView: NSView {
|
||||
|
||||
var contentView = NSView()
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
|
||||
// MARK: - Drawing
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
// Draw the outline background.
|
||||
NSColor.yellow.set()
|
||||
bounds.fill()
|
||||
}
|
||||
|
||||
// MAR: - Accessibility
|
||||
|
||||
override func isAccessibilityElement() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override func accessibilityRole() -> NSAccessibilityRole? {
|
||||
return NSAccessibilityRole.pageRole
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating setup of accessibility rotors to search for various text attributes on an text view.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
class CustomRotorsTextView: NSTextView {
|
||||
|
||||
weak var rotorDelegate: CustomRotorsTextViewDelegate?
|
||||
|
||||
// MARK: Accessibility
|
||||
|
||||
override func accessibilityCustomRotors() -> [NSAccessibilityCustomRotor] {
|
||||
return rotorDelegate?.createCustomRotors() ?? []
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
protocol CustomRotorsTextViewDelegate : class {
|
||||
func createCustomRotors() -> [NSAccessibilityCustomRotor]
|
||||
}
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating setup of accessibility rotors to search for various text attributes on an text view.
|
||||
*/
|
||||
|
||||
// To test this feature:
|
||||
// 1) Change voice over focus to the text view.
|
||||
// 2) Type cmd-option-u
|
||||
// 3) Refer to the rotor that contains: Misspellings, Vocabulary and Alice's Thoughts
|
||||
// 4) You can left arrow or right arrow to navigate between these rotors.
|
||||
|
||||
import Cocoa
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
class CustomRotorsTextViewController: NSViewController,
|
||||
CustomRotorsTextViewDelegate,
|
||||
NSAccessibilityCustomRotorItemSearchDelegate {
|
||||
|
||||
// Rotor titles.
|
||||
let vocabularyRotorTitle = "Vocabulary"
|
||||
let highlightRotorTitle = "Alice's Thoughts"
|
||||
|
||||
let storyTitle = "Alice's Adventures In Wonderland"
|
||||
|
||||
let storySnippet = "Alice's Adventures In Wonderland\nBy Lewis Carroll\n\nAlice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversetions in it, and what is the use of a book, thought Alice without pictures or conversation?\n\nSo she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.\n\nThere was nothing so VERY remarkable in that; nor did Alice think it so VERY much out of the way to hear the Rabbit say to itself, Oh dear! Oh dear! I shall be late! (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-POCKET, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fertunately was just in time to see it pop down a large rabbit-hole under the hedge.\n\nIn another moment down went Alice after it, never once considering how in the world she was to get out again.\n\nThe rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well.\n\nEither the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her and to wonder what was going to hapen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything; then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves; here and there she saw maps and pictures hung upon pegs. She took down a jar from one of the shelves as she passed; it was labelled 'ORANGE MARMALADE', but to her great disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so managed to put it into one of the cupboards as she fell past it.\n\n'Well!' thought Alice to herself, after such a fall as this, I shall think nothing of tumbling down stairs! How brave they'll all think me at home! Why, I wouldn't say anything about it, even if I fell off the top of the house! (Which was very likely true.)\n\nDown, down, down. Would the fall NEVER come to an end! I wonder how many miles I've fallen by this time? she said aloud. I must be getting somewhere near the centre of the earth. Let me see: that would be four thousand miles down, I think— (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a VERY good opportunity for showing off her knowledge, as there was no one to lisen to her, still it was good practice to say it over) —yes, that's about the right distance—but then I wonder what Latitude or Longitude I've got to? (Alice had no idea what Latitude was, or Longitude either, but thought they were nice grand words to say.)\n\n"
|
||||
|
||||
let vocabWord1 = "pleasure"
|
||||
let vocabWord2 = "curiosity"
|
||||
let vocabWord3 = "disappointment"
|
||||
let vocabWord4 = "opportunity"
|
||||
let vocabWord5 = "knowledge"
|
||||
|
||||
let highlightedNote1 = "and what is the use of a book"
|
||||
let highlightedNote2 = "without pictures or conversation?"
|
||||
let highlightedNote3 = "Oh dear! Oh dear! I shall be late!"
|
||||
let highlightedNote4 = "after such a fall as this, I shall think nothing of tumbling down stairs! How brave they'll all think me at home! Why, I wouldn't say anything about it, even if I fell off the top of the house!"
|
||||
let highlightedNote5 = "I wonder how many miles I've fallen by this time?"
|
||||
let highlightedNote6 = "I must be getting somewhere near the centre of the earth. Let me see: that would be four thousand miles down, I think—"
|
||||
let highlightedNote7 = "—yes, that's about the right distance—but then I wonder what Latitude or Longitude I've got to?"
|
||||
|
||||
let misspelledWord1 = "conversetions" // correct version = conversations
|
||||
let misspelledWord2 = "fertunately" // correct version = fortunately
|
||||
let misspelledWord3 = "hapen" // correct version = happen
|
||||
let misspelledWord4 = "lisen" // correct version = listen
|
||||
|
||||
// Search for "dream" will result in - "when suddently"
|
||||
// Search for "falling into the well" will result in - "In another moment"
|
||||
//
|
||||
// User must search for either of these strings:
|
||||
let searchKeyword1 = "dream"
|
||||
let searchKeyword2 = "falling into the well"
|
||||
// The search will result these content strings:
|
||||
let contentSearchEntry1 = "when suddenly"
|
||||
let contentSearchEntry2 = "In another moment"
|
||||
|
||||
var vocabWords = [NSRange]()
|
||||
var highlightedNotes = [NSRange]()
|
||||
var misspelledWords = [NSRange]()
|
||||
|
||||
@IBOutlet var textView: CustomRotorsTextView!
|
||||
|
||||
// MARK: - View Controller Lifecycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
insertTextViewString()
|
||||
textView.rotorDelegate = self
|
||||
}
|
||||
|
||||
func buildVocabulary(textStorage: NSTextStorage) {
|
||||
let vocabWord1Range = textView.string.range(of: vocabWord1)
|
||||
let vocabWord2Range = textView.string.range(of: vocabWord2)
|
||||
let vocabWord3Range = textView.string.range(of: vocabWord3)
|
||||
let vocabWord4Range = textView.string.range(of: vocabWord4)
|
||||
let vocabWord5Range = textView.string.range(of: vocabWord5)
|
||||
|
||||
vocabWords = [ NSRange(vocabWord1Range!, in: vocabWord1),
|
||||
NSRange(vocabWord2Range!, in: vocabWord2),
|
||||
NSRange(vocabWord3Range!, in: vocabWord3),
|
||||
NSRange(vocabWord4Range!, in: vocabWord4),
|
||||
NSRange(vocabWord5Range!, in: vocabWord5) ]
|
||||
|
||||
// Apply the blue bold font vocabulary words.
|
||||
let vocabColor = NSColor.blue
|
||||
var attrRange = NSRange(vocabWord1Range!, in: misspelledWord4)
|
||||
textStorage.addAttribute(NSAttributedStringKey.foregroundColor, value: vocabColor, range: attrRange)
|
||||
textStorage.applyFontTraits(NSFontTraitMask(rawValue: NSFontTraitMask.RawValue(NSFontBoldTrait)), range: attrRange)
|
||||
|
||||
attrRange = NSRange(vocabWord2Range!, in: vocabWord2)
|
||||
textStorage.addAttribute(NSAttributedStringKey.foregroundColor, value: vocabColor, range: attrRange)
|
||||
textStorage.applyFontTraits(NSFontTraitMask(rawValue: NSFontTraitMask.RawValue(NSFontBoldTrait)), range: attrRange)
|
||||
|
||||
attrRange = NSRange(vocabWord3Range!, in: vocabWord3)
|
||||
textStorage.addAttribute(NSAttributedStringKey.foregroundColor, value: vocabColor, range: attrRange)
|
||||
textStorage.applyFontTraits(NSFontTraitMask(rawValue: NSFontTraitMask.RawValue(NSFontBoldTrait)), range: attrRange)
|
||||
|
||||
attrRange = NSRange(vocabWord4Range!, in: vocabWord4)
|
||||
textStorage.addAttribute(NSAttributedStringKey.foregroundColor, value: vocabColor, range: attrRange)
|
||||
textStorage.applyFontTraits(NSFontTraitMask(rawValue: NSFontTraitMask.RawValue(NSFontBoldTrait)), range: attrRange)
|
||||
|
||||
attrRange = NSRange(vocabWord5Range!, in: vocabWord5)
|
||||
textStorage.addAttribute(NSAttributedStringKey.foregroundColor, value: vocabColor, range: attrRange)
|
||||
textStorage.applyFontTraits(NSFontTraitMask(rawValue: NSFontTraitMask.RawValue(NSFontBoldTrait)), range: attrRange)
|
||||
}
|
||||
|
||||
func buildHighlighted(textStorage: NSTextStorage) {
|
||||
let highlightedNote1Range = textView.string.range(of: highlightedNote1)
|
||||
let highlightedNote2Range = textView.string.range(of: highlightedNote2)
|
||||
let highlightedNote3Range = textView.string.range(of: highlightedNote3)
|
||||
let highlightedNote4Range = textView.string.range(of: highlightedNote4)
|
||||
let highlightedNote5Range = textView.string.range(of: highlightedNote5)
|
||||
let highlightedNote6Range = textView.string.range(of: highlightedNote6)
|
||||
let highlightedNote7Range = textView.string.range(of: highlightedNote7)
|
||||
|
||||
highlightedNotes = [ NSRange(highlightedNote1Range!, in: highlightedNote1),
|
||||
NSRange(highlightedNote2Range!, in: highlightedNote2),
|
||||
NSRange(highlightedNote3Range!, in: highlightedNote3),
|
||||
NSRange(highlightedNote4Range!, in: highlightedNote4),
|
||||
NSRange(highlightedNote5Range!, in: highlightedNote5),
|
||||
NSRange(highlightedNote6Range!, in: highlightedNote6),
|
||||
NSRange(highlightedNote7Range!, in: highlightedNote7) ]
|
||||
|
||||
// Apply the highlighted words.
|
||||
let highlightColor = NSColor.yellow
|
||||
var attrRange = NSRange(highlightedNote1Range!, in: highlightedNote1)
|
||||
textStorage.addAttribute(NSAttributedStringKey.backgroundColor, value: highlightColor, range: attrRange)
|
||||
|
||||
attrRange = NSRange(highlightedNote2Range!, in: highlightedNote2)
|
||||
textStorage.addAttribute(NSAttributedStringKey.backgroundColor, value: highlightColor, range: attrRange)
|
||||
|
||||
attrRange = NSRange(highlightedNote3Range!, in: highlightedNote3)
|
||||
textStorage.addAttribute(NSAttributedStringKey.backgroundColor, value: highlightColor, range: attrRange)
|
||||
|
||||
attrRange = NSRange(highlightedNote4Range!, in: highlightedNote4)
|
||||
textStorage.addAttribute(NSAttributedStringKey.backgroundColor, value: highlightColor, range: attrRange)
|
||||
|
||||
attrRange = NSRange(highlightedNote5Range!, in: highlightedNote5)
|
||||
textStorage.addAttribute(NSAttributedStringKey.backgroundColor, value: highlightColor, range: attrRange)
|
||||
|
||||
attrRange = NSRange(highlightedNote6Range!, in: highlightedNote6)
|
||||
textStorage.addAttribute(NSAttributedStringKey.backgroundColor, value: highlightColor, range: attrRange)
|
||||
|
||||
attrRange = NSRange(highlightedNote7Range!, in: highlightedNote7)
|
||||
textStorage.addAttribute(NSAttributedStringKey.backgroundColor, value: highlightColor, range: attrRange)
|
||||
}
|
||||
|
||||
func buildMisspelled(textStorage: NSTextStorage) {
|
||||
let misspelledWord1Range = textView.string.range(of: misspelledWord1)
|
||||
let misspelledWord2Range = textView.string.range(of: misspelledWord2)
|
||||
let misspelledWord3Range = textView.string.range(of: misspelledWord3)
|
||||
let misspelledWord4Range = textView.string.range(of: misspelledWord4)
|
||||
|
||||
misspelledWords = [ NSRange(misspelledWord1Range!, in: misspelledWord1),
|
||||
NSRange(misspelledWord2Range!, in: misspelledWord2),
|
||||
NSRange(misspelledWord3Range!, in: misspelledWord3),
|
||||
NSRange(misspelledWord4Range!, in: misspelledWord4) ]
|
||||
|
||||
// Apply the underline misspelled words.
|
||||
let underlineValue = NSNumber(value: 1)
|
||||
var attrRange = NSRange(misspelledWord1Range!, in: misspelledWord1)
|
||||
textStorage.addAttribute(NSAttributedStringKey.underlineStyle, value: underlineValue, range: attrRange)
|
||||
|
||||
attrRange = NSRange(misspelledWord2Range!, in: misspelledWord2)
|
||||
textStorage.addAttribute(NSAttributedStringKey.underlineStyle, value: underlineValue, range: attrRange)
|
||||
|
||||
attrRange = NSRange(misspelledWord3Range!, in: misspelledWord3)
|
||||
textStorage.addAttribute(NSAttributedStringKey.underlineStyle, value: underlineValue, range: attrRange)
|
||||
|
||||
attrRange = NSRange(misspelledWord4Range!, in: misspelledWord4)
|
||||
textStorage.addAttribute(NSAttributedStringKey.underlineStyle, value: underlineValue, range: attrRange)
|
||||
}
|
||||
|
||||
func insertTextViewString() {
|
||||
// Set the content.
|
||||
textView.string = storySnippet
|
||||
|
||||
// Prepare to edit the text storage.
|
||||
let textStorage: NSTextStorage = textView.textStorage!
|
||||
textStorage.beginEditing()
|
||||
|
||||
// Find the all ranges.
|
||||
buildVocabulary(textStorage: textStorage)
|
||||
buildHighlighted(textStorage: textStorage)
|
||||
buildMisspelled(textStorage: textStorage)
|
||||
|
||||
// Grab the default font.
|
||||
let range = NSRange(location: 0, length: textView.string.characters.count)
|
||||
if let font = textStorage.attribute(NSAttributedStringKey.font, at: range.location, effectiveRange: nil) as? NSFont {
|
||||
// Apply the heading font.
|
||||
let titleRange = textView.string.range(of: storyTitle)
|
||||
|
||||
let headingFont = NSFont(name: font.familyName!, size: font.pointSize + 10)
|
||||
textStorage.addAttribute(NSAttributedStringKey.font,
|
||||
value: headingFont as Any,
|
||||
range: NSRange(titleRange!, in: storyTitle))
|
||||
}
|
||||
|
||||
textStorage.endEditing()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - NSAccessibilityCustomRotorItemSearchDelegate
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
extension CustomRotorsTextViewController {
|
||||
|
||||
func textSearchResultForString(searchString: String, fromRange: NSRange, direction: NSAccessibilityCustomRotor.SearchDirection)
|
||||
-> NSAccessibilityCustomRotor.ItemResult? {
|
||||
var searchResult: NSAccessibilityCustomRotor.ItemResult?
|
||||
|
||||
var searchEntry = String()
|
||||
if searchString == searchKeyword1 {
|
||||
searchEntry = contentSearchEntry1
|
||||
} else if searchString == searchKeyword2 {
|
||||
searchEntry = contentSearchEntry2
|
||||
}
|
||||
|
||||
if !searchEntry.characters.isEmpty {
|
||||
var searchFound = false
|
||||
let contentString = textView.textStorage?.string
|
||||
|
||||
let resultRange = contentString?.range(of: searchEntry,
|
||||
options: NSString.CompareOptions.literal,
|
||||
range: (contentString?.startIndex)!..<(contentString?.endIndex)!,
|
||||
locale: nil)
|
||||
let realRange = NSRange(resultRange!, in: contentString!)
|
||||
|
||||
if direction == NSAccessibilityCustomRotor.SearchDirection.previous {
|
||||
searchFound = (realRange.location) < fromRange.location
|
||||
} else if direction == NSAccessibilityCustomRotor.SearchDirection.next {
|
||||
searchFound = (realRange.location) >= NSMaxRange(fromRange)
|
||||
}
|
||||
if searchFound {
|
||||
searchResult = NSAccessibilityCustomRotor.ItemResult(targetElement: textView as NSAccessibilityElementProtocol)
|
||||
searchResult?.targetRange = realRange
|
||||
}
|
||||
}
|
||||
return searchResult
|
||||
}
|
||||
|
||||
public func rotor(_ rotor: NSAccessibilityCustomRotor,
|
||||
resultFor searchParameters: NSAccessibilityCustomRotor.SearchParameters) -> NSAccessibilityCustomRotor.ItemResult? {
|
||||
var searchResult: NSAccessibilityCustomRotor.ItemResult?
|
||||
|
||||
let currentItemResult = searchParameters.currentItem
|
||||
let direction = searchParameters.searchDirection
|
||||
let filterText = searchParameters.filterString
|
||||
var currentRange = currentItemResult?.targetRange
|
||||
let rotorName = rotor.label
|
||||
|
||||
if rotor.type == .any {
|
||||
return textSearchResultForString(searchString: filterText, fromRange: currentRange!, direction: direction)
|
||||
}
|
||||
|
||||
var filteredChildren = [NSRange]()
|
||||
if rotorName == vocabularyRotorTitle {
|
||||
filteredChildren = vocabWords
|
||||
} else if rotorName == highlightRotorTitle {
|
||||
filteredChildren = highlightedNotes
|
||||
} else if rotor.type == .misspelledWord {
|
||||
filteredChildren = misspelledWords
|
||||
}
|
||||
|
||||
// If filter text is available, but not a range, use the start range.
|
||||
if !filterText.characters.isEmpty && currentRange?.location == NSNotFound {
|
||||
currentRange = NSRange(location: 0, length: 0)
|
||||
}
|
||||
|
||||
var targetRangeValue: NSRange?
|
||||
let contentString = textView.textStorage?.string
|
||||
let currentTextIndex = currentRange?.location
|
||||
if currentTextIndex == NSNotFound {
|
||||
// Find the start or end element.
|
||||
if direction == NSAccessibilityCustomRotor.SearchDirection.next {
|
||||
targetRangeValue = filteredChildren.first
|
||||
} else if direction == NSAccessibilityCustomRotor.SearchDirection.previous {
|
||||
targetRangeValue = filteredChildren.last
|
||||
}
|
||||
} else {
|
||||
if direction == NSAccessibilityCustomRotor.SearchDirection.previous {
|
||||
for i in (0...filteredChildren.count).reversed() {
|
||||
let range = Range(filteredChildren[i], in: contentString!)
|
||||
let subString = contentString![range!]
|
||||
|
||||
let matches = subString.localizedCaseInsensitiveCompare(filterText)
|
||||
let index = filteredChildren[i].location
|
||||
|
||||
let matchesFilterText = (filterText.characters.isEmpty || matches == .orderedSame)
|
||||
if index < currentTextIndex! && matchesFilterText {
|
||||
targetRangeValue = filteredChildren[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if direction == NSAccessibilityCustomRotor.SearchDirection.next {
|
||||
for i in 0..<filteredChildren.count {
|
||||
let range = Range(filteredChildren[i], in: contentString!)
|
||||
let subString = contentString![range!]
|
||||
|
||||
let matches = subString.localizedCaseInsensitiveCompare(filterText)
|
||||
let index = filteredChildren[i].location
|
||||
|
||||
let matchesFilterText = (filterText.characters.isEmpty || matches == .orderedSame)
|
||||
if index > currentTextIndex! && matchesFilterText {
|
||||
targetRangeValue = filteredChildren[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if targetRangeValue != nil {
|
||||
let textRange = targetRangeValue
|
||||
searchResult = NSAccessibilityCustomRotor.ItemResult(targetElement: textView as NSAccessibilityElementProtocol)
|
||||
searchResult?.targetRange = textRange!
|
||||
}
|
||||
return searchResult
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CustomRotorsTextViewDelegate
|
||||
|
||||
@available(OSX 10.13, *)
|
||||
extension CustomRotorsTextViewController {
|
||||
func createCustomRotors() -> [NSAccessibilityCustomRotor] {
|
||||
// Create the vocabulary rotor.
|
||||
let vocabularyRotor =
|
||||
NSAccessibilityCustomRotor(label: vocabularyRotorTitle, itemSearchDelegate: self as NSAccessibilityCustomRotorItemSearchDelegate)
|
||||
|
||||
// Create the special text highlight rotor.
|
||||
let highlightRotor =
|
||||
NSAccessibilityCustomRotor(label: highlightRotorTitle, itemSearchDelegate: self as NSAccessibilityCustomRotorItemSearchDelegate)
|
||||
|
||||
// Create the misspelled rotor.
|
||||
let misspelledRotor =
|
||||
NSAccessibilityCustomRotor(rotorType: .misspelledWord, itemSearchDelegate: self as NSAccessibilityCustomRotorItemSearchDelegate)
|
||||
|
||||
// Create the text search rotor.
|
||||
let textSearchRotor =
|
||||
NSAccessibilityCustomRotor(rotorType: .any, itemSearchDelegate: self as NSAccessibilityCustomRotorItemSearchDelegate)
|
||||
|
||||
return [vocabularyRotor, highlightRotor, misspelledRotor, textSearchRotor]
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomButtonDown.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomButtonDown@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomButtonHighlight.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomButtonHighlight@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomButtonUp.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomButtonUp@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomCheckboxSelected.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomCheckboxSelected@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 4.1 KiB |
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomCheckboxUnselected.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomCheckboxUnselected@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.8 KiB |
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomRadioButtonSelected.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomRadioButtonSelected@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 4.6 KiB |
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomRadioButtonUnselected.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CustomRadioButtonUnselected@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 4.1 KiB |
21
AccessibilityUIExamples/AccessibilityUIExamples/Images.xcassets/RedDot.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "RedDot.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
AccessibilityUIExamples/AccessibilityUIExamples/Images.xcassets/RedDot.imageset/RedDot.png
vendored
Normal file
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "SwitchHandle.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "SwitchHandleDown.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "SwitchOverlayMask.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.3 KiB |
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "SwitchWell.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
AccessibilityUIExamples/AccessibilityUIExamples/Images.xcassets/SwitchWell.imageset/SwitchWell.png
vendored
Normal file
After Width: | Height: | Size: 3.9 KiB |
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating adding accessibility to a CALayer subclass that behaves like an image by implementing the NSAccessibilityImage protocol.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
import QuartzCore
|
||||
|
||||
class CustomImageLayer: CALayer, NSAccessibilityImage {
|
||||
|
||||
var parent: NSView!
|
||||
var titleElement: CustomTextLayer!
|
||||
|
||||
// MARK: NSAccessibilityImage
|
||||
|
||||
func accessibilityFrame() -> NSRect {
|
||||
return NSAccessibilityFrameInView(parent, frame)
|
||||
}
|
||||
|
||||
func accessibilityParent() -> Any? {
|
||||
return NSAccessibilityUnignoredAncestor(parent)
|
||||
}
|
||||
|
||||
func accessibilityLabel() -> String? {
|
||||
return titleElement.string as? String
|
||||
}
|
||||
|
||||
func accessibilityTitleUIElement() -> Any? {
|
||||
return titleElement
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating adding accessibility to an NSView subclass that behaves like a label by implementing the NSAccessibilityStaticText protocol.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class CustomTextLayer: CATextLayer, NSAccessibilityStaticText {
|
||||
|
||||
var parent: NSView!
|
||||
|
||||
// MARK: NSAccessibilityStaticText
|
||||
|
||||
func accessibilityFrame() -> NSRect {
|
||||
return NSAccessibilityFrameInView(parent, frame)
|
||||
}
|
||||
|
||||
func accessibilityParent() -> Any? {
|
||||
return NSAccessibilityUnignoredAncestor(parent)
|
||||
}
|
||||
|
||||
func accessibilityValue() -> String? {
|
||||
return string as? String
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating adding accessibility to an NSView subclass that draws itself using two separate CALayers.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ImageViewLayerView: NSView {
|
||||
|
||||
// MARK: - Internals
|
||||
|
||||
fileprivate struct LayoutInfo {
|
||||
static let ImageWidth = CGFloat(75.0)
|
||||
static let ImageHeight = ImageWidth
|
||||
static let FontSize = CGFloat(18.0)
|
||||
static let TextFrameHeight = CGFloat(25.0)
|
||||
}
|
||||
|
||||
var imageLayer: CustomImageLayer!
|
||||
var textLayer: CustomTextLayer!
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
func commonInit() {
|
||||
// Root layer will have a green background color.
|
||||
let rootLayer = CALayer()
|
||||
let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)
|
||||
rootLayer.backgroundColor = CGColor(colorSpace: colorSpace!, components: [0.9, 1.0, 0.60, 1.0])
|
||||
layer = rootLayer
|
||||
|
||||
// Sub image layer will have the RedDot image as it's content.
|
||||
let imageLayer = CustomImageLayer()
|
||||
let imageName = "RedDot"
|
||||
imageLayer.contents = NSImage(named: NSImage.Name(rawValue: imageName))
|
||||
imageLayer.parent = self
|
||||
let imageFrame = NSRect(x: (frame.size.width / 2) - LayoutInfo.ImageWidth,
|
||||
y: (frame.size.height / 2) - LayoutInfo.ImageHeight + 8,
|
||||
width: LayoutInfo.ImageWidth,
|
||||
height: LayoutInfo.ImageHeight)
|
||||
imageLayer.frame = imageFrame
|
||||
imageLayer.anchorPoint = CGPoint()
|
||||
rootLayer.addSublayer(imageLayer)
|
||||
|
||||
// Sub text layer will have a black label.
|
||||
let textLayer = CustomTextLayer()
|
||||
textLayer.string = NSLocalizedString("Red Dot", comment: "displayed text for the RedDot image")
|
||||
textLayer.parent = self
|
||||
textLayer.frame = CGRect(x: imageFrame.origin.x,
|
||||
y: imageFrame.origin.y,
|
||||
width: LayoutInfo.ImageWidth,
|
||||
height: LayoutInfo.TextFrameHeight)
|
||||
textLayer.anchorPoint = CGPoint()
|
||||
textLayer.fontSize = LayoutInfo.FontSize
|
||||
textLayer.alignmentMode = "center"
|
||||
textLayer.foregroundColor = NSColor.black.cgColor
|
||||
rootLayer.addSublayer(textLayer)
|
||||
|
||||
wantsLayer = true
|
||||
|
||||
imageLayer.titleElement = textLayer
|
||||
|
||||
self.imageLayer = imageLayer
|
||||
self.textLayer = textLayer
|
||||
}
|
||||
|
||||
override var wantsUpdateLayer: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension ImageViewLayerView {
|
||||
|
||||
// MARK: NSAccessibility
|
||||
|
||||
override func accessibilityChildren() -> [Any]? {
|
||||
return [imageLayer, textLayer]
|
||||
}
|
||||
|
||||
override func accessibilityHitTest(_ point: NSPoint) -> Any? {
|
||||
// Note: use Xcode's "Accessibility Inspector" to test this.
|
||||
let accessibilityContainer = NSAccessibilityUnignoredAncestor(self)
|
||||
let imageFrame = NSAccessibilityFrameInView(self, imageLayer.frame)
|
||||
let textFrame = NSAccessibilityFrameInView(self, textLayer.frame)
|
||||
|
||||
var hitTestElement : Any
|
||||
if imageFrame.contains(point) {
|
||||
hitTestElement = imageLayer
|
||||
} else if textFrame.contains(point) {
|
||||
hitTestElement = textLayer
|
||||
} else {
|
||||
hitTestElement = accessibilityContainer!
|
||||
}
|
||||
|
||||
return hitTestElement
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating the preferred method of making an accessible, custom image by subclassing NSImageView.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
/*
|
||||
IMPORTANT: This is not a template for developing a custom control.
|
||||
This sample is intended to demonstrate how to add accessibility to
|
||||
existing custom controls that are not implemented using the preferred methods.
|
||||
For information on how to create custom controls please visit http://developer.apple.com
|
||||
*/
|
||||
|
||||
class ImageViewSubclass: NSImageView {
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
let name = "RedDot"
|
||||
let image = NSImage(named: NSImage.Name(rawValue: name))
|
||||
image?.draw(in: bounds, from: NSRect.zero, operation: NSCompositingOperation.sourceOver, fraction: 1.0)
|
||||
}
|
||||
|
||||
// MARK: - NSAccessibility
|
||||
|
||||
override func accessibilityLabel() -> String? {
|
||||
return NSLocalizedString("RedDot", comment: "accessibility label of the RedDot image")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating adding accessibility to an NSView subclass that behaves like an image by implementing the NSAccessibilityImage protocol.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
/*
|
||||
IMPORTANT: This is not a template for developing a custom control.
|
||||
This sample is intended to demonstrate how to add accessibility to
|
||||
existing custom controls that are not implemented using the preferred methods.
|
||||
For information on how to create custom controls please visit http://developer.apple.com
|
||||
*/
|
||||
|
||||
class ViewImageSubclass: NSView, NSAccessibilityImage {
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
let imageName = "RedDot"
|
||||
let image = NSImage(named: NSImage.Name(rawValue: imageName))
|
||||
image?.draw(in: bounds, from: NSRect.zero, operation: NSCompositingOperation.sourceOver, fraction: 1.0)
|
||||
}
|
||||
|
||||
// MARK: - NSAccessibility
|
||||
|
||||
override func accessibilityLabel() -> String? {
|
||||
return NSLocalizedString("RedDot", comment: "accessibility label of the RedDot image")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Extends the CustomLayoutAreaView with methods to return position and size measurements
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension CustomLayoutAreaView {
|
||||
|
||||
fileprivate func rectForItemIndex(itemIndex: Int) -> NSRect {
|
||||
let layoutItem = layoutItems[itemIndex]
|
||||
return layoutItem.bounds
|
||||
}
|
||||
|
||||
func handleRectForItemIndex(itemIndex: Int, position: HandlePosition) -> NSRect {
|
||||
let itemRect = rectForItemIndex(itemIndex: itemIndex)
|
||||
var handleRect = NSRect.zero
|
||||
let size = LayoutInfo.LayoutItemHandleSize
|
||||
let halfSize = size / 2.0
|
||||
|
||||
switch position {
|
||||
case .north:
|
||||
handleRect = NSRect(x: itemRect.midX, y: itemRect.maxY, width: size, height: size)
|
||||
case .northEast:
|
||||
handleRect = NSRect(x: itemRect.maxX, y: itemRect.maxY, width: size, height: size)
|
||||
case .east:
|
||||
handleRect = NSRect(x: itemRect.maxX, y: itemRect.midY, width: size, height: size)
|
||||
case .southEast:
|
||||
handleRect = NSRect(x: itemRect.maxX, y: itemRect.minY, width: size, height: size)
|
||||
case .south:
|
||||
handleRect = NSRect(x: itemRect.midX, y: itemRect.minY, width: size, height: size)
|
||||
case .southWest:
|
||||
handleRect = NSRect(x: itemRect.minX, y: itemRect.minY, width: size, height: size)
|
||||
case .west:
|
||||
handleRect = NSRect(x: itemRect.minX, y: itemRect.midY, width: size, height: size)
|
||||
case .northWest:
|
||||
handleRect = NSRect(x: itemRect.minX, y: itemRect.maxY, width: size, height: size)
|
||||
default: break
|
||||
}
|
||||
handleRect.origin.x -= halfSize
|
||||
handleRect.origin.y -= halfSize
|
||||
return handleRect
|
||||
}
|
||||
|
||||
func rectForLayoutItem(rect: NSRect, handle: HandlePosition, deltaX: CGFloat, deltaY: CGFloat) -> NSRect {
|
||||
var originX = rect.origin.x
|
||||
var originY = rect.origin.y
|
||||
var width = rect.size.width
|
||||
var height = rect.size.height
|
||||
|
||||
let eastDeltaX = max(min(deltaX, bounds.size.width - width - originX), -(width - LayoutInfo.LayoutItemMinSize))
|
||||
let westDeltaX = max(min(deltaX, width - LayoutInfo.LayoutItemMinSize), -originX)
|
||||
let northDeltaY = max(min(deltaY, bounds.size.height - height - originY), -(height - LayoutInfo.LayoutItemMinSize))
|
||||
let southDeltaY = max(min(deltaY, height - LayoutInfo.LayoutItemMinSize), -originY)
|
||||
|
||||
switch handle {
|
||||
case .north:
|
||||
height += northDeltaY
|
||||
case .northEast:
|
||||
width += eastDeltaX
|
||||
height += northDeltaY
|
||||
case .east:
|
||||
width += eastDeltaX
|
||||
case .southEast:
|
||||
originY += southDeltaY
|
||||
width += eastDeltaX
|
||||
height -= southDeltaY
|
||||
case .south:
|
||||
originY += southDeltaY
|
||||
height -= southDeltaY
|
||||
case .southWest:
|
||||
originX += westDeltaX
|
||||
originY += southDeltaY
|
||||
width -= westDeltaX
|
||||
height -= southDeltaY
|
||||
case .west:
|
||||
originX += westDeltaX
|
||||
width -= westDeltaX
|
||||
case .northWest:
|
||||
originX += westDeltaX
|
||||
width -= westDeltaX
|
||||
height += northDeltaY
|
||||
case .unknown:
|
||||
originX += max(min(deltaX, bounds.size.width - width - originX), -originX)
|
||||
originY += max(min(deltaY, bounds.size.height - height - originY), -originY)
|
||||
}
|
||||
|
||||
return NSRect(x: originX, y: originY, width: width, height: height)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
An example demonstrating adding accessibility to a view that serves to layout UIs by implementing the NSAccessibilityLayoutArea protocol.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
/*
|
||||
IMPORTANT: This is not a template for developing a custom control.
|
||||
This sample is intended to demonstrate how to add accessibility to
|
||||
existing custom controls that are not implemented using the preferred methods.
|
||||
For information on how to create custom controls please visit http://developer.apple.com
|
||||
*/
|
||||
|
||||
// Used to iterate over the HandlePosition values.
|
||||
protocol HandleCollection: Hashable {}
|
||||
extension HandleCollection {
|
||||
static func cases() -> AnySequence<Self> {
|
||||
typealias Myself = Self
|
||||
return AnySequence { () -> AnyIterator<Myself> in
|
||||
var rawValue = 0
|
||||
return AnyIterator {
|
||||
let current: Self = withUnsafePointer(to: &rawValue) { $0.withMemoryRebound(to: Myself.self, capacity: 1) { $0.pointee } }
|
||||
guard current.hashValue == rawValue else { return nil }
|
||||
rawValue += 1
|
||||
return current
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CustomLayoutAreaView: NSView, NSAccessibilityLayoutArea {
|
||||
|
||||
// MARK: - Internals
|
||||
|
||||
struct LayoutInfo {
|
||||
static let LayoutItemHandleSize = CGFloat(8.0)
|
||||
static let LayoutItemMinSize = CGFloat(LayoutItemHandleSize * 3.0)
|
||||
static let LayoutItemMoveDelta = CGFloat(10.0)
|
||||
static let LayoutItemSize = CGFloat(50.0)
|
||||
}
|
||||
|
||||
enum HandlePosition: HandleCollection {
|
||||
case unknown
|
||||
case north
|
||||
case northEast
|
||||
case east
|
||||
case southEast
|
||||
case south
|
||||
case southWest
|
||||
case west
|
||||
case northWest
|
||||
}
|
||||
|
||||
var layoutItems = [LayoutItem]()
|
||||
var layoutItemsNeedOrdering = false
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
func commonInit() {
|
||||
let rectangleA = LayoutItem()
|
||||
rectangleA.setAccessibilityParent(self)
|
||||
rectangleA.bounds = NSRect(x: 0, y: 0, width: LayoutInfo.LayoutItemSize, height: LayoutInfo.LayoutItemSize)
|
||||
rectangleA.setAccessibilityLabel(NSLocalizedString("Rectangle A",
|
||||
comment: "accessibility layout for the first layout item"))
|
||||
layoutItems.append(rectangleA)
|
||||
|
||||
let rectangleB = LayoutItem()
|
||||
rectangleB.setAccessibilityParent(self)
|
||||
rectangleB.bounds = NSRect(x: 75, y: 75, width: LayoutInfo.LayoutItemSize, height: LayoutInfo.LayoutItemSize)
|
||||
|
||||
rectangleB.setAccessibilityLabel(NSLocalizedString("Rectangle B",
|
||||
comment: "accessibility label for the second layout item"))
|
||||
layoutItems.append(rectangleB)
|
||||
}
|
||||
|
||||
// MARK: - Layout Item Management
|
||||
|
||||
var selectedLayoutItemIndex: Int = -1 {
|
||||
didSet {
|
||||
if (selectedLayoutItemIndex >= layoutItems.count) || (selectedLayoutItemIndex < 0) {
|
||||
selectedLayoutItemIndex = -1
|
||||
} else {
|
||||
bringItemToTop(itemIndex: selectedLayoutItemIndex)
|
||||
}
|
||||
NSAccessibilityPostNotification(self, NSAccessibilityNotificationName.focusedUIElementChanged)
|
||||
needsDisplay = true
|
||||
}
|
||||
}
|
||||
|
||||
var selectedLayoutItem: LayoutItem? {
|
||||
didSet {
|
||||
guard selectedLayoutItem != nil else { return }
|
||||
|
||||
if let itemIndex = layoutItems.index(of: selectedLayoutItem!) {
|
||||
let newItemIndex = (itemIndex != NSNotFound) ? itemIndex : -1
|
||||
selectedLayoutItemIndex = newItemIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func layoutItemsInZOrder() -> [LayoutItem] {
|
||||
_ = layoutItems.sorted(by: { $0.zOrder > $1.zOrder })
|
||||
return layoutItems
|
||||
}
|
||||
|
||||
fileprivate func bringItemToTop(itemIndex: Int) {
|
||||
if itemIndex >= 0 && itemIndex < layoutItems.count {
|
||||
var zOrder = 0
|
||||
for layoutItem in layoutItemsInZOrder() {
|
||||
layoutItem.zOrder = zOrder
|
||||
zOrder += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Keyboard Events
|
||||
|
||||
fileprivate func handleArrowKeys(with event: NSEvent) {
|
||||
// We allow up/down arrow keys to change the current selection, left/right arrow keys to expand/collapse.
|
||||
guard event.modifierFlags.contains(.numericPad),
|
||||
let charactersIgnoringModifiers = event.charactersIgnoringModifiers, charactersIgnoringModifiers.characters.count == 1,
|
||||
let char = charactersIgnoringModifiers.characters.first
|
||||
else {
|
||||
super.keyDown(with: event)
|
||||
return
|
||||
}
|
||||
|
||||
let layoutItem = layoutItems[selectedLayoutItemIndex]
|
||||
var bounds = layoutItem.bounds
|
||||
|
||||
switch char {
|
||||
case Character(NSDownArrowFunctionKey)!:
|
||||
bounds.origin.y -= LayoutInfo.LayoutItemMoveDelta
|
||||
case Character(NSUpArrowFunctionKey)!:
|
||||
bounds.origin.y += LayoutInfo.LayoutItemMoveDelta
|
||||
case Character(NSLeftArrowFunctionKey)!:
|
||||
bounds.origin.x -= LayoutInfo.LayoutItemMoveDelta
|
||||
case Character(NSRightArrowFunctionKey)!:
|
||||
bounds.origin.x += LayoutInfo.LayoutItemMoveDelta
|
||||
default: break
|
||||
}
|
||||
|
||||
if !(bounds == layoutItem.bounds) {
|
||||
layoutItem.bounds = bounds
|
||||
}
|
||||
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
override func keyDown(with event: NSEvent) {
|
||||
guard let charactersIgnoringModifiers = event.charactersIgnoringModifiers, charactersIgnoringModifiers.characters.count == 1,
|
||||
let char = charactersIgnoringModifiers.characters.first
|
||||
else {
|
||||
super.keyDown(with: event)
|
||||
return
|
||||
}
|
||||
switch char {
|
||||
case Character(NSTabCharacter)!:
|
||||
if selectedLayoutItemIndex < (NSInteger)(layoutItems.count - 1) {
|
||||
selectedLayoutItemIndex += 1
|
||||
}
|
||||
case Character(NSBackTabCharacter)!: // Shift-tab
|
||||
if selectedLayoutItemIndex > 0 {
|
||||
selectedLayoutItemIndex -= 1
|
||||
}
|
||||
default:
|
||||
handleArrowKeys(with: event)
|
||||
break
|
||||
}
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
// MARK: - Mouse Events
|
||||
|
||||
fileprivate func hitTestForLayoutItemAtPoint(point: NSPoint) -> LayoutItem? {
|
||||
// Look for any layout item under the mouse click.
|
||||
for layoutItem in layoutItemsInZOrder() {
|
||||
if layoutItem.bounds.contains(point) {
|
||||
// Found a layout item the mouse clicked on.
|
||||
return layoutItem
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
fileprivate func hitTestForHandleAtPoint(point: NSPoint) -> HandlePosition {
|
||||
var hitTestHandle: HandlePosition = .unknown
|
||||
|
||||
if selectedLayoutItemIndex >= 0 {
|
||||
let cases = Array(HandlePosition.cases())
|
||||
for position in cases {
|
||||
let handleRect = handleRectForItemIndex(itemIndex: selectedLayoutItemIndex,
|
||||
position: position)
|
||||
if handleRect.contains(point) {
|
||||
hitTestHandle = position
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hitTestHandle
|
||||
}
|
||||
|
||||
override func mouseDown(with event: NSEvent) {
|
||||
let mouseDownPoint = convert(event.locationInWindow, from: nil)
|
||||
|
||||
var currentSelectedlayoutItem = selectedLayoutItem
|
||||
let selectedHandlePosition = hitTestForHandleAtPoint(point: mouseDownPoint)
|
||||
if selectedHandlePosition == .unknown {
|
||||
currentSelectedlayoutItem = hitTestForLayoutItemAtPoint(point: mouseDownPoint)
|
||||
selectedLayoutItem = currentSelectedlayoutItem
|
||||
}
|
||||
|
||||
var deltaX = CGFloat(0)
|
||||
var deltaY = CGFloat(0)
|
||||
let bounds = selectedLayoutItem?.bounds
|
||||
|
||||
var currentEvent = event
|
||||
let eventMask: NSEvent.EventTypeMask = [NSEvent.EventTypeMask.leftMouseUp, NSEvent.EventTypeMask.leftMouseDragged]
|
||||
let untilDate = NSDate.distantFuture
|
||||
|
||||
var stop = false
|
||||
repeat {
|
||||
var mousePoint = convert(currentEvent.locationInWindow, from: nil)
|
||||
|
||||
switch currentEvent.type {
|
||||
case NSEvent.EventType.leftMouseDown, NSEvent.EventType.leftMouseDragged:
|
||||
// User dragged a layout item.
|
||||
mousePoint = convert(currentEvent.locationInWindow, from: nil)
|
||||
deltaX = mousePoint.x - mouseDownPoint.x
|
||||
deltaY = mousePoint.y - mouseDownPoint.y
|
||||
|
||||
selectedLayoutItem?.bounds = rectForLayoutItem(rect: bounds!, handle: selectedHandlePosition, deltaX: deltaX, deltaY: deltaY)
|
||||
|
||||
// As the user keeps dragging the mouse get the next event.
|
||||
currentEvent =
|
||||
(window?.nextEvent(matching: eventMask, until: untilDate, inMode: RunLoopMode.eventTrackingRunLoopMode, dequeue: true))!
|
||||
default:
|
||||
// User stopped tracking the layout item.
|
||||
stop = true
|
||||
break
|
||||
}
|
||||
display()
|
||||
}
|
||||
while !stop
|
||||
}
|
||||
|
||||
// MARK: - Drawing
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
if window?.firstResponder != self {
|
||||
selectedLayoutItemIndex = -1
|
||||
}
|
||||
|
||||
// Draw the layout area's background and border.
|
||||
let outline = NSBezierPath(rect: bounds)
|
||||
NSColor.white.set()
|
||||
outline.lineWidth = 2.0
|
||||
outline.fill()
|
||||
NSColor.lightGray.set()
|
||||
outline.stroke()
|
||||
|
||||
let interimArray = NSArray(array: layoutItemsInZOrder())
|
||||
let enumerator = interimArray.reverseObjectEnumerator()
|
||||
let items = enumerator.allObjects
|
||||
for case let layoutItem as LayoutItem in items {
|
||||
let itemPath = NSBezierPath(rect: layoutItem.bounds)
|
||||
NSColor.blue.set()
|
||||
itemPath.fill()
|
||||
NSColor.black.set()
|
||||
itemPath.stroke()
|
||||
}
|
||||
|
||||
// Draw all the layout item handles.
|
||||
let iterIdx = selectedLayoutItemIndex
|
||||
if iterIdx >= 0 {
|
||||
let handles = Array(HandlePosition.cases())
|
||||
|
||||
for position in handles {
|
||||
let handleRect =
|
||||
handleRectForItemIndex(itemIndex: selectedLayoutItemIndex, position: position)
|
||||
let handlePath = NSBezierPath(rect: handleRect)
|
||||
NSColor.gray.set()
|
||||
handlePath.fill()
|
||||
NSColor.black.set()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension CustomLayoutAreaView {
|
||||
|
||||
// MARK: First Responder
|
||||
|
||||
// Set to allow keyDown, moveLeft, moveRight to be called.
|
||||
override var acceptsFirstResponder: Bool { return true }
|
||||
|
||||
override func becomeFirstResponder() -> Bool {
|
||||
let didBecomeFirstResponder = super.becomeFirstResponder()
|
||||
if didBecomeFirstResponder {
|
||||
setKeyboardFocusRingNeedsDisplay(bounds)
|
||||
|
||||
// If user is tabbing through the key loop and that's how this element became first responder,
|
||||
// select the first or last layout item depending on the direction of motion through the key loop.
|
||||
let event = NSApp.currentEvent
|
||||
if event?.type == NSEvent.EventType.keyDown {
|
||||
guard let charactersIgnoringModifiers = event?.charactersIgnoringModifiers, charactersIgnoringModifiers.characters.count == 1,
|
||||
let char = charactersIgnoringModifiers.characters.first else { return true }
|
||||
switch char {
|
||||
case Character(NSBackTabCharacter)!: // Shift-tab
|
||||
if selectedLayoutItemIndex > 0 {
|
||||
selectedLayoutItemIndex -= 1
|
||||
}
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
return didBecomeFirstResponder
|
||||
}
|
||||
|
||||
override func resignFirstResponder() -> Bool {
|
||||
let didResignFirstResponder = super.resignFirstResponder()
|
||||
if didResignFirstResponder {
|
||||
setKeyboardFocusRingNeedsDisplay(bounds)
|
||||
selectedLayoutItemIndex = -1
|
||||
needsDisplay = true
|
||||
}
|
||||
return didResignFirstResponder
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension CustomLayoutAreaView {
|
||||
|
||||
// MARK: NSAccessibilityLayoutArea
|
||||
|
||||
override var accessibilityFocusedUIElement: Any {
|
||||
if let accessibilityFocusedUIElement = selectedLayoutItem {
|
||||
return accessibilityFocusedUIElement
|
||||
} else {
|
||||
return super.accessibilityFocusedUIElement!
|
||||
}
|
||||
}
|
||||
|
||||
override func accessibilityLabel() -> String {
|
||||
return NSLocalizedString("Rectangles", comment: "accessibility label for the layout area")
|
||||
}
|
||||
|
||||
override func accessibilityChildren() -> [Any]? {
|
||||
return layoutItems
|
||||
}
|
||||
|
||||
override func accessibilitySelectedChildren() -> [Any]? {
|
||||
if let selectedItem = selectedLayoutItem {
|
||||
let accessibilitySelectedChildren: [LayoutItem] = [selectedItem]
|
||||
return accessibilitySelectedChildren
|
||||
}
|
||||
return super.accessibilitySelectedChildren()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
View controller demonstrating an accessible custom NSView that behaves like a layout area with adjustable items.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class CustomLayoutAreaViewController: NSViewController {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
The object representing the accessibility element for the CustomLayoutAreaView.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class LayoutItem: NSAccessibilityElement, NSAccessibilityLayoutItem {
|
||||
|
||||
var zOrder = 0
|
||||
|
||||
override func accessibilityIdentifier() -> String {
|
||||
return accessibilityLabel()!
|
||||
}
|
||||
|
||||
var bounds: NSRect = .zero {
|
||||
didSet {
|
||||
let minSize = CustomLayoutAreaView.LayoutInfo.LayoutItemHandleSize * 3
|
||||
if bounds.size.height < minSize {
|
||||
bounds.size.height = minSize
|
||||
}
|
||||
if bounds.size.width < minSize {
|
||||
bounds.size.width = minSize
|
||||
}
|
||||
|
||||
if let parent = accessibilityParent() as? CustomLayoutAreaView {
|
||||
if !(oldValue.origin == bounds.origin) && parent.selectedLayoutItem == self {
|
||||
// A layout item was moved (bounds changed).
|
||||
NSAccessibilityPostNotification(accessibilityParent, NSAccessibilityNotificationName.selectedChildrenMoved)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension LayoutItem {
|
||||
|
||||
// MARK: NSAccessibilityLayoutItem
|
||||
|
||||
override func setAccessibilityFrame(_ accessibilityFrame: NSRect) {
|
||||
var newFrame = accessibilityFrame
|
||||
if let parentView = accessibilityParent() as? CustomLayoutAreaView {
|
||||
let window = parentView.window
|
||||
newFrame = (window?.convertFromScreen(newFrame))!
|
||||
newFrame = parentView.convert(newFrame, from:nil)
|
||||
bounds = newFrame
|
||||
parentView.needsDisplay = true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: NSAccessibilityElement
|
||||
|
||||
override func accessibilityParent() -> Any? {
|
||||
return super.accessibilityParent()
|
||||
}
|
||||
|
||||
override func accessibilityFrame() -> NSRect {
|
||||
var result = NSRect.zero
|
||||
if let accessibilityParent = accessibilityParent() as? CustomLayoutAreaView {
|
||||
result = NSAccessibilityFrameInView(accessibilityParent, bounds)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override func isAccessibilityFocused() -> Bool {
|
||||
var isFocused = false
|
||||
if let accessibilityParent = accessibilityParent() as? CustomLayoutAreaView {
|
||||
if accessibilityParent.selectedLayoutItem != nil {
|
||||
isFocused = accessibilityParent.selectedLayoutItem == self
|
||||
}
|
||||
}
|
||||
return isFocused
|
||||
}
|
||||
|
||||
// MARK: NSAccessibility
|
||||
|
||||
override func setAccessibilityFocused(_ accessibilityFocused: Bool) {
|
||||
guard let accessibilityParent = accessibilityParent() as? CustomLayoutAreaView else { return }
|
||||
|
||||
if accessibilityFocused {
|
||||
accessibilityParent.selectedLayoutItem = self
|
||||
} else {
|
||||
if let layoutItem = accessibilityParent.accessibilityFocusedUIElement as? LayoutItem {
|
||||
if layoutItem == self {
|
||||
accessibilityParent.selectedLayoutItem = self
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
Category for adoption on NSAccessibilityOutline.
|
||||
*/
|
||||
|
||||
#import "AccessibilityUIExamples-Swift.h"
|
||||
|
||||
@interface CustomOutlineView (Accessibility) <NSAccessibilityOutline>
|
||||
@end
|
||||
|
||||
@implementation CustomOutlineView (Accessibility)
|
||||
|
||||
- (NSArray *)accessibilityRows
|
||||
{
|
||||
NSMutableArray *accessibilityRows = [[NSMutableArray alloc] init];
|
||||
NSArray *visibleNodes = [self visibleNodes];
|
||||
|
||||
for (OutlineViewNode *node in visibleNodes) {
|
||||
NSAccessibilityElement *element = [self accessibilityElementForNodeWithNode:node];
|
||||
[accessibilityRows addObject:element];
|
||||
}
|
||||
|
||||
return accessibilityRows;
|
||||
}
|
||||
|
||||
- (NSArray *)accessibilitySelectedRows {
|
||||
NSArray *accessibilityRows = [self accessibilityRows];
|
||||
return @[accessibilityRows[self.selectedRow]];
|
||||
}
|
||||
|
||||
- (void)setAccessibilitySelectedRows:(NSArray *)selectedRows {
|
||||
if (selectedRows.count == 1) {
|
||||
NSArray *accessibilityRows = [self accessibilityRows];
|
||||
NSInteger selectedRow = [accessibilityRows indexOfObject:selectedRows.firstObject];
|
||||
if (selectedRow != NSNotFound) {
|
||||
self.selectedRow = selectedRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
View controller demonstrating an accessible, custom NSView subclass that behaves like a button.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
/*
|
||||
IMPORTANT: This is not a template for developing a custom outline view.
|
||||
This sample is intended to demonstrate how to add accessibility to
|
||||
existing custom controls that are not implemented using the preferred methods.
|
||||
For information on how to create custom controls please visit http://developer.apple.com
|
||||
*/
|
||||
|
||||
class CustomOutlineView: NSView {
|
||||
|
||||
// MARK: - Internals
|
||||
|
||||
fileprivate struct LayoutInfo {
|
||||
static let OutlineRowHeight = CGFloat(18.0)
|
||||
static let OutlineBorderLineWidth = CGFloat(2.0)
|
||||
static let OutlineIndentationSize = CGFloat(18.0)
|
||||
}
|
||||
|
||||
fileprivate var rootNode = OutlineViewNode()
|
||||
fileprivate var mouseDownRow = 0
|
||||
fileprivate var mouseDownInDisclosureTriangle = false
|
||||
fileprivate var accessibilityRowElements = NSMutableDictionary()
|
||||
|
||||
@objc var selectedRow: Int = 0 {
|
||||
didSet {
|
||||
let numVisibleRows = visibleNodes().count
|
||||
|
||||
// Protect from of bounds selection.
|
||||
if selectedRow >= numVisibleRows {
|
||||
selectedRow = numVisibleRows - 1
|
||||
} else if selectedRow < 0 {
|
||||
selectedRow = 0
|
||||
}
|
||||
NSAccessibilityPostNotification(self, NSAccessibilityNotificationName.selectedRowsChanged)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
required override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
fileprivate func commonInit() {
|
||||
buildTree()
|
||||
}
|
||||
|
||||
// MARK: - Content
|
||||
|
||||
fileprivate func buildTree() {
|
||||
rootNode = OutlineViewNode.node(name: "")
|
||||
rootNode.expanded = true
|
||||
|
||||
let nobleGas = rootNode.addChildNode(name: NSLocalizedString("Noble Gas", comment:""))
|
||||
nobleGas.expanded = true
|
||||
_ = nobleGas.addChildNode(name: NSLocalizedString("Neon", comment: ""))
|
||||
_ = nobleGas.addChildNode(name: NSLocalizedString("Helium", comment: ""))
|
||||
|
||||
let semiMetal = rootNode.addChildNode(name: NSLocalizedString("Semi Metal", comment:""))
|
||||
semiMetal.expanded = true
|
||||
let boron = semiMetal.addChildNode(name: NSLocalizedString("Boron", comment: ""))
|
||||
let silicon = semiMetal.addChildNode(name: NSLocalizedString("Silicon", comment: ""))
|
||||
|
||||
_ = boron.addChildNode(name: NumberFormatter.localizedString(from: NSNumber(value: 10.811), number: NumberFormatter.Style.decimal))
|
||||
_ = silicon.addChildNode(name: NumberFormatter.localizedString(from: NSNumber(value: 28.086), number: NumberFormatter.Style.decimal))
|
||||
|
||||
accessibilityRowElements = NSMutableDictionary()
|
||||
selectedRow = 1
|
||||
}
|
||||
|
||||
fileprivate func selectedNode() -> OutlineViewNode {
|
||||
return nodeAtRow(row: selectedRow)!
|
||||
}
|
||||
|
||||
fileprivate func nodeAtRow(row: Int) -> OutlineViewNode? {
|
||||
if row >= 0 && row < visibleNodes().count {
|
||||
return visibleNodes()[row]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
fileprivate func rowCount() -> Int {
|
||||
return visibleNodes().count
|
||||
}
|
||||
|
||||
fileprivate func rowForPoint(point: NSPoint) -> Int {
|
||||
return Int(bounds.size.height - point.y - LayoutInfo.OutlineBorderLineWidth) / Int(LayoutInfo.OutlineRowHeight)
|
||||
}
|
||||
|
||||
fileprivate func rowForNode(node: OutlineViewNode) -> Int {
|
||||
return visibleNodes().index(of: node)!
|
||||
}
|
||||
|
||||
@objc
|
||||
func visibleNodes() -> [OutlineViewNode] {
|
||||
var visibleNodesToUse = [OutlineViewNode]()
|
||||
visibleNodesToUse.append(rootNode)
|
||||
|
||||
var idx = 0
|
||||
while !visibleNodesToUse.isEmpty {
|
||||
var insertIndex = idx + 1
|
||||
|
||||
if insertIndex > visibleNodesToUse.count {
|
||||
break
|
||||
}
|
||||
|
||||
let node = visibleNodesToUse[idx]
|
||||
if (node as OutlineViewNode).expanded {
|
||||
for child in node.children {
|
||||
if insertIndex < visibleNodesToUse.count {
|
||||
visibleNodesToUse.insert(child, at: insertIndex)
|
||||
} else {
|
||||
visibleNodesToUse.append(child)
|
||||
}
|
||||
insertIndex += 1
|
||||
}
|
||||
}
|
||||
idx += 1
|
||||
}
|
||||
|
||||
visibleNodesToUse.remove(at: 0)
|
||||
return visibleNodesToUse
|
||||
}
|
||||
|
||||
// Area Measurements
|
||||
|
||||
fileprivate func rectForRow(row: Int) -> NSRect {
|
||||
let rectBounds = bounds
|
||||
return NSRect(x: rectBounds.origin.x + LayoutInfo.OutlineBorderLineWidth,
|
||||
y: rectBounds.size.height - LayoutInfo.OutlineRowHeight * CGFloat(row + 1) - (LayoutInfo.OutlineBorderLineWidth),
|
||||
width: rectBounds.size.width - 2 * LayoutInfo.OutlineBorderLineWidth,
|
||||
height: LayoutInfo.OutlineRowHeight)
|
||||
}
|
||||
|
||||
fileprivate func textRectForRow(row: Int) -> NSRect {
|
||||
var textRect = NSRect.zero
|
||||
if let node = nodeAtRow(row: row) {
|
||||
let rowRect = rectForRow(row: row)
|
||||
textRect = NSRect(x: rowRect.origin.x + CGFloat(node.depth) * LayoutInfo.OutlineIndentationSize,
|
||||
y: rowRect.origin.y,
|
||||
width: rowRect.size.width,
|
||||
height: rowRect.size.height)
|
||||
}
|
||||
return textRect
|
||||
}
|
||||
|
||||
fileprivate func disclosureTriangleRectForRow(row: Int) -> NSRect {
|
||||
let textRect = textRectForRow(row: row)
|
||||
return NSRect(x: textRect.origin.x - LayoutInfo.OutlineIndentationSize + (LayoutInfo.OutlineBorderLineWidth * 1.5),
|
||||
y: textRect.origin.y - LayoutInfo.OutlineBorderLineWidth,
|
||||
width: LayoutInfo.OutlineIndentationSize,
|
||||
height: textRect.size.height)
|
||||
}
|
||||
|
||||
fileprivate func rect(row: Int) -> NSRect {
|
||||
let rowBounds = bounds
|
||||
return NSRect(x: rowBounds.origin.x + LayoutInfo.OutlineBorderLineWidth,
|
||||
y: rowBounds.size.height - LayoutInfo.OutlineRowHeight * CGFloat(row + 1) - (LayoutInfo.OutlineBorderLineWidth),
|
||||
width: rowBounds.size.width - 2 * LayoutInfo.OutlineBorderLineWidth,
|
||||
height: LayoutInfo.OutlineRowHeight)
|
||||
}
|
||||
|
||||
// MARK: - Expansion
|
||||
|
||||
fileprivate func setExpandedStatus(expanded: Bool, node: OutlineViewNode) {
|
||||
if !node.children.isEmpty {
|
||||
node.expanded = expanded
|
||||
selectedRow = rowForNode(node: node)
|
||||
|
||||
// Post a notification to let accessibility clients know a row has expanded or collapsed.
|
||||
// With a screen reader, for example, this could be announced as "row 1 expanded" or "row 2 collapsed"
|
||||
if node.expanded {
|
||||
NSAccessibilityPostNotification(accessibilityElementForNode(node: node), NSAccessibilityNotificationName.rowExpanded)
|
||||
} else {
|
||||
NSAccessibilityPostNotification(accessibilityElementForNode(node: node), NSAccessibilityNotificationName.rowCollapsed)
|
||||
}
|
||||
// Post a notification to let accessibility clients know the row count has changed.
|
||||
// With a screen reader, for example, this could be announced as "2 rows added".
|
||||
NSAccessibilityPostNotification(self, NSAccessibilityNotificationName.rowCountChanged)
|
||||
}
|
||||
}
|
||||
|
||||
func setExpandedStatus(expanded: Bool, rowIndex: Int) {
|
||||
let node = nodeAtRow(row: rowIndex)
|
||||
if node?.expanded != expanded {
|
||||
setExpandedStatus(expanded: expanded, node: node!)
|
||||
}
|
||||
}
|
||||
|
||||
override func keyDown(with event: NSEvent) {
|
||||
// We allow up/down arrow keys to change the current selection, left/right arrow keys to expand/collapse.
|
||||
guard event.modifierFlags.contains(.numericPad),
|
||||
let charactersIgnoringModifiers = event.charactersIgnoringModifiers, charactersIgnoringModifiers.characters.count == 1,
|
||||
let char = charactersIgnoringModifiers.characters.first
|
||||
else {
|
||||
super.keyDown(with: event)
|
||||
return
|
||||
}
|
||||
|
||||
switch char {
|
||||
case Character(NSDownArrowFunctionKey)!:
|
||||
selectedRow += 1
|
||||
case Character(NSUpArrowFunctionKey)!:
|
||||
selectedRow -= 1
|
||||
case Character(NSLeftArrowFunctionKey)!, Character(NSRightArrowFunctionKey)!:
|
||||
toggleExpandedStatusForNode(node: selectedNode())
|
||||
default: break
|
||||
}
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
// MARK: - Drawing
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
// Draw the outline background.
|
||||
NSColor.white.set()
|
||||
bounds.fill()
|
||||
|
||||
// Draw the outline's background and border.
|
||||
let outline = NSBezierPath(rect: bounds)
|
||||
NSColor.white.set()
|
||||
outline.lineWidth = 2.0
|
||||
outline.fill()
|
||||
NSColor.lightGray.set()
|
||||
outline.stroke()
|
||||
|
||||
// Draw the selected row.
|
||||
if selectedRow >= 0 {
|
||||
// Decide the fill color based on first responder status.
|
||||
let fillColor = window?.firstResponder == self ? NSColor.alternateSelectedControlColor : NSColor.secondarySelectedControlColor
|
||||
fillColor.set()
|
||||
let rowRect = rectForRow(row: selectedRow)
|
||||
rowRect.fill()
|
||||
}
|
||||
|
||||
// Draw each row item.
|
||||
for rowidx in 0..<visibleNodes().count {
|
||||
// Draw the row text.
|
||||
let node = visibleNodes()[rowidx]
|
||||
let textRect = textRectForRow(row: rowidx)
|
||||
|
||||
// Choose the right color based on first responder status and the selected row.
|
||||
let textColor = (window?.firstResponder == self && selectedRow == rowidx) ? NSColor.white : NSColor.black
|
||||
|
||||
let textAttributes = [ NSAttributedStringKey.font: NSFont.systemFont(ofSize: NSFont.systemFontSize),
|
||||
NSAttributedStringKey.foregroundColor: textColor ]
|
||||
node.name.draw(in: textRect, withAttributes:textAttributes)
|
||||
|
||||
// Draw the row disclosure triangle.
|
||||
if !node.children.isEmpty {
|
||||
let disclosureRect = disclosureTriangleRectForRow(row: rowidx)
|
||||
let disclosureText = node.expanded ? "▼" : "►"
|
||||
disclosureText.draw(in: disclosureRect, withAttributes:nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Events
|
||||
|
||||
// Used by accessibilityPerformPress or mouseUp functions to change the expanded state of each outline item.
|
||||
fileprivate func toggleExpandedStatusForNode(node: OutlineViewNode) {
|
||||
setExpandedStatus(expanded: !node.expanded, node: node)
|
||||
}
|
||||
|
||||
override func mouseDown(with event: NSEvent) {
|
||||
let point = convert(event.locationInWindow, from: nil)
|
||||
mouseDownRow = rowForPoint(point: point)
|
||||
let disclosureTriangleRect = disclosureTriangleRectForRow(row: mouseDownRow)
|
||||
mouseDownInDisclosureTriangle = disclosureTriangleRect.contains(point)
|
||||
}
|
||||
|
||||
override func mouseUp(with event: NSEvent) {
|
||||
let point = convert(event.locationInWindow, from: nil)
|
||||
let mouseUpRow = rowForPoint(point: point)
|
||||
if mouseDownRow == mouseUpRow {
|
||||
let disclosureTriangleRect = disclosureTriangleRectForRow(row: mouseUpRow)
|
||||
let isMouseUpInDisclosureTriangle = disclosureTriangleRect.contains(point)
|
||||
|
||||
if mouseDownInDisclosureTriangle && isMouseUpInDisclosureTriangle {
|
||||
let selectedNode = nodeAtRow(row: mouseUpRow)
|
||||
toggleExpandedStatusForNode(node: selectedNode!)
|
||||
} else {
|
||||
selectedRow = mouseUpRow
|
||||
}
|
||||
needsDisplay = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension CustomOutlineView {
|
||||
|
||||
// MARK: First Responder
|
||||
|
||||
// Set to allow keyDown to be called.
|
||||
override var acceptsFirstResponder: Bool { return true }
|
||||
|
||||
override func becomeFirstResponder() -> Bool {
|
||||
let didBecomeFirstResponder = super.becomeFirstResponder()
|
||||
if didBecomeFirstResponder {
|
||||
setKeyboardFocusRingNeedsDisplay(bounds)
|
||||
}
|
||||
needsDisplay = true
|
||||
return didBecomeFirstResponder
|
||||
}
|
||||
|
||||
override func resignFirstResponder() -> Bool {
|
||||
let didResignFirstResponder = super.resignFirstResponder()
|
||||
if didResignFirstResponder {
|
||||
setKeyboardFocusRingNeedsDisplay(bounds)
|
||||
}
|
||||
needsDisplay = true
|
||||
return didResignFirstResponder
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension CustomOutlineView {
|
||||
|
||||
// MARK: Accessibility Utilities
|
||||
|
||||
@objc
|
||||
func accessibilityElementForNode(node: OutlineViewNode) -> NSAccessibilityElement {
|
||||
var rowElement = CustomOutlineViewAccessibilityRowElement()
|
||||
|
||||
if let rowElementTarget = accessibilityRowElements[node] {
|
||||
guard let rowElementCheck = rowElementTarget as? CustomOutlineViewAccessibilityRowElement else { return rowElement }
|
||||
rowElement = rowElementCheck
|
||||
} else {
|
||||
rowElement = CustomOutlineViewAccessibilityRowElement()
|
||||
rowElement.setAccessibilityParent(self)
|
||||
accessibilityRowElements[node] = rowElement
|
||||
}
|
||||
|
||||
let row = rowForNode(node: node)
|
||||
let rowRect = rect(row: row)
|
||||
let disclosureTriangleRect = disclosureTriangleRectForRow(row: row)
|
||||
let disclosureTriangleCenterPoint = NSPoint(x: disclosureTriangleRect.midX, y: disclosureTriangleRect.midY)
|
||||
|
||||
rowElement.setAccessibilityLabel(node.name)
|
||||
rowElement.setAccessibilityFrameInParentSpace(rowRect)
|
||||
rowElement.setAccessibilityIndex(row)
|
||||
rowElement.setAccessibilityDisclosed(node.expanded)
|
||||
rowElement.setAccessibilityDisclosureLevel(node.depth)
|
||||
rowElement.disclosureTriangleCenterPoint = disclosureTriangleCenterPoint
|
||||
rowElement.canDisclose = !node.children.isEmpty
|
||||
|
||||
return rowElement
|
||||
}
|
||||
|
||||
// MARK: NSAccessibility
|
||||
|
||||
override func accessibilityLabel() -> String? {
|
||||
return NSLocalizedString("chemical property", comment: "accessibility label for the outline")
|
||||
}
|
||||
|
||||
override func accessibilityPerformPress() -> Bool {
|
||||
// User did control-option-space keyboard shortcut.
|
||||
toggleExpandedStatusForNode(node: selectedNode())
|
||||
needsDisplay = true
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|