forked from gonzalezreal/AttributedText
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAttributedTextImpl+macOS.swift
76 lines (64 loc) · 2.29 KB
/
AttributedTextImpl+macOS.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#if os(macOS)
import SwiftUI
extension AttributedTextImpl: NSViewRepresentable {
func makeNSView(context: Context) -> TextView {
let nsView = TextView(frame: .zero)
nsView.drawsBackground = false
nsView.textContainerInset = .zero
nsView.isEditable = false
nsView.isRichText = false
nsView.textContainer?.lineFragmentPadding = 0
// we are setting the container's width manually
nsView.textContainer?.widthTracksTextView = false
nsView.delegate = context.coordinator
return nsView
}
func updateNSView(_ nsView: TextView, context: Context) {
nsView.textStorage?.setAttributedString(attributedText)
nsView.maxLayoutWidth = maxLayoutWidth
nsView.textContainer?.maximumNumberOfLines = context.environment.lineLimit ?? 0
nsView.textContainer?.lineBreakMode = NSLineBreakMode(
truncationMode: context.environment.truncationMode
)
context.coordinator.openLink = onOpenLink ?? { context.environment.openURL($0) }
textSizeViewModel.didUpdateTextView(nsView)
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
}
extension AttributedTextImpl {
final class TextView: NSTextView {
var maxLayoutWidth: CGFloat {
get { textContainer?.containerSize.width ?? 0 }
set {
guard textContainer?.containerSize.width != newValue else { return }
textContainer?.containerSize.width = newValue
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: NSSize {
guard maxLayoutWidth > 0,
let textContainer = self.textContainer,
let layoutManager = self.layoutManager
else {
return super.intrinsicContentSize
}
layoutManager.ensureLayout(for: textContainer)
return layoutManager.usedRect(for: textContainer).size
}
}
final class Coordinator: NSObject, NSTextViewDelegate {
var openLink: ((URL) -> Void)?
func textView(_: NSTextView, clickedOnLink link: Any, at _: Int) -> Bool {
guard let openLink = self.openLink,
let url = (link as? URL) ?? (link as? String).flatMap(URL.init(string:))
else {
return false
}
openLink(url)
return true
}
}
}
#endif