Files
vorleser/Vorleser-macOS/MacReadingTextView.swift
2026-03-13 22:29:10 +01:00

67 lines
2.0 KiB
Swift

import SwiftUI
import AppKit
import VorleserKit
struct MacReadingTextView: NSViewRepresentable {
let text: String
let highlightedRange: Range<Int>?
let onClickCharacter: (CharacterOffset) -> Void
func makeNSView(context: Context) -> NSScrollView {
let scrollView = NSTextView.scrollableTextView()
let textView = scrollView.documentView as! NSTextView
textView.isEditable = false
textView.isSelectable = false
textView.font = .preferredFont(forTextStyle: .body)
textView.textContainerInset = NSSize(width: 16, height: 16)
let click = NSClickGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleClick(_:)))
textView.addGestureRecognizer(click)
context.coordinator.textView = textView
return scrollView
}
func updateNSView(_ scrollView: NSScrollView, context: Context) {
let textView = scrollView.documentView as! NSTextView
let attributed = NSMutableAttributedString(
string: text,
attributes: [
.font: NSFont.preferredFont(forTextStyle: .body),
.foregroundColor: NSColor.textColor,
]
)
if let range = highlightedRange,
range.lowerBound >= 0,
range.upperBound <= text.count {
let nsRange = NSRange(location: range.lowerBound, length: range.upperBound - range.lowerBound)
attributed.addAttribute(.backgroundColor, value: NSColor.systemYellow.withAlphaComponent(0.3), range: nsRange)
}
textView.textStorage?.setAttributedString(attributed)
}
func makeCoordinator() -> Coordinator {
Coordinator(onClickCharacter: onClickCharacter)
}
class Coordinator: NSObject {
weak var textView: NSTextView?
let onClickCharacter: (CharacterOffset) -> Void
init(onClickCharacter: @escaping (CharacterOffset) -> Void) {
self.onClickCharacter = onClickCharacter
}
@objc func handleClick(_ gesture: NSClickGestureRecognizer) {
guard let textView else { return }
let point = gesture.location(in: textView)
let characterIndex = textView.characterIndexForInsertion(at: point)
if characterIndex < textView.string.count {
onClickCharacter(characterIndex)
}
}
}
}