Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions Sources/OpenSwiftUICore/View/Text/Text/Text+Justification.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// Text+Justification.swift
// OpenSwiftUICore
//
// Audited for 6.5.4
// Status: Complete
// ID: F89CCC57FFF9CABCAC4F565338DE677C (SwiftUICore)

@_spi(Private)
@available(OpenSwiftUI_v5_0, *)
public struct TextJustification: Sendable, Equatable {
struct Full: Equatable {
var allLines: Bool
var flexible: Bool
}

enum Storage: Equatable {
case full(Full)
case none
}

var storage: Storage

public static let none: TextJustification = .init(storage: .none)

public static let full: TextJustification = .full()

public static let stretched: TextJustification = .stretched(true)

public static func stretched(_ flexible: Bool = true) -> TextJustification {
.full(allLines: true, flexible: flexible)
}

public static func full(
allLines: Bool = false,
flexible: Bool = false
) -> TextJustification {
.init(storage: .full(.init(allLines: allLines, flexible: flexible)))
}
}

private struct TextJustificationKey: EnvironmentKey {
static let defaultValue: TextJustification = .none
}

extension EnvironmentValues {
var textJustification: TextJustification {
get { self[TextJustificationKey.self] }
set { self[TextJustificationKey.self] = newValue }
}
}

@_spi(Private)
@available(OpenSwiftUI_v5_0, *)
extension View {

@available(OpenSwiftUI_v5_0, *)
nonisolated public func justification(_ justfication: TextJustification) -> some View {
environment(\.textJustification, justfication)
}
}
4 changes: 4 additions & 0 deletions Sources/OpenSwiftUICore/View/Text/Text/Text+LayoutShape.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,7 @@ package struct TextShape: Equatable {
)
}
}

extension EnvironmentValues {
@Entry var textShape: TextShape = .bounds
}
52 changes: 52 additions & 0 deletions Sources/OpenSwiftUICore/View/Text/Text/Text+Sizing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,46 @@
// Status: Complete
// ID: 22747AAF70EE5063D02F299CE90A18BE (SwiftUICore)

// MARK: TextSizingModifier

protocol TextSizingModifier: Equatable {
func updateLayoutMargins(_ margins: inout EdgeInsets)
}

class AnyTextSizingModifier: Equatable, TextSizingModifier, @unchecked Sendable {
static func == (lhs: AnyTextSizingModifier, rhs: AnyTextSizingModifier) -> Bool {
lhs.isEqual(to: rhs)
}

func updateLayoutMargins(_ margins: inout EdgeInsets) {
_openSwiftUIBaseClassAbstractMethod()
}

func isEqual(to other: AnyTextSizingModifier) -> Bool {
_openSwiftUIBaseClassAbstractMethod()
}
}

private class ConcreteTextSizingModifier<M>: AnyTextSizingModifier, @unchecked Sendable where M: TextSizingModifier {
let modifier: M

init(modifier: M) {
self.modifier = modifier
}

override func updateLayoutMargins(_ margins: inout EdgeInsets) {
modifier.updateLayoutMargins(&margins)
}

override func isEqual(to other: AnyTextSizingModifier) -> Bool {
guard let other = other as? ConcreteTextSizingModifier else {
return false
}
return modifier == other.modifier
}
}


// MARK: - Text + Sizing

@_spi(Private)
Expand All @@ -22,6 +62,8 @@ extension Text {

package var storage: Text.Sizing.Storage

private var modifiers: [AnyTextSizingModifier] = []

package init(_ storage: Text.Sizing.Storage) {
self.storage = storage
}
Expand All @@ -34,6 +76,16 @@ extension Text {
}
}

//extension Text.Sizing {
// func layoutMargins(
// for: NSAttributedString,
// metrics: inout NSAttributedString.EncodedFontMetrics?
// layoutProperties: LayoutProperties
// ) {
// _openSwiftUIUnimplementedFailure()
// }
//}

private struct TextSizingKey: EnvironmentKey {
static let defaultValue: Text.Sizing = .standard
}
Expand Down
148 changes: 125 additions & 23 deletions Sources/OpenSwiftUICore/View/Text/Text/Text+View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,23 @@ public struct TextLayoutProperties: Equatable {

package var lowerLineLimit: Int?

// public var truncationMode: Text.TruncationMode =
public var truncationMode: Text.TruncationMode = .tail

public var multilineTextAlignment: TextAlignment
public var multilineTextAlignment: TextAlignment = .leading

public var layoutDirection: LayoutDirection
public var layoutDirection: LayoutDirection = .leftToRight

package var transitionStyle: ContentTransition.Style
package var transitionStyle: ContentTransition.Style = .default

public var minScaleFactor: CGFloat = 1.0

public var lineSpacing: CGFloat = .zero

public var lineHeightMultiple: CGFloat = .zero

// public var maximumLineHeight: CGFloat =
public var maximumLineHeight: CGFloat = MaximumLineHeightKey.defaultValue

// public var minimumLineHeight: CGFloat
public var minimumLineHeight: CGFloat = MinimumLineHeightKey.defaultValue

public var hyphenationFactor: CGFloat = .zero

Expand All @@ -75,45 +75,119 @@ public struct TextLayoutProperties: Equatable {

package var textSizing: Text.Sizing = .standard

// package var textShape: TextShape
private var textShape: TextShape = .bounds

// package var flags: Flags
private struct Flags: OptionSet {
var rawValue: UInt8

static let widthIsFlexible = Flags(rawValue: 1 << 0)

static let sizeFitting = Flags(rawValue: 1 << 1)
}

private var flags: Flags = []

package var widthIsFlexible: Bool {
get { _openSwiftUIUnimplementedFailure() }
set { _openSwiftUIUnimplementedFailure() }
get { flags.contains(.widthIsFlexible) }
set { flags.setValue(newValue, for: .widthIsFlexible) }
}

package var sizeFitting: Bool {
get { _openSwiftUIUnimplementedFailure() }
set { _openSwiftUIUnimplementedFailure() }
get { flags.contains(.sizeFitting) }
set { flags.setValue(newValue, for: .sizeFitting) }
}

package init() {
_openSwiftUIUnimplementedFailure()
_openSwiftUIEmptyStub()
}

public init(_ env: EnvironmentValues) {
self = env[Key.self]
}

private struct Key: DerivedEnvironmentKey {
static func value(in environment: EnvironmentValues) -> TextLayoutProperties {
// TODO
.init()
TextLayoutProperties(from: environment)
}
}

public init(_ env: EnvironmentValues) {
self = env[Key.self]
init(from env: EnvironmentValues) {
lineLimit = env.lineLimit
lowerLineLimit = env.lowerLineLimit
truncationMode = env.truncationMode
multilineTextAlignment = env.multilineTextAlignment
layoutDirection = env.layoutDirection
transitionStyle = env.contentTransitionStyle
minScaleFactor = env.minimumScaleFactor
lineSpacing = env.lineSpacing
lineHeightMultiple = env.lineHeightMultiple
maximumLineHeight = env.maximumLineHeight
minimumLineHeight = env.minimumLineHeight
hyphenationFactor = env.hyphenationFactor
hyphenationDisabled = env.hyphenationDisabled
writingMode = env.writingMode
bodyHeadOutdent = env.bodyHeadOutdent
pixelLength = env.pixelLength
textSizing = env.textSizing
textShape = env.textShape
widthIsFlexible = switch env.textJustification.storage {
case .full(let full): full.flexible
case .none: false
}
}

package func update(
_ env: inout EnvironmentValues,
from old: TextLayoutProperties
) {
_openSwiftUIUnimplementedFailure()
}

public static func == (a: TextLayoutProperties, b: TextLayoutProperties) -> Bool {
_openSwiftUIUnimplementedFailure()
if lineLimit != old.lineLimit {
env.lineLimit = lineLimit
}
if lowerLineLimit != old.lowerLineLimit {
env.lowerLineLimit = lowerLineLimit
}
if truncationMode != old.truncationMode {
env.truncationMode = truncationMode
}
if multilineTextAlignment != old.multilineTextAlignment {
env.multilineTextAlignment = multilineTextAlignment
}
if layoutDirection != old.layoutDirection {
env.layoutDirection = layoutDirection
}
if minScaleFactor != old.minScaleFactor {
env.minimumScaleFactor = minScaleFactor
}
if lineSpacing != old.lineSpacing {
env.lineSpacing = lineSpacing
}
if lineHeightMultiple != old.lineHeightMultiple {
env.lineHeightMultiple = lineHeightMultiple
}
if maximumLineHeight != old.maximumLineHeight {
env.maximumLineHeight = maximumLineHeight
}
if minimumLineHeight != old.minimumLineHeight {
env.minimumLineHeight = minimumLineHeight
}
if hyphenationFactor != old.hyphenationFactor {
env.hyphenationFactor = hyphenationFactor
}
if hyphenationDisabled != old.hyphenationDisabled {
env.hyphenationDisabled = hyphenationDisabled
}
if transitionStyle != old.transitionStyle {
env.contentTransitionStyle = transitionStyle
}
if textSizing != old.textSizing {
env.textSizing = textSizing
}
if writingMode != old.writingMode {
env.writingMode = writingMode
}
if textShape != old.textShape {
env.textShape = textShape
}
}
}

Expand All @@ -132,7 +206,6 @@ extension TextLayoutProperties: ProtobufMessage {
}
}


// MARK: - ResolvedTextFilter [WIP]

struct ResolvedTextFilter: StatefulRule, AsyncAttribute {
Expand Down Expand Up @@ -195,3 +268,32 @@ extension ResolvedStyledText {
private struct TextFilter {

}

// FIXME

extension EnvironmentValues {
private struct LineLimitKey: EnvironmentKey {
static var defaultValue: Int? { nil }
}

public var lineLimit: Int? {
get { self[LineLimitKey.self] }
set { self[LineLimitKey.self] = newValue }
}

private struct LowerLineLimitKey: EnvironmentKey {
static var defaultValue: Int? { nil }
}

package var lowerLineLimit: Int? {
get { self[LowerLineLimitKey.self] }
set { self[LowerLineLimitKey.self] = newValue }
}
}

extension EnvironmentValues {
var contentTransitionStyle: ContentTransition.Style {
get { _openSwiftUIUnimplementedFailure() }
set { _openSwiftUIUnimplementedFailure() }
}
}
9 changes: 9 additions & 0 deletions Sources/OpenSwiftUICore/View/Text/Util/TruncationMode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ extension EnvironmentValues {
set { self[MinimumLineHeightKey.self] = newValue }
}

var hyphenationDisabled: Bool {
get { self[HyphenationDisabledKey.self] }
set { self[HyphenationDisabledKey.self] = newValue }
}

@_spi(Private)
@available(OpenSwiftUI_v2_0, *)
public var hyphenationFactor: CGFloat {
Expand Down Expand Up @@ -463,6 +468,10 @@ extension View {
environment(\.minimumLineHeight, lineHeight)
}

func hyphenationDisabled(_ flag: Bool) -> some View {
environment(\.hyphenationDisabled, flag)
}

@_spi(Private)
@available(OpenSwiftUI_v2_0, *)
nonisolated public func hyphenationFactor(_ factor: CGFloat) -> some View {
Expand Down
Loading