mirror of
https://github.com/writeas/writefreely-swiftui-multiplatform.git
synced 2024-11-15 01:11:02 +00:00
Add tweaked MacEditorTextView to project
This commit is contained in:
parent
076df6d5a0
commit
d333049cac
@ -22,6 +22,7 @@
|
||||
171BFDFB24D4AF8300888236 /* CollectionListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171BFDF924D4AF8300888236 /* CollectionListView.swift */; };
|
||||
173E19D1254318F600440F0F /* RemoteChangePromptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 173E19D0254318F600440F0F /* RemoteChangePromptView.swift */; };
|
||||
173E19E3254329CC00440F0F /* PostTextEditingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 173E19E2254329CC00440F0F /* PostTextEditingView.swift */; };
|
||||
17466626256C0D0600629997 /* MacEditorTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17466625256C0D0600629997 /* MacEditorTextView.swift */; };
|
||||
17480CA5251272EE00EB7765 /* Bundle+AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17480CA4251272EE00EB7765 /* Bundle+AppVersion.swift */; };
|
||||
17480CA6251272EE00EB7765 /* Bundle+AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17480CA4251272EE00EB7765 /* Bundle+AppVersion.swift */; };
|
||||
174D313224EC2831006CA9EE /* WriteFreelyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 174D313124EC2831006CA9EE /* WriteFreelyModel.swift */; };
|
||||
@ -123,6 +124,7 @@
|
||||
171BFDF924D4AF8300888236 /* CollectionListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionListView.swift; sourceTree = "<group>"; };
|
||||
173E19D0254318F600440F0F /* RemoteChangePromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteChangePromptView.swift; sourceTree = "<group>"; };
|
||||
173E19E2254329CC00440F0F /* PostTextEditingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostTextEditingView.swift; sourceTree = "<group>"; };
|
||||
17466625256C0D0600629997 /* MacEditorTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacEditorTextView.swift; sourceTree = "<group>"; };
|
||||
17480CA4251272EE00EB7765 /* Bundle+AppVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+AppVersion.swift"; sourceTree = "<group>"; };
|
||||
174D313124EC2831006CA9EE /* WriteFreelyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteFreelyModel.swift; sourceTree = "<group>"; };
|
||||
1753F6AB24E431CC00309365 /* MacPreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacPreferencesView.swift; sourceTree = "<group>"; };
|
||||
@ -309,6 +311,7 @@
|
||||
children = (
|
||||
17A67CAE251A5DD7002F163D /* PostEditorView.swift */,
|
||||
17E5DF892543610700DCDC9B /* PostTextEditingView.swift */,
|
||||
17466625256C0D0600629997 /* MacEditorTextView.swift */,
|
||||
);
|
||||
path = PostEditor;
|
||||
sourceTree = "<group>";
|
||||
@ -744,6 +747,7 @@
|
||||
17480CA6251272EE00EB7765 /* Bundle+AppVersion.swift in Sources */,
|
||||
17C42E662509237800072984 /* PostListFilteredView.swift in Sources */,
|
||||
17120DAD24E1B99F002B9F6C /* AccountLoginView.swift in Sources */,
|
||||
17466626256C0D0600629997 /* MacEditorTextView.swift in Sources */,
|
||||
17E5DF8A2543610700DCDC9B /* PostTextEditingView.swift in Sources */,
|
||||
17C42E71250AAFD500072984 /* NSManagedObjectContext+ExecuteAndMergeChanges.swift in Sources */,
|
||||
1756AE7B24CB65DF00FD7257 /* PostListView.swift in Sources */,
|
||||
|
@ -7,12 +7,12 @@
|
||||
<key>WriteFreely-MultiPlatform (iOS).xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>WriteFreely-MultiPlatform (macOS).xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
|
206
macOS/PostEditor/MacEditorTextView.swift
Normal file
206
macOS/PostEditor/MacEditorTextView.swift
Normal file
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* Based on:
|
||||
*
|
||||
* MacEditorTextView
|
||||
* Copyright (c) Thiago Holanda 2020
|
||||
* https://twitter.com/tholanda
|
||||
*
|
||||
* MIT license
|
||||
*
|
||||
* See: https://gist.github.com/unnamedd/6e8c3fbc806b8deb60fa65d6b9affab0
|
||||
*/
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct MacEditorTextView: NSViewRepresentable {
|
||||
@Binding var text: String
|
||||
var isFirstResponder: Bool = false
|
||||
var isEditable: Bool = true
|
||||
var font: NSFont? = .systemFont(ofSize: 14, weight: .regular)
|
||||
|
||||
var onEditingChanged: () -> Void = {}
|
||||
var onCommit : () -> Void = {}
|
||||
var onTextChange : (String) -> Void = { _ in }
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(self)
|
||||
}
|
||||
|
||||
func makeNSView(context: Context) -> CustomTextView {
|
||||
let textView = CustomTextView(
|
||||
text: text,
|
||||
isEditable: isEditable,
|
||||
isFirstResponder: isFirstResponder,
|
||||
font: font
|
||||
)
|
||||
textView.delegate = context.coordinator
|
||||
|
||||
return textView
|
||||
}
|
||||
|
||||
func updateNSView(_ view: CustomTextView, context: Context) {
|
||||
view.text = text
|
||||
view.selectedRanges = context.coordinator.selectedRanges
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Coordinator
|
||||
|
||||
extension MacEditorTextView {
|
||||
|
||||
class Coordinator: NSObject, NSTextViewDelegate {
|
||||
var parent: MacEditorTextView
|
||||
var selectedRanges: [NSValue] = []
|
||||
var didBecomeFirstResponder: Bool = false
|
||||
|
||||
init(_ parent: MacEditorTextView) {
|
||||
self.parent = parent
|
||||
}
|
||||
|
||||
func textDidBeginEditing(_ notification: Notification) {
|
||||
guard let textView = notification.object as? NSTextView else {
|
||||
return
|
||||
}
|
||||
|
||||
self.parent.text = textView.string
|
||||
self.parent.onEditingChanged()
|
||||
}
|
||||
|
||||
func textDidChange(_ notification: Notification) {
|
||||
guard let textView = notification.object as? NSTextView else {
|
||||
return
|
||||
}
|
||||
|
||||
self.parent.text = textView.string
|
||||
self.selectedRanges = textView.selectedRanges
|
||||
self.parent.onTextChange(textView.string)
|
||||
}
|
||||
|
||||
func textDidEndEditing(_ notification: Notification) {
|
||||
guard let textView = notification.object as? NSTextView else {
|
||||
return
|
||||
}
|
||||
|
||||
self.parent.text = textView.string
|
||||
self.parent.onCommit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CustomTextView
|
||||
|
||||
final class CustomTextView: NSView {
|
||||
private var isFirstResponder: Bool
|
||||
private var isEditable: Bool
|
||||
private var font: NSFont?
|
||||
|
||||
weak var delegate: NSTextViewDelegate?
|
||||
|
||||
var text: String {
|
||||
didSet {
|
||||
textView.string = text
|
||||
}
|
||||
}
|
||||
|
||||
var selectedRanges: [NSValue] = [] {
|
||||
didSet {
|
||||
guard selectedRanges.count > 0 else {
|
||||
return
|
||||
}
|
||||
|
||||
textView.selectedRanges = selectedRanges
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var scrollView: NSScrollView = {
|
||||
let scrollView = NSScrollView()
|
||||
scrollView.drawsBackground = true
|
||||
scrollView.borderType = .noBorder
|
||||
scrollView.hasVerticalScroller = true
|
||||
scrollView.hasHorizontalRuler = false
|
||||
scrollView.autoresizingMask = [.width, .height]
|
||||
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
return scrollView
|
||||
}()
|
||||
|
||||
private lazy var textView: NSTextView = {
|
||||
let contentSize = scrollView.contentSize
|
||||
let textStorage = NSTextStorage()
|
||||
|
||||
|
||||
let layoutManager = NSLayoutManager()
|
||||
textStorage.addLayoutManager(layoutManager)
|
||||
|
||||
|
||||
let textContainer = NSTextContainer(containerSize: scrollView.frame.size)
|
||||
textContainer.widthTracksTextView = true
|
||||
textContainer.containerSize = NSSize(
|
||||
width: contentSize.width,
|
||||
height: CGFloat.greatestFiniteMagnitude
|
||||
)
|
||||
|
||||
layoutManager.addTextContainer(textContainer)
|
||||
|
||||
|
||||
let textView = NSTextView(frame: .zero, textContainer: textContainer)
|
||||
textView.autoresizingMask = .width
|
||||
textView.backgroundColor = NSColor.textBackgroundColor
|
||||
textView.delegate = self.delegate
|
||||
textView.drawsBackground = true
|
||||
textView.font = self.font
|
||||
textView.isEditable = self.isEditable
|
||||
textView.isHorizontallyResizable = false
|
||||
textView.isVerticallyResizable = true
|
||||
textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
|
||||
textView.minSize = NSSize(width: 0, height: contentSize.height)
|
||||
textView.textColor = NSColor.labelColor
|
||||
|
||||
return textView
|
||||
}()
|
||||
|
||||
// MARK: - Init
|
||||
init(text: String, isEditable: Bool, isFirstResponder: Bool, font: NSFont?) {
|
||||
self.font = font
|
||||
self.isFirstResponder = isFirstResponder
|
||||
self.isEditable = isEditable
|
||||
self.text = text
|
||||
|
||||
super.init(frame: .zero)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
override func viewWillDraw() {
|
||||
super.viewWillDraw()
|
||||
|
||||
setupScrollViewConstraints()
|
||||
setupTextView()
|
||||
|
||||
if isFirstResponder {
|
||||
self.window?.makeFirstResponder(self.textView)
|
||||
}
|
||||
}
|
||||
|
||||
func setupScrollViewConstraints() {
|
||||
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
addSubview(scrollView)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
scrollView.topAnchor.constraint(equalTo: topAnchor),
|
||||
scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
||||
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||
scrollView.leadingAnchor.constraint(equalTo: leadingAnchor)
|
||||
])
|
||||
}
|
||||
|
||||
func setupTextView() {
|
||||
scrollView.documentView = textView
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user