|
| 1 | +// |
| 2 | +// TextLineStyle.swift |
| 3 | +// OpenSwiftUICore |
| 4 | +// |
| 5 | +// Audited for 6.5.4 |
| 6 | +// Status: Complete |
| 7 | + |
| 8 | +package import OpenSwiftUI_SPI |
| 9 | + |
| 10 | +@available(OpenSwiftUI_v3_0, *) |
| 11 | +extension Text { |
| 12 | + |
| 13 | + /// Description of the style used to draw the line for `StrikethroughStyleAttribute` |
| 14 | + /// and `UnderlineStyleAttribute`. |
| 15 | + /// |
| 16 | + /// Use this type to specify `underlineStyle` and `strikethroughStyle` |
| 17 | + /// OpenSwiftUI attributes of an `AttributedString`. |
| 18 | + public struct LineStyle: Hashable, Sendable { |
| 19 | + package var nsUnderlineStyleValue: Int |
| 20 | + |
| 21 | + package var color: Color? |
| 22 | + |
| 23 | + package var nsUnderlineStyle: NSUnderlineStyle { |
| 24 | + get { NSUnderlineStyle(rawValue: nsUnderlineStyleValue) } |
| 25 | + set { nsUnderlineStyleValue = newValue.rawValue } |
| 26 | + } |
| 27 | + |
| 28 | + /// Creates a line style. |
| 29 | + /// |
| 30 | + /// - Parameters: |
| 31 | + /// - pattern: The pattern of the line. |
| 32 | + /// - color: The color of the line. If not provided, the foreground |
| 33 | + /// color of text is used. |
| 34 | + public init(pattern: Text.LineStyle.Pattern = .solid, color: Color? = nil) { |
| 35 | + self.nsUnderlineStyleValue = NSUnderlineStyle([pattern.nsUnderlineStyle, .single]).rawValue |
| 36 | + self.color = color |
| 37 | + } |
| 38 | + |
| 39 | + /// The pattern, that the line has. |
| 40 | + public struct Pattern: Sendable { |
| 41 | + let nsUnderlineStyle: NSUnderlineStyle |
| 42 | + |
| 43 | + /// Draw a solid line. |
| 44 | + public static let solid: Text.LineStyle.Pattern = .init(nsUnderlineStyle: []) |
| 45 | + |
| 46 | + /// Draw a line of dots. |
| 47 | + public static let dot: Text.LineStyle.Pattern = .init(nsUnderlineStyle: .patternDot) |
| 48 | + |
| 49 | + /// Draw a line of dashes. |
| 50 | + public static let dash: Text.LineStyle.Pattern = .init(nsUnderlineStyle: .patternDash) |
| 51 | + |
| 52 | + /// Draw a line of alternating dashes and dots. |
| 53 | + public static let dashDot: Text.LineStyle.Pattern = .init(nsUnderlineStyle: .patternDashDot) |
| 54 | + |
| 55 | + /// Draw a line of alternating dashes and two dots. |
| 56 | + public static let dashDotDot: Text.LineStyle.Pattern = .init(nsUnderlineStyle: .patternDashDotDot) |
| 57 | + } |
| 58 | + |
| 59 | + /// Draw a single solid line. |
| 60 | + public static let single: Text.LineStyle = .init() |
| 61 | + |
| 62 | + package init?(_nsUnderlineStyle: NSUnderlineStyle) { |
| 63 | + guard !_nsUnderlineStyle.contains(.thick), |
| 64 | + !_nsUnderlineStyle.contains(.double), |
| 65 | + !_nsUnderlineStyle.contains(.byWord), |
| 66 | + !_nsUnderlineStyle.isEmpty else { |
| 67 | + return nil |
| 68 | + } |
| 69 | + self.nsUnderlineStyleValue = _nsUnderlineStyle.rawValue |
| 70 | + self.color = nil |
| 71 | + } |
| 72 | + |
| 73 | + package struct Resolved { |
| 74 | + package var nsUnderlineStyle: NSUnderlineStyle |
| 75 | + |
| 76 | + package var color: Color.Resolved? |
| 77 | + } |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | + |
| 82 | +struct UnderlineStyleKey: EnvironmentKey { |
| 83 | + static var defaultValue: Text.LineStyle? { nil } |
| 84 | +} |
| 85 | + |
| 86 | +struct StrikethroughStyleKey: EnvironmentKey { |
| 87 | + static var defaultValue: Text.LineStyle? { nil } |
| 88 | +} |
| 89 | + |
| 90 | +extension EnvironmentValues { |
| 91 | + var underlineStyle: Text.LineStyle? { |
| 92 | + get { self[UnderlineStyleKey.self] } |
| 93 | + set { self[UnderlineStyleKey.self] = newValue } |
| 94 | + } |
| 95 | + |
| 96 | + var strikethroughStyle: Text.LineStyle? { |
| 97 | + get { self[StrikethroughStyleKey.self] } |
| 98 | + set { self[StrikethroughStyleKey.self] = newValue } |
| 99 | + } |
| 100 | +} |
| 101 | + |
| 102 | +@available(OpenSwiftUI_v4_0, *) |
| 103 | +extension View { |
| 104 | + |
| 105 | + /// Applies an underline to the text in this view. |
| 106 | + /// |
| 107 | + /// - Parameters: |
| 108 | + /// - isActive: A Boolean value that indicates whether underline |
| 109 | + /// is added. The default value is `true`. |
| 110 | + /// - pattern: The pattern of the line. The default value is `solid`. |
| 111 | + /// - color: The color of the underline. If `color` is `nil`, the |
| 112 | + /// underline uses the default foreground color. |
| 113 | + /// |
| 114 | + /// - Returns: A view where text has a line running along its baseline. |
| 115 | + @available(OpenSwiftUI_v4_0, *) |
| 116 | + nonisolated public func underline( |
| 117 | + _ isActive: Bool = true, |
| 118 | + pattern: Text.LineStyle.Pattern = .solid, |
| 119 | + color: Color? = nil |
| 120 | + ) -> some View { |
| 121 | + environment( |
| 122 | + \.underlineStyle, |
| 123 | + isActive ? Text.LineStyle(pattern: pattern, color: color) : nil |
| 124 | + ) |
| 125 | + } |
| 126 | + |
| 127 | + /// Applies a strikethrough to the text in this view. |
| 128 | + /// |
| 129 | + /// - Parameters: |
| 130 | + /// - isActive: A Boolean value that indicates whether |
| 131 | + /// strikethrough is added. The default value is `true`. |
| 132 | + /// - pattern: The pattern of the line. The default value is `solid`. |
| 133 | + /// - color: The color of the strikethrough. If `color` is `nil`, the |
| 134 | + /// strikethrough uses the default foreground color. |
| 135 | + /// |
| 136 | + /// - Returns: A view where text has a line through its center. |
| 137 | + @available(OpenSwiftUI_v4_0, *) |
| 138 | + nonisolated public func strikethrough( |
| 139 | + _ isActive: Bool = true, |
| 140 | + pattern: Text.LineStyle.Pattern = .solid, |
| 141 | + color: Color? = nil |
| 142 | + ) -> some View { |
| 143 | + environment( |
| 144 | + \.strikethroughStyle, |
| 145 | + isActive ? Text.LineStyle(pattern: pattern, color: color) : nil |
| 146 | + ) |
| 147 | + } |
| 148 | +} |
0 commit comments