diff --git a/Sources/Runestone/Library/DefaultStringAttributes.swift b/Sources/Runestone/Library/DefaultStringAttributes.swift new file mode 100644 index 000000000..630982e0f --- /dev/null +++ b/Sources/Runestone/Library/DefaultStringAttributes.swift @@ -0,0 +1,41 @@ +import Foundation +import UIKit + +struct DefaultStringAttributes { + private let textColor: UIColor + private let font: UIFont + private let kern: CGFloat + private let tabWidth: CGFloat + private let lineHeightMultiplier: CGFloat + + init( + textColor: UIColor, + font: UIFont, + kern: CGFloat, + tabWidth: CGFloat, + lineHeightMultiplier: CGFloat = 1 + ) { + self.textColor = textColor + self.font = font + self.kern = kern + self.tabWidth = tabWidth + self.lineHeightMultiplier = lineHeightMultiplier + } + + func apply(to attributedString: NSMutableAttributedString) { + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.tabStops = [] + paragraphStyle.defaultTabInterval = tabWidth + paragraphStyle.lineHeightMultiple = lineHeightMultiplier + let range = NSRange(location: 0, length: attributedString.length) + let attributes: [NSAttributedString.Key: Any] = [ + .foregroundColor: textColor, + .font: font, + .kern: kern as NSNumber, + .paragraphStyle: paragraphStyle + ] + attributedString.beginEditing() + attributedString.setAttributes(attributes, range: range) + attributedString.endEditing() + } +} diff --git a/Sources/Runestone/TextView/Core/TextInputView.swift b/Sources/Runestone/TextView/Core/TextInputView.swift index b6f61d0b8..a7b2f2c10 100644 --- a/Sources/Runestone/TextView/Core/TextInputView.swift +++ b/Sources/Runestone/TextView/Core/TextInputView.swift @@ -1623,9 +1623,7 @@ extension TextInputView: LineControllerStorageDelegate { // MARK: - LineControllerDelegate extension TextInputView: LineControllerDelegate { func lineSyntaxHighlighter(for lineController: LineController) -> LineSyntaxHighlighter? { - let syntaxHighlighter = languageMode.createLineSyntaxHighlighter() - syntaxHighlighter.kern = kern - return syntaxHighlighter + languageMode.createLineSyntaxHighlighter() } func lineControllerDidInvalidateLineWidthDuringAsyncSyntaxHighlight(_ lineController: LineController) { diff --git a/Sources/Runestone/TextView/LineController/LineController.swift b/Sources/Runestone/TextView/LineController/LineController.swift index ed3036d39..a837661ec 100644 --- a/Sources/Runestone/TextView/LineController/LineController.swift +++ b/Sources/Runestone/TextView/LineController/LineController.swift @@ -64,7 +64,7 @@ final class LineController { var kern: CGFloat = 0 { didSet { if kern != oldValue { - syntaxHighlighter?.kern = kern + isDefaultAttributesInvalid = true } } } @@ -240,25 +240,20 @@ private extension LineController { private func updateDefaultAttributesIfNecessary() { if isDefaultAttributesInvalid { if let input = createLineSyntaxHighlightInput() { - syntaxHighlighter?.setDefaultAttributes(on: input.attributedString) + let defaultStringAttributes = DefaultStringAttributes( + textColor: theme.textColor, + font: theme.font, + kern: kern, + tabWidth: tabWidth + ) + defaultStringAttributes.apply(to: input.attributedString) } - updateParagraphStyle() isDefaultAttributesInvalid = false isSyntaxHighlightingInvalid = true isTypesetterInvalid = true } } - private func updateParagraphStyle() { - if let attributedString = attributedString { - let paragraphStyle = NSMutableParagraphStyle() - paragraphStyle.tabStops = [] - paragraphStyle.defaultTabInterval = tabWidth - let range = NSRange(location: 0, length: attributedString.length) - attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: range) - } - } - private func updateTypesetterIfNecessary() { if isTypesetterInvalid { lineFragmentTree.reset(rootValue: 0, rootData: LineFragmentNodeData(lineFragment: nil)) diff --git a/Sources/Runestone/TextView/LineController/LineSyntaxHighlighter.swift b/Sources/Runestone/TextView/LineController/LineSyntaxHighlighter.swift index 9f2d5ecf5..8f0319855 100644 --- a/Sources/Runestone/TextView/LineController/LineSyntaxHighlighter.swift +++ b/Sources/Runestone/TextView/LineController/LineSyntaxHighlighter.swift @@ -23,24 +23,8 @@ final class LineSyntaxHighlighterInput { protocol LineSyntaxHighlighter: AnyObject { typealias AsyncCallback = (Result) -> Void var theme: Theme { get set } - var kern: CGFloat { get set } var canHighlight: Bool { get } - func setDefaultAttributes(on attributedString: NSMutableAttributedString) func syntaxHighlight(_ input: LineSyntaxHighlighterInput) func syntaxHighlight(_ input: LineSyntaxHighlighterInput, completion: @escaping AsyncCallback) func cancel() } - -extension LineSyntaxHighlighter { - func setDefaultAttributes(on attributedString: NSMutableAttributedString) { - let entireRange = NSRange(location: 0, length: attributedString.length) - let attributes: [NSAttributedString.Key: Any] = [ - .foregroundColor: theme.textColor, - .font: theme.font, - .kern: kern as NSNumber - ] - attributedString.beginEditing() - attributedString.setAttributes(attributes, range: entireRange) - attributedString.endEditing() - } -}