Skip to content

Commit

Permalink
Use layout manager range
Browse files Browse the repository at this point in the history
  • Loading branch information
krzyzanowskim committed Feb 12, 2024
1 parent 3f74665 commit 17f366a
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 27 deletions.
4 changes: 2 additions & 2 deletions Sources/STTextView/STTextLayoutManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ private func testIfNeedsBoundsWorkaround() -> Bool {
textContentManager.attributedString = NSAttributedString(string: "01234567890123456789")

textContainer.lineFragmentPadding = 5
textLayoutManager.ensureLayout(for: textContentManager.documentRange)
textLayoutManager.ensureLayout(for: textLayoutManager.documentRange)
let bounds1 = textLayoutManager.usageBoundsForTextContainer

textContainer.lineFragmentPadding = 0
textLayoutManager.ensureLayout(for: textContentManager.documentRange)
textLayoutManager.ensureLayout(for: textLayoutManager.documentRange)
let bounds2 = textLayoutManager.usageBoundsForTextContainer

if bounds1.width == bounds2.width {
Expand Down
2 changes: 1 addition & 1 deletion Sources/STTextView/STTextView+InsertionPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ extension STTextView {
// because `textLayoutManager.enumerateTextLayoutFragments(from: nil, options: [.ensuresExtraLineFragment, .ensuresLayout, .estimatesSize])`
// returns unexpected value for extra line fragment height (return 14) that is not correct in the context,
// therefore for empty override height with value manually calculated from font + paragraph style
if textRange == textContentManager.documentRange, textRange.isEmpty {
if textRange == textLayoutManager.documentRange, textRange.isEmpty {
return CGRect(origin: selectionFrame.origin, size: CGSize(width: selectionFrame.width, height: typingLineHeight)).pixelAligned
}

Expand Down
6 changes: 3 additions & 3 deletions Sources/STTextView/STTextView+NSTextCheckingClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ extension STTextView: NSTextCheckingClient {

// If the specified range is {NSNotFound, 0}, then the receiver should replace it with the entire range of the document.
if adjRange == .notFound {
adjRange = NSRange(textContentManager.documentRange, in: textContentManager)
adjRange = NSRange(textLayoutManager.documentRange, in: textContentManager)
}

guard var adjRange = adjRange.clamped(NSRange(textContentManager.documentRange, in: textContentManager)) else {
guard var adjRange = adjRange.clamped(NSRange(textLayoutManager.documentRange, in: textContentManager)) else {
return nil
}

Expand Down Expand Up @@ -79,7 +79,7 @@ extension STTextView: NSTextCheckingClient {
}

// add (apply) spellcheck attributes from rendering attributes where annotations are saved
let offset = textContentManager.offset(from: textContentManager.documentRange.location, to: actualTextRange.location)
let offset = textContentManager.offset(from: textLayoutManager.documentRange.location, to: actualTextRange.location)
textLayoutManager.enumerateRenderingAttributes(in: actualTextRange, reverse: false) { textLayoutManager, attrs, attrTextRange in
for spellcheckAttributeKey in attrs.keys.filter({ textCheckingController.validAnnotations().contains($0) }) {
guard let value = attrs[spellcheckAttributeKey],
Expand Down
4 changes: 2 additions & 2 deletions Sources/STTextView/STTextView+NSTextInputClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ extension STTextView: NSTextInputClient {

@objc public func attributedSubstring(forProposedRange range: NSRange, actualRange: NSRangePointer?) -> NSAttributedString? {
// An implementation of this method should be prepared for range to be out of bounds.
let location = textContentManager.location(textContentManager.documentRange.location, offsetBy: range.location) ?? textContentManager.documentRange.location
let endLocation = textContentManager.location(textContentManager.documentRange.location, offsetBy: range.location + range.length) ?? textContentManager.documentRange.endLocation
let location = textLayoutManager.location(textLayoutManager.documentRange.location, offsetBy: range.location) ?? textLayoutManager.documentRange.location
let endLocation = textLayoutManager.location(textLayoutManager.documentRange.location, offsetBy: range.location + range.length) ?? textLayoutManager.documentRange.endLocation

guard let textRange = NSTextRange(location: location, end: endLocation), !textRange.isEmpty else {
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ extension STTextView: NSUserInterfaceValidations {
public func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool {
switch item.action {
case #selector(copy(_:)), #selector(cut(_:)), #selector(delete(_:)):
return !textContentManager.documentRange.isEmpty && !selectedRange().isEmpty
return !textLayoutManager.documentRange.isEmpty && !selectedRange().isEmpty
case #selector(selectAll(_:)):
return !textContentManager.documentRange.isEmpty
return !textLayoutManager.documentRange.isEmpty
case #selector(paste(_:)), #selector(pasteAsPlainText(_:)), #selector(pasteAsRichText(_:)):
return isEditable && NSPasteboard.general.string(forType: .string) != nil
case #selector(undo(_:)):
Expand All @@ -44,7 +44,7 @@ extension STTextView: NSUserInterfaceValidations {
case #selector(stopSpeaking(_:)):
return speechSynthesizer.isSpeaking
case #selector(startSpeaking(_:)):
return !textContentManager.documentRange.isEmpty
return !textLayoutManager.documentRange.isEmpty
case #selector(toggleRuler(_:)):
return usesRuler && enclosingScrollView?.hasHorizontalRuler == true || enclosingScrollView?.hasVerticalRuler == true
case #selector(toggleContinuousSpellChecking(_:)):
Expand Down
2 changes: 1 addition & 1 deletion Sources/STTextView/STTextView+Select.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extension STTextView {
}

public func setSelectedTextRange(_ textRange: NSTextRange, updateLayout: Bool = true) {
guard isSelectable, textRange.endLocation <= textContentManager.documentRange.endLocation else {
guard isSelectable, textRange.endLocation <= textLayoutManager.documentRange.endLocation else {
return
}

Expand Down
30 changes: 15 additions & 15 deletions Sources/STTextView/STTextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ import AVFoundation
@objc dynamic open var font: NSFont? {
get {
// if not empty, return a font at location 0
if !textContentManager.documentRange.isEmpty {
let location = textContentManager.documentRange.location
let endLocation = textContentManager.location(location, offsetBy: 1)
return textContentManager.attributedString(in: NSTextRange(location: location, end: endLocation))?.attribute(.font, at: 0, effectiveRange: nil) as? NSFont
if !textLayoutManager.documentRange.isEmpty {
let location = textLayoutManager.documentRange.location
let endLocation = textLayoutManager.location(location, offsetBy: 1)
return textLayoutManager.textContentManager?.attributedString(in: NSTextRange(location: location, end: endLocation))?.attribute(.font, at: 0, effectiveRange: nil) as? NSFont
}

// otherwise return current typing attribute
Expand All @@ -106,8 +106,8 @@ import AVFoundation
return
}

if !textContentManager.documentRange.isEmpty {
addAttributes([.font: newValue], range: textContentManager.documentRange)
if !textLayoutManager.documentRange.isEmpty {
addAttributes([.font: newValue], range: textLayoutManager.documentRange)
}

typingAttributes[.font] = newValue
Expand Down Expand Up @@ -179,15 +179,15 @@ import AVFoundation
}

internal func typingAttributes(at startLocation: NSTextLocation) -> [NSAttributedString.Key : Any] {
guard !textContentManager.documentRange.isEmpty else {
guard !textLayoutManager.documentRange.isEmpty else {
return typingAttributes
}

var attrs: [NSAttributedString.Key: Any] = [:]
// The attribute is derived from the previous (upstream) location,
// except for the beginning of the document where it from whatever is at location 0
let options: NSTextContentManager.EnumerationOptions = startLocation == textContentManager.documentRange.location ? [] : [.reverse]
let offsetDiff = startLocation == textContentManager.documentRange.location ? 0 : -1
let options: NSTextContentManager.EnumerationOptions = startLocation == textLayoutManager.documentRange.location ? [] : [.reverse]
let offsetDiff = startLocation == textLayoutManager.documentRange.location ? 0 : -1

textContentManager.enumerateTextElements(from: startLocation, options: options) { textElement in
if let textParagraph = textElement as? NSTextParagraph,
Expand Down Expand Up @@ -591,7 +591,7 @@ import AVFoundation
textCheckingController = NSTextCheckingController(client: self)

// Set insert point at the very beginning
setSelectedTextRange(NSTextRange(location: textContentManager.documentRange.location))
setSelectedTextRange(NSTextRange(location: textLayoutManager.documentRange.location))

postsBoundsChangedNotifications = true
postsFrameChangedNotifications = true
Expand Down Expand Up @@ -797,10 +797,10 @@ import AVFoundation
context.restoreGState()
}

if textContentManager.documentRange.isEmpty {
if textLayoutManager.documentRange.isEmpty {
// - empty document has no layout fragments, nothing, it's empt and has to be handled explicitly.
// - there's no layout fragment at the document endLocation (technically it's out of bounds), has to be handled explicitly.
if let selectionFrame = textLayoutManager.textSegmentFrame(at: textContentManager.documentRange.location, type: .standard) {
if let selectionFrame = textLayoutManager.textSegmentFrame(at: textLayoutManager.documentRange.location, type: .standard) {
drawHighlight(
in: CGRect(
origin: CGPoint(
Expand Down Expand Up @@ -886,15 +886,15 @@ import AVFoundation
if case .some(let string) = string {
switch string {
case let attributedString as NSAttributedString:
replaceCharacters(in: textContentManager.documentRange, with: attributedString, allowsTypingCoalescing: false)
replaceCharacters(in: textLayoutManager.documentRange, with: attributedString, allowsTypingCoalescing: false)
case let string as String:
replaceCharacters(in: textContentManager.documentRange, with: string, useTypingAttributes: true, allowsTypingCoalescing: false)
replaceCharacters(in: textLayoutManager.documentRange, with: string, useTypingAttributes: true, allowsTypingCoalescing: false)
default:
assertionFailure()
return
}
} else if case .none = string {
replaceCharacters(in: textContentManager.documentRange, with: "", useTypingAttributes: true, allowsTypingCoalescing: false)
replaceCharacters(in: textLayoutManager.documentRange, with: "", useTypingAttributes: true, allowsTypingCoalescing: false)
}
}

Expand Down

0 comments on commit 17f366a

Please sign in to comment.