Skip to content

Commit

Permalink
Unify common API under STTextViewProtocol
Browse files Browse the repository at this point in the history
  • Loading branch information
krzyzanowskim committed Jul 31, 2024
1 parent 5dc8233 commit 453421f
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Sources/STTextViewAppKit/STTextFinderClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ final class STTextFinderClient: NSObject, NSTextFinderClient {
weak var textView: STTextView?

var string: String {
textView?.string ?? ""
textView?.text ?? ""
}

func stringLength() -> Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ extension STTextView {
}

open override func accessibilityValue() -> Any? {
string
text
}

open override func setAccessibilityValue(_ accessibilityValue: Any?) {
guard let string = accessibilityValue as? String else {
return
}

self.string = string
self.text = string
}

open override func accessibilityAttributedString(for range: NSRange) -> NSAttributedString? {
Expand All @@ -54,7 +54,7 @@ extension STTextView {
}

open override func accessibilityNumberOfCharacters() -> Int {
string.count
text?.count ?? 0
}

open override func accessibilitySelectedText() -> String? {
Expand Down
35 changes: 29 additions & 6 deletions Sources/STTextViewAppKit/STTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import STTextViewCommon
import AVFoundation

/// A TextKit2 text view without NSTextView baggage
@objc open class STTextView: NSView, NSTextInput, NSTextContent {
@objc open class STTextView: NSView, NSTextInput, NSTextContent, STTextViewProtocol {
/// Posted before an object performs any operation that changes characters or formatting attributes.
public static let textWillChangeNotification = NSNotification.Name("NSTextWillChangeNotification")

Expand Down Expand Up @@ -219,7 +219,7 @@ import AVFoundation
///
/// For performance reasons, this value is the current backing store of the text object.
/// If you want to maintain a snapshot of this as you manipulate the text storage, you should make a copy of the appropriate substring.
@objc public var string: String {
@objc public var text: String? {
set {
let prevLocation = textLayoutManager.insertionPointLocations.first

Expand All @@ -238,9 +238,26 @@ import AVFoundation
}
}

/// Replaces the receiver’s entire contents with the characters and attributes of the given attributed string.
@objc public func setAttributedString(_ attributedString: NSAttributedString) {
setString(attributedString)
/// The styled text that the text view displays.
///
/// Assigning a new value to this property also replaces the value of the `text` property with the same string data, albeit without any formatting information. In addition, the `font`, `textColor`, and `textAlignment` properties are updated to reflect the typing attributes of the text view.
@objc public var attributedText: NSAttributedString? {
set {
let prevLocation = textLayoutManager.insertionPointLocations.first

setString(newValue)

if let prevLocation {
// restore selection location
setSelectedTextRange(NSTextRange(location: prevLocation))
} else {
// or try to set at the begining of the document
setSelectedTextRange(NSTextRange(location: textContentManager.documentRange.location))
}
}
get {
textContentManager.attributedString(in: nil)
}
}

/// A Boolean that controls whether the text container adjusts the width of its bounding rectangle when its text view resizes.
Expand Down Expand Up @@ -425,7 +442,13 @@ import AVFoundation

/// The text view's text container
public var textContainer: NSTextContainer {
textLayoutManager.textContainer!
get {
textLayoutManager.textContainer!
}

set {
textLayoutManager.textContainer = newValue
}
}

/// Content view. Layout fragments content.
Expand Down
60 changes: 60 additions & 0 deletions Sources/STTextViewCommon/STTextViewProtocol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Created by Marcin Krzyzanowski
// https://github.com/krzyzanowskim/STTextView/blob/main/LICENSE.md

#if canImport(AppKit) && !targetEnvironment(macCatalyst)
import AppKit
#endif
#if canImport(UIKit)
import UIKit
#endif

/// A common public interface for TextView
package protocol STTextViewProtocol {
associatedtype RulerView
associatedtype Color
associatedtype Font
associatedtype Delegate

static var didChangeSelectionNotification: NSNotification.Name { get }
static var textWillChangeNotification: NSNotification.Name { get }
static var textDidChangeNotification: NSNotification.Name { get }

var textLayoutManager: NSTextLayoutManager { get }
var textContentManager: NSTextContentManager { get }
var textContainer: NSTextContainer { get set }
var widthTracksTextView: Bool { get set }
var isHorizontallyResizable: Bool { get set }
var heightTracksTextView: Bool { get set }
var isVerticallyResizable: Bool { get set }
var highlightSelectedLine: Bool { get set }
var showLineNumbers: Bool { get set }
var selectedLineHighlightColor: Color { get set}
var font: Font? { get set }
var textColor: Color? { get set }
var text: String? { get set }
var attributedText: NSAttributedString? { get set }
var isEditable: Bool { get set }
var isSelectable: Bool { get set }
var defaultParagraphStyle: NSParagraphStyle? { get set }
var typingAttributes: [NSAttributedString.Key: Any] { get set }
var gutterView: RulerView? { get }

var textDelegate: Delegate? { get set }

func toggleRuler(_ sender: Any?)
var isRulerVisible: Bool { get set }
func setSelectedTextRange(_ textRange: NSTextRange, updateLayout: Bool)

func addAttributes(_ attrs: [NSAttributedString.Key: Any], range: NSRange, updateLayout: Bool)
func addAttributes(_ attrs: [NSAttributedString.Key: Any], range: NSTextRange, updateLayout: Bool)

func setAttributes(_ attrs: [NSAttributedString.Key: Any], range: NSRange, updateLayout: Bool)
func setAttributes(_ attrs: [NSAttributedString.Key: Any], range: NSTextRange, updateLayout: Bool)

func removeAttribute(_ attribute: NSAttributedString.Key, range: NSRange, updateLayout: Bool)
func removeAttribute(_ attribute: NSAttributedString.Key, range: NSTextRange, updateLayout: Bool)

func shouldChangeText(in affectedTextRange: NSTextRange, replacementString: String?) -> Bool
func replaceCharacters(in range: NSTextRange, with string: String)
func insertText(_ string: Any, replacementRange: NSRange)
}
4 changes: 2 additions & 2 deletions Sources/STTextViewSwiftUIAppKit/TextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private struct TextViewRepresentable: NSViewRepresentable {
textView.setSelectedRange(NSRange())

context.coordinator.isUpdating = true
textView.setAttributedString(NSAttributedString(styledAttributedString(textView.typingAttributes)))
textView.attributedText = NSAttributedString(styledAttributedString(textView.typingAttributes))
context.coordinator.isUpdating = false

for plugin in plugins {
Expand All @@ -102,7 +102,7 @@ private struct TextViewRepresentable: NSViewRepresentable {
do {
context.coordinator.isUpdating = true
if context.coordinator.isDidChangeText == false {
textView.setAttributedString(NSAttributedString(styledAttributedString(textView.typingAttributes)))
textView.attributedText = NSAttributedString(styledAttributedString(textView.typingAttributes))
}
context.coordinator.isUpdating = false
context.coordinator.isDidChangeText = false
Expand Down
6 changes: 3 additions & 3 deletions Sources/STTextViewUIKit/STTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import UIKit
import STTextKitPlus
import STTextViewCommon

@objc open class STTextView: UIScrollView {
@objc open class STTextView: UIScrollView, STTextViewProtocol {

/// Sent when the selection range of characters changes.
public static let didChangeSelectionNotification = STTextLayoutManager.didChangeSelectionNotification
Expand Down Expand Up @@ -722,7 +722,7 @@ import STTextViewCommon
)
}

open func textWillChange(_ sender: Any?) {
public func textWillChange(_ sender: Any?) {
inputDelegate?.textWillChange(self)

let notification = Notification(name: Self.textWillChangeNotification, object: self, userInfo: nil)
Expand All @@ -735,7 +735,7 @@ import STTextViewCommon
///
/// Invoked automatically at the end of a series of changes, this method posts an `textDidChangeNotification` to the default notification center, which also results in the delegate receiving `textViewDidChangeText(_:)` message.
/// Subclasses implementing methods that change their text should invoke this method at the end of those methods.
open func didChangeText() {
public func didChangeText() {
let notification = Notification(name: Self.textDidChangeNotification, object: self, userInfo: nil)
NotificationCenter.default.post(notification)

Expand Down
10 changes: 5 additions & 5 deletions TextEdit/Mac/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class ViewController: NSViewController {
textView.typingAttributes[.paragraphStyle] = paragraph

textView.font = NSFont.monospacedSystemFont(ofSize: 14, weight: .regular)
textView.string = try! String(contentsOf: Bundle.main.url(forResource: "content", withExtension: "txt")!)
textView.text = try! String(contentsOf: Bundle.main.url(forResource: "content", withExtension: "txt")!)
textView.isHorizontallyResizable = false // wrap
textView.highlightSelectedLine = true
textView.isIncrementalSearchingEnabled = true
Expand All @@ -50,7 +50,7 @@ final class ViewController: NSViewController {

// add link to occurences of STTextView
do {
let str = textView.string
let str = textView.text!
var currentRange = str.startIndex..<str.endIndex
while let ocurrenceRange = str.range(of: "STTextView", range: currentRange) {
textView.addAttributes([.link: URL(string: "https://swift.best")! as NSURL], range: NSRange(ocurrenceRange, in: str))
Expand All @@ -59,7 +59,7 @@ final class ViewController: NSViewController {
}

do {
let str = textView.string
let str = textView.text!
var currentRange = str.startIndex..<str.endIndex
while let ocurrenceRange = str.range(of: "vim", range: currentRange) {
textView.addAttributes([.cursor: NSCursor.operationNotAllowed], range: NSRange(ocurrenceRange, in: str))
Expand Down Expand Up @@ -92,7 +92,7 @@ final class ViewController: NSViewController {
.foregroundColor: NSColor.controlAccentColor,
.font: NSFont.preferredFont(forTextStyle: .largeTitle)
],
range: NSRange(textView.string.linesRanges().first!, in: textView.string)
range: NSRange(textView.text!.linesRanges().first!, in: textView.text!)
)

updateCompletionsInBackground()
Expand All @@ -119,7 +119,7 @@ final class ViewController: NSViewController {
completionTask = Task(priority: .background) {
var arr: Set<String> = []

for await word in Tokenizer.words(textView.string) where !Task.isCancelled {
for await word in Tokenizer.words(textView.text ?? "") where !Task.isCancelled {
arr.insert(word.string)
}

Expand Down

0 comments on commit 453421f

Please sign in to comment.