SwiftExtension // Backport the TextEditor to macOS 10.15 Catalina.
- This TextEditorEX is much faster than Apple official TextEditor for SwiftUI.
This commit is contained in:
parent
cec578e3dd
commit
e163c63343
|
@ -80,3 +80,83 @@ public struct VisualEffectView: NSViewRepresentable {
|
||||||
visualEffectView.blendingMode = blendingMode
|
visualEffectView.blendingMode = blendingMode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - TextEditor for macOS 10.15 Catalina
|
||||||
|
|
||||||
|
// Ref: https://stackoverflow.com/a/63761738/4162914
|
||||||
|
|
||||||
|
@available(macOS 10.15, *)
|
||||||
|
/// A much faster alternative than Apple official TextEditor.
|
||||||
|
public struct TextEditorEX: NSViewRepresentable {
|
||||||
|
@Binding var text: String
|
||||||
|
|
||||||
|
public init(text: Binding<String>) {
|
||||||
|
_text = text
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeNSView(context: Context) -> NSScrollView {
|
||||||
|
context.coordinator.createTextViewStack()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateNSView(_ nsView: NSScrollView, context _: Context) {
|
||||||
|
if let textArea = nsView.documentView as? NSTextView, textArea.string != self.text {
|
||||||
|
textArea.string = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeCoordinator() -> Coordinator {
|
||||||
|
Coordinator(text: $text)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Coordinator: NSObject, NSTextViewDelegate {
|
||||||
|
public var text: Binding<String>
|
||||||
|
|
||||||
|
public init(text: Binding<String>) {
|
||||||
|
self.text = text
|
||||||
|
}
|
||||||
|
|
||||||
|
public func textView(_ textView: NSTextView, shouldChangeTextIn range: NSRange, replacementString text: String?)
|
||||||
|
-> Bool
|
||||||
|
{
|
||||||
|
defer {
|
||||||
|
self.text.wrappedValue = (textView.string as NSString).replacingCharacters(in: range, with: text!)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate lazy var textStorage = NSTextStorage()
|
||||||
|
fileprivate lazy var layoutManager = NSLayoutManager()
|
||||||
|
fileprivate lazy var textContainer = NSTextContainer()
|
||||||
|
fileprivate lazy var textView: NSTextView = {
|
||||||
|
let result = NSTextView(frame: CGRect(), textContainer: textContainer)
|
||||||
|
result.font = NSFont.systemFont(ofSize: 13, weight: .regular)
|
||||||
|
result.allowsUndo = true
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
fileprivate lazy var scrollview = NSScrollView()
|
||||||
|
|
||||||
|
public func createTextViewStack() -> NSScrollView {
|
||||||
|
let contentSize = scrollview.contentSize
|
||||||
|
|
||||||
|
textContainer.containerSize = CGSize(width: contentSize.width, height: CGFloat.greatestFiniteMagnitude)
|
||||||
|
textContainer.widthTracksTextView = true
|
||||||
|
|
||||||
|
textView.minSize = CGSize(width: 0, height: 0)
|
||||||
|
textView.maxSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
|
||||||
|
textView.isVerticallyResizable = true
|
||||||
|
textView.frame = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height)
|
||||||
|
textView.autoresizingMask = [.width]
|
||||||
|
textView.delegate = self
|
||||||
|
|
||||||
|
scrollview.borderType = .noBorder
|
||||||
|
scrollview.hasVerticalScroller = true
|
||||||
|
scrollview.documentView = textView
|
||||||
|
|
||||||
|
textStorage.addLayoutManager(layoutManager)
|
||||||
|
layoutManager.addTextContainer(textContainer)
|
||||||
|
|
||||||
|
return scrollview
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue