Skip to content

Commit bb9fe40

Browse files
committed
feat: enhance accessibility support in STTextView
The commit extends NSAccessibilityProtocol implementation in STTextView by adding support for NSAccessibilityStaticText and NSAccessibilityNavigableStaticText protocols. It implements frame, line positioning, and range methods to improve screen reader compatibility and navigation capabilities within text content.
1 parent 9ead4f9 commit bb9fe40

File tree

1 file changed

+63
-22
lines changed

1 file changed

+63
-22
lines changed

Sources/STTextViewAppKit/STTextView+NSAccessibilityProtocol.swift

+63-22
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// https://github.com/krzyzanowskim/STTextView/blob/main/LICENSE.md
33

44
import AppKit
5+
import STTextKitPlus
56

7+
/// NSAccessibilityProtocol
68
extension STTextView {
79

810
open override func isAccessibilityElement() -> Bool {
@@ -25,21 +27,26 @@ extension STTextView {
2527
NSLocalizedString("Text Editor", comment: "")
2628
}
2729

28-
open override func accessibilityValue() -> Any? {
29-
text
30+
open override func accessibilityNumberOfCharacters() -> Int {
31+
text?.count ?? 0
3032
}
3133

32-
open override func setAccessibilityValue(_ accessibilityValue: Any?) {
33-
guard let string = accessibilityValue as? String else {
34-
return
35-
}
34+
open override func accessibilitySelectedText() -> String? {
35+
textLayoutManager.textSelectionsString()
36+
}
3637

37-
self.text = string
38+
open override func accessibilitySelectedTextRange() -> NSRange {
39+
selectedRange()
3840
}
3941

40-
open override func accessibilityAttributedString(for range: NSRange) -> NSAttributedString? {
41-
attributedSubstring(forProposedRange: range, actualRange: nil)
42+
open override func isAccessibilityFocused() -> Bool {
43+
isFirstResponder && isSelectable
4244
}
45+
}
46+
47+
extension STTextView {
48+
49+
// NSAccessibilityStaticText
4350

4451
open override func accessibilityVisibleCharacterRange() -> NSRange {
4552
if let viewportRange = textLayoutManager.textViewportLayoutController.viewportRange {
@@ -49,27 +56,61 @@ extension STTextView {
4956
return NSRange()
5057
}
5158

52-
open override func accessibilityString(for range: NSRange) -> String? {
53-
attributedSubstring(forProposedRange: range, actualRange: nil)?.string
59+
open override func setAccessibilitySelectedTextRange(_ accessibilitySelectedTextRange: NSRange) {
60+
guard let textRange = NSTextRange(accessibilitySelectedTextRange, in: textContentManager) else {
61+
assertionFailure()
62+
return
63+
}
64+
setSelectedTextRange(textRange, updateLayout: true)
5465
}
5566

56-
open override func accessibilityNumberOfCharacters() -> Int {
57-
text?.count ?? 0
67+
open override func accessibilityAttributedString(for range: NSRange) -> NSAttributedString? {
68+
attributedSubstring(forProposedRange: range, actualRange: nil)
5869
}
5970

60-
open override func accessibilitySelectedText() -> String? {
61-
textLayoutManager.textSelectionsString()
71+
open override func accessibilityValue() -> Any? {
72+
text
6273
}
6374

64-
open override func accessibilitySelectedTextRange() -> NSRange {
65-
selectedRange()
75+
open override func setAccessibilityValue(_ accessibilityValue: Any?) {
76+
guard let string = accessibilityValue as? String else {
77+
return
78+
}
79+
80+
self.text = string
6681
}
6782

68-
open override func setAccessibilitySelectedTextRange(_ accessibilitySelectedTextRange: NSRange) {
69-
if let textRange = NSTextRange(accessibilitySelectedTextRange, in: textContentManager) {
70-
setSelectedTextRange(textRange, updateLayout: true)
71-
} else {
72-
assertionFailure()
83+
// NSAccessibilityNavigableStaticText
84+
85+
open override func accessibilityFrame(for range: NSRange) -> NSRect {
86+
guard let textRange = NSTextRange(range, in: textContentManager) else {
87+
return .zero
88+
}
89+
return textLayoutManager.textSegmentFrame(in: textRange, type: .standard) ?? .zero
90+
}
91+
92+
open override func accessibilityLine(for index: Int) -> Int {
93+
guard let location = textContentManager.location(at: index),
94+
let position = textContentManager.position(location)
95+
else {
96+
return 0
97+
}
98+
return position.row
99+
}
100+
101+
open override func accessibilityRange(forLine line: Int) -> NSRange {
102+
guard let location = textContentManager.location(line: line),
103+
let textElement = textContentManager.textElements(for: NSTextRange(location: location)).first,
104+
let textElementRange = textElement.elementRange
105+
else {
106+
return .notFound
73107
}
108+
109+
return NSRange(textElementRange, in: textContentManager)
74110
}
111+
112+
open override func accessibilityString(for range: NSRange) -> String? {
113+
attributedSubstring(forProposedRange: range, actualRange: nil)?.string
114+
}
115+
75116
}

0 commit comments

Comments
 (0)