Skip to content

Commit

Permalink
Adjust foundation documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsaidi committed Oct 8, 2024
1 parent eaa2a02 commit 54bde27
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 122 deletions.
70 changes: 29 additions & 41 deletions Sources/RichTextKit/_Foundation/RichTextCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,24 @@
import Combine
import SwiftUI

/**
This coordinator is used to keep a ``RichTextView`` in sync
with a ``RichTextContext``.
This is used by ``RichTextEditor`` to coordinate changes in
its context and the underlying text view.
The coordinator sets itself as the text view's delegate. It
updates the context when things change in the text view and
syncs to context changes to the text view.
*/
/// This class is used to keep ``RichTextView`` in sync with
/// a ``RichTextContext``.
///
/// This is used by ``RichTextEditor`` to coordinate changes
/// in its context and the underlying text view. It will set
/// itself as the text view delegate, and update the context
/// when things change in the text view, and vice versa.
@preconcurrency @MainActor
open class RichTextCoordinator: NSObject {

// MARK: - Initialization

/**
Create a rich text coordinator.
- Parameters:
- text: The rich text to edit.
- textView: The rich text view to keep in sync.
- richTextContext: The context to keep in sync.
*/
/// Create a rich text coordinator.
///
/// - Parameters:
/// - text: The rich text to edit.
/// - textView: The rich text view to keep in sync.
/// - richTextContext: The context to keep in sync.
public init(
text: Binding<NSAttributedString>,
textView: RichTextView,
Expand Down Expand Up @@ -67,16 +61,13 @@ open class RichTextCoordinator: NSObject {

// MARK: - Internal Properties

/**
The background color that was used before the currently
highlighted range was set.
*/
/// The background color that was set before any current
/// highlighted range was set.
var highlightedRangeOriginalBackgroundColor: ColorRepresentable?

/**
The foreground color that was used before the currently
highlighted range was set.
*/

/// The foreground color that was set before any current
/// highlighted range was set.
var highlightedRangeOriginalForegroundColor: ColorRepresentable?

#if canImport(UIKit)
Expand Down Expand Up @@ -213,20 +204,17 @@ extension RichTextCoordinator {
}
}

/**
On macOS, we have to update the font and colors when we
move the text input cursor and there's no selected text.
The code looks very strange, but setting current values
to the current values will reset the text view in a way
that is otherwise not done correctly.
To try out the incorrect behavior, comment out the code
below, then change font size, colors etc. for a part of
the text then move the input cursor around. When you do,
the presented information will be correct, but when you
type, the last selected font, colors etc. will be used.
*/
/// On macOS, we have to update the font and colors when
/// we move the text input cursor with no selected text.
///
/// The code may look strange, but setting values resets
/// the text view in a way that is otherwise not correct.
///
/// To try out the incorrect behavior, disable this code,
/// then change font size, colors etc. for a part of the
/// text, then move the input cursor around. When you do,
/// the information will show correctly, but as you type,
/// the last selected font, colors etc. will be used.
func updateTextViewAttributesIfNeeded() {
#if macOS
if textView.hasSelectedRange { return }
Expand Down
10 changes: 2 additions & 8 deletions Sources/RichTextKit/_Foundation/RichTextPresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,8 @@

import Foundation

/**
This protocol can be implemented any types that can present
a rich text and provide a ``selectedRange``.
This protocol is implemented by ``RichTextEditor`` since it
can both present and select text. It is also implemented by
the platform-specific ``RichTextView`` components.
*/
/// This protocol can be implemented by any type that can be
/// used to present rich text and provide a ``selectedRange``.
public protocol RichTextPresenter: RichTextReader {

/// Get the currently selected range.
Expand Down
67 changes: 26 additions & 41 deletions Sources/RichTextKit/_Foundation/RichTextReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,12 @@

import Foundation

/**
This protocol can be implemented any types that can provide
a rich text string.
The protocol is implemented by `NSAttributedString` as well
as other types in the library.
*/
/// This protocol can be implemented by any type that can be
/// used to access an ``attributedString``.
@preconcurrency @MainActor
public protocol RichTextReader {

/// The attributed string to use as rich text.
/// The attributed string.
var attributedString: NSAttributedString { get }
}

Expand All @@ -30,54 +25,44 @@ extension NSAttributedString: RichTextReader {

public extension RichTextReader {

/**
The rich text to use.
This is a convenience name alias for ``attributedString``
to provide this type with a property that uses the rich
text naming convention.
*/
/// The rich text.
///
/// This is a name alias for ``attributedString``.
var richText: NSAttributedString {
attributedString
}

/**
Get the full range of the entire ``richText``.
This uses `safeRange(for:)` to return a range that will
always be valid for the current rich text.
*/
/// The full range of the entire ``richText``.
///
/// This will use ``safeRange(for:isAttributeOperation:)``
/// to return a range that is always valid for this text.
var richTextRange: NSRange {
let range = NSRange(location: 0, length: richText.length)
let safeRange = safeRange(for: range)
return safeRange
}

/**
Get the rich text at a certain range.
Since this function uses `safeRange(for:)` to not crash
for invalid ranges, always use this function instead of
the unsafe `attributedSubstring`.
- Parameters:
- range: The range for which to get the rich text.
*/
/// The rich text at a certain range.
///
/// This will use ``safeRange(for:isAttributeOperation:)``
/// to return a range that is always valid for the range,
/// so use it instead of the unsafe `attributedSubstring`.
///
/// - Parameters:
/// - range: The range for which to get the rich text.
func richText(at range: NSRange) -> NSAttributedString {
let range = safeRange(for: range)
return attributedString.attributedSubstring(from: range)
}

/**
Get a safe range for the provided range.
A safe range is limited to the bounds of the attributed
string and helps protecting against range overflow.
- Parameters:
- range: The range for which to get a safe range.
- isAttributeOperation: Set this to `true` to avoid last position.
*/
/// Get a safe range for the provided range.
///
/// This range is capped to the bounds of the attributed
/// string and helps protecting against range overflow.
///
/// - Parameters:
/// - range: The range for which to get a safe range.
/// - isAttributeOperation: Set this to `true` to avoid last position.
func safeRange(
for range: NSRange,
isAttributeOperation: Bool = false
Expand Down
66 changes: 34 additions & 32 deletions Sources/RichTextKit/_Foundation/RichTextWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@

import Foundation

/**
This protocol extends ``RichTextReader`` and is implemented
by types that can provide a writable rich text string.
This protocol is implemented by `NSMutableAttributedString`
as well as other types in the library.
*/
/// This protocol can be implemented by any type that can be
/// used to access an ``mutableAttributedString``.
///
///
public protocol RichTextWriter: RichTextReader {

/// Get the writable attributed string for the type.
/// The mutable attributed string.
var mutableAttributedString: NSMutableAttributedString? { get }
}

Expand All @@ -31,35 +28,40 @@ extension NSMutableAttributedString: RichTextWriter {

public extension RichTextWriter {

/**
Get the writable rich text from the implementing type.
This is an alias for ``mutableAttributedString`` and is
used to get a property that uses the rich text naming.
*/
/// The mutable rich text.
///
/// This is a name alias for ``mutableAttributedString``.
var mutableRichText: NSMutableAttributedString? {
mutableAttributedString
}

/**
Replace the text in a certain range with a new string.
- Parameters:
- range: The range to replace text in.
- string: The string to replace the current text with.
*/
func replaceText(in range: NSRange, with string: String) {
mutableRichText?.replaceCharacters(in: range, with: string)
/// Replace the text in a certain range.
///
/// - Parameters:
/// - range: The range to replace text in.
/// - string: The string to replace the current text with.
func replaceText(
in range: NSRange,
with string: String
) {
mutableRichText?.replaceCharacters(
in: range,
with: string
)
}

/**
Replace the text in a certain range with a new string.
- Parameters:
- range: The range to replace text in.
- string: The string to replace the current text with.
*/
func replaceText(in range: NSRange, with string: NSAttributedString) {
mutableRichText?.replaceCharacters(in: range, with: string)
/// Replace the text in a certain range.
///
/// - Parameters:
/// - range: The range to replace text in.
/// - string: The string to replace the current text with.
func replaceText(
in range: NSRange,
with string: NSAttributedString
) {
mutableRichText?.replaceCharacters(
in: range,
with: string
)
}
}

0 comments on commit 54bde27

Please sign in to comment.