diff --git a/.swiftformat b/.swiftformat new file mode 100644 index 00000000..6a52dfc9 --- /dev/null +++ b/.swiftformat @@ -0,0 +1,86 @@ +--acronyms ID,URL,UUID +--allman false +--anonymousforeach convert +--assetliterals visual-width +--asynccapturing +--beforemarks +--binarygrouping 4,8 +--categorymark "MARK: %c" +--classthreshold 0 +--closingparen balanced +--closurevoid remove +--commas always +--conflictmarkers reject +--decimalgrouping 3,6 +--elseposition same-line +--emptybraces no-space +--enumnamespaces always +--enumthreshold 0 +--exponentcase lowercase +--exponentgrouping disabled +--extensionacl on-declarations +--extensionlength 0 +--extensionmark "MARK: - %t + %c" +--fractiongrouping disabled +--fragment false +--funcattributes preserve +--generictypes +--groupedextension "MARK: %c" +--guardelse auto +--header ignore +--hexgrouping 4,8 +--hexliteralcase uppercase +--ifdef no-indent +--importgrouping alpha +--indent 4 +--indentcase false +--indentstrings false +--lifecycle +--lineaftermarks true +--linebreaks lf +--markcategories true +--markextensions always +--marktypes always +--maxwidth none +--modifierorder +--nevertrailing +--nospaceoperators +--nowrapoperators +--octalgrouping 4,8 +--onelineforeach ignore +--operatorfunc spaced +--organizetypes actor,class,enum,struct +--patternlet hoist +--ranges spaced +--redundanttype inferred +--self remove +--selfrequired +--semicolons inline +--shortoptionals always +--smarttabs enabled +--someany false +--stripunusedargs always +--structthreshold 0 +--swiftversion 5.10 +--tabwidth unspecified +--throwcapturing +--trailingclosures +--trimwhitespace nonblank-lines +--typeattributes preserve +--typeblanklines remove +--typemark "MARK: - %t" +--varattributes preserve +--voidtype void +--wraparguments preserve +--wrapcollections preserve +--wrapconditions preserve +--wrapeffects preserve +--wrapenumcases always +--wrapparameters default +--wrapreturntype preserve +--wrapternary default +--wraptypealiases preserve +--xcodeindentation disabled +--yodaswap always +--disable blankLineAfterImports,wrapMultilineStatementBraces +--enable acronyms,blankLinesBetweenImports diff --git a/Sources/OpenSwiftUI/Core/Data/VersionSeed.swift b/Sources/OpenSwiftUI/Core/Data/VersionSeed.swift index b6b28e3d..7f5a3eaa 100644 --- a/Sources/OpenSwiftUI/Core/Data/VersionSeed.swift +++ b/Sources/OpenSwiftUI/Core/Data/VersionSeed.swift @@ -47,6 +47,16 @@ struct VersionSeed: CustomStringConvertible { newValue.merge(seed) return newValue } + + @inline(__always) + static func == (lhs: VersionSeed, rhs: VersionSeed) -> Bool { + lhs.value == rhs.value + } + + @inline(__always) + static func != (lhs: VersionSeed, rhs: VersionSeed) -> Bool { + lhs.value != rhs.value + } } private func merge32(_ a: UInt32, _ b: UInt32) -> UInt32 { diff --git a/Sources/OpenSwiftUI/Core/Graph/GraphHost.swift b/Sources/OpenSwiftUI/Core/Graph/GraphHost.swift index c8a19633..f2c53cbe 100644 --- a/Sources/OpenSwiftUI/Core/Graph/GraphHost.swift +++ b/Sources/OpenSwiftUI/Core/Graph/GraphHost.swift @@ -17,7 +17,7 @@ class GraphHost { private(set) var data: Data private(set) var isInstantiated = false - private(set) var hostPreferenceValues: OptionalAttribute + /* private(set)*/ var hostPreferenceValues: OptionalAttribute private(set) var lastHostPreferencesSeed: VersionSeed = .invalid private var pendingTransactions: [AsyncTransaction] = [] /*private(set)*/ var inTransaction = false @@ -147,16 +147,33 @@ class GraphHost { } final func preferenceValue(_ key: Key.Type) -> Key.Value { - fatalError("TODO") + if data.hostPreferenceKeys.contains(key) { + return preferenceValues()[key].value + } else { + defer { removePreference(key) } + addPreference(key) + return preferenceValues()[key].value + } } - + final func addPreference(_ key: Key.Type) { - fatalError("TODO") + OGGraph.withoutUpdate { + data.hostPreferenceKeys.add(key) + } } - + + final func removePreference(_ key: Key.Type) { + OGGraph.withoutUpdate { + data.hostPreferenceKeys.remove(key) + } + } + final func updatePreferences() -> Bool { - // fatalError("TODO") - return false + let seed = hostPreferenceValues.value?.mergedSeed ?? .empty + let lastSeed = lastHostPreferencesSeed + let didUpdate = seed.isInvalid || lastSeed.isInvalid || (seed != lastSeed) + lastHostPreferencesSeed = seed + return didUpdate } final func updateRemovedState() { @@ -203,11 +220,11 @@ class GraphHost { } } - final func uninstantiate(immediately: Bool) { + final func uninstantiate(immediately _: Bool) { guard isInstantiated else { return } - // TODO + // TODO: } final func graphInvalidation(from attribute: OGAttribute?) { @@ -224,7 +241,7 @@ class GraphHost { } else { asyncTransaction( transaction, - mutation: EmptyGraphMutation(), + mutation: EmptyGraphMutation(), style: ._1, mayDeferUpdate: true ) @@ -264,7 +281,7 @@ class GraphHost { final func continueTransaction(_ body: @escaping () -> Void) { var host = self - while(!host.inTransaction) { + while !host.inTransaction { guard let parent = host.parentHost else { asyncTransaction( Transaction(), @@ -349,7 +366,7 @@ private final class AsyncTransaction { func append(_ mutation: Mutation) { // ``GraphMutation/combine`` is mutating function // So we use ``Array.subscript/_modify`` instead of ``Array.last/getter`` to mutate inline - if !mutations.isEmpty, mutations[mutations.count-1].combine(with: mutation) { + if !mutations.isEmpty, mutations[mutations.count - 1].combine(with: mutation) { return } mutations.append(mutation) diff --git a/Sources/OpenSwiftUI/Core/Modifier/ViewModifier/SafeAreaInsetsModifier.swift b/Sources/OpenSwiftUI/Core/Modifier/ViewModifier/SafeAreaInsetsModifier.swift new file mode 100644 index 00000000..1ccbc42e --- /dev/null +++ b/Sources/OpenSwiftUI/Core/Modifier/ViewModifier/SafeAreaInsetsModifier.swift @@ -0,0 +1,13 @@ +// +// ViewBuilder.swift +// OpenSwiftUI +// +// Audited for RELEASE_2023 +// Status: WIP + +struct _SafeAreaInsetsModifier: PrimitiveViewModifier/*, MultiViewModifier*/ { + var elements: [SafeAreaInsets.Element] + var nextInsets: SafeAreaInsets.OptionalValue? + + var insets: EdgeInsets = .init() // FIXME +} diff --git a/Sources/OpenSwiftUI/Core/View/TODO/_ViewInputs.swift b/Sources/OpenSwiftUI/Core/View/TODO/_ViewInputs.swift index e0b698dc..50e1a553 100644 --- a/Sources/OpenSwiftUI/Core/View/TODO/_ViewInputs.swift +++ b/Sources/OpenSwiftUI/Core/View/TODO/_ViewInputs.swift @@ -7,5 +7,5 @@ public struct _ViewInputs { var position: Attribute var containerPosition: Attribute var size: Attribute - // var safeAreaInsets: OptionalAttribute + var safeAreaInsets: OptionalAttribute } diff --git a/Sources/OpenSwiftUI/Core/View/ViewGraph.swift b/Sources/OpenSwiftUI/Core/View/ViewGraph.swift index e4f204a7..8eff6ada 100644 --- a/Sources/OpenSwiftUI/Core/View/ViewGraph.swift +++ b/Sources/OpenSwiftUI/Core/View/ViewGraph.swift @@ -10,6 +10,9 @@ internal import OpenGraphShims import Foundation final class ViewGraph: GraphHost { + @inline(__always) + static var current: ViewGraph { GraphHost.currentHost as! ViewGraph } + let rootViewType: Any.Type let makeRootView: (OGAttribute, _ViewInputs) -> _ViewOutputs weak var delegate: ViewGraphDelegate? @@ -65,7 +68,7 @@ final class ViewGraph: GraphHost { // TODO _proposedSize = Attribute(value: .zero) // TODO - _rootGeometry = Attribute(RootGeometry()) // FIXME + _rootGeometry = Attribute(RootGeometry(proposedSize: _proposedSize)) _position = _rootGeometry.origin() _dimensions = _rootGeometry.size() _updateSeed = Attribute(value: .zero) @@ -165,6 +168,15 @@ final class ViewGraph: GraphHost { // TODO } + private func makePreferenceOutlets(outputs: _ViewOutputs) { + // TODO + } + + private func removePreferenceOutlets(isInvalidating: Bool) { + // TODO + } + + // MARK: - Override Methods override var graphDelegate: GraphDelegate? { delegate } @@ -174,11 +186,65 @@ final class ViewGraph: GraphHost { } override func instantiateOutputs() { + #if canImport(Darwin) + let outputs = self.data.globalSubgraph.apply { + let graphInputs = graphInputs + var inputs = _ViewInputs( + base: graphInputs, + preferences: PreferencesInputs(hostKeys: data.$hostPreferenceKeys), + transform: $rootTransform, + position: $position, + containerPosition: $zeroPoint, + size: $dimensions, + safeAreaInsets: OptionalAttribute() + ) + if requestedOutputs.contains(.layout) { + // FIXME + inputs.base.options.formUnion(.init(rawValue: 0xe2)) + } + requestedOutputs.addRequestedPreferences(to: &inputs) + _preferenceBridge?.wrapInputs(&inputs) + _ViewDebug.instantiateIfNeeded() + delegate?.modifyViewInputs(&inputs) + // TODO + $rootGeometry.mutateBody( + as: RootGeometry.self, + invalidating: true + ) { rootGeometry in + // FIXME + rootGeometry.$layoutDirection = inputs.base.cachedEnvironment.wrappedValue.attribute(keyPath: \.layoutDirection) + } + // TOOD + return makeRootView(rootView, inputs) + } + $rootGeometry.mutateBody( + as: RootGeometry.self, + invalidating: true + ) { rootGeometry in + rootGeometry.$childLayoutComputer = outputs.$layoutComputer + } // TODO + makePreferenceOutlets(outputs: outputs) + #endif } override func uninstantiateOutputs() { - // TODO + #if canImport(Darwin) + removePreferenceOutlets(isInvalidating: false) + $rootGeometry.mutateBody( + as: RootGeometry.self, + invalidating: true + ) { rootGeometry in + rootGeometry.$layoutDirection = nil + rootGeometry.$childLayoutComputer = nil + } +// $rootPlatformList = nil +// $rootResponders = nil +// $rootAccessibilityNodes = nil +// $rootLayoutComputer = nil +// $rootDisplayList = nil + hostPreferenceValues = OptionalAttribute() + #endif } override func timeDidChange() { @@ -223,23 +289,102 @@ extension ViewGraph { struct Outputs: OptionSet { let rawValue: UInt8 + static var _0: Outputs { .init(rawValue: 1 << 0) } + static var _1: Outputs { .init(rawValue: 1 << 1) } + static var _2: Outputs { .init(rawValue: 1 << 2) } + static var _3: Outputs { .init(rawValue: 1 << 3) } static var layout: Outputs { .init(rawValue: 1 << 4) } + + fileprivate func addRequestedPreferences(to inputs: inout _ViewInputs) { + inputs.preferences.add(HostPreferencesKey.self) + if contains(._0) { + inputs.preferences.add(DisplayList.Key.self) + } + if contains(._2) { +// inputs.preferences.add(ViewRespondersKey.self) + } + if contains(._1) { +// inputs.preferences.add(PlatformItemList.Key.self) + } + if contains(._3) { +// inputs.preferences.add(AccessibilityNodesKe.self) + } + } } } private struct RootTransform: Rule { var value: ViewTransform { - let graph = GraphHost.currentHost as! ViewGraph - guard let delegate = graph.delegate else { + guard let delegate = ViewGraph.current.delegate else { return ViewTransform() } return delegate.rootTransform() } } -struct RootGeometry: Rule { +struct RootGeometry: Rule, AsyncAttribute { + @OptionalAttribute var layoutDirection: LayoutDirection? + @Attribute var proposedSize: ViewSize + @OptionalAttribute var safeAreaInsets: _SafeAreaInsetsModifier? + @OptionalAttribute var childLayoutComputer: LayoutComputer? + + // |←--------------------------proposedSize.value.width--------------------------→| (0, 0) + // ┌──────────────────────────────────────────────────────────────────────────────┐ ┌─────────> x + // │ (x: insets.leading, y: insets.top) | │ + // │ ↓ | | + // | |←--------------------------proposal.width--------------------------→| | | + // │ ┌────────────┬───────────────────────────────────────────────────────┐ | | + // │ |████████████| | │ ↓ y + // │ |████████████| | │ eg. + // │ ├────────────┘ │ | proposedSize = (width: 80, height: 30) + // | |←----------→| | | insets = ( + // │ |fittingSize.width | | top: 4, + // │ | | │ leading: 6, + // | | (x: insets.leading + (proposal.width - fittingSize.width ) * 0.5, | | bottom: 2, + // | | y: insets.top + (proposal.height - fittingSize.height) * 0.5) | | trailing: 4 + // | | ↓ | | ) + // │ | ┌────────────┐ │ | proposal = (width: 70, height: 24) + // │ | |████████████| │ | fitting = (width: 14, height: 4) + // │ | |████████████| | │ + // │ | └────────────┘ | │ Result: + // │ | | │ center: false + left + // │ | | │ x: insets.leading = 6 + // │ | | │ y: insets.top = 4 + // │ | | │ + // │ | | │ center: false + right + // │ | | │ x: insets.leading = proposedSize.width-(i.l+f.w) + // │ | | │ y: insets.top = 4 + // │ | | │ + // │ | | │ center: true + left + // │ └────────────────────────────────────────────────────────────────────┘ | x: i.l+(p.width-f.width)*0.5=34 + // | | y: i.t+(p.height-f.height)*0.5=14 + // └──────────────────────────────────────────────────────────────────────────────┘ var value: ViewGeometry { - // FIXME - .zero + let layoutComputer = childLayoutComputer ?? .defaultValue + let insets = safeAreaInsets?.insets ?? EdgeInsets() + let proposal = proposedSize.value.inset(by: insets) + let fittingSize = layoutComputer.delegate.sizeThatFits(_ProposedSize(size: proposal)) + + var x = insets.leading + var y = insets.top + if ViewGraph.current.centersRootView { + x += (proposal.width - fittingSize.width) * 0.5 + y += (proposal.height - fittingSize.height) * 0.5 + } + + let layoutDirection = layoutDirection ?? .leftToRight + switch layoutDirection { + case .leftToRight: + break + case .rightToLeft: + x = proposedSize.value.width - CGRect(origin: CGPoint(x: x, y: y), size: fittingSize).maxX + } + return ViewGeometry( + origin: ViewOrigin(value: CGPoint(x: x, y: y)), + dimensions: ViewDimensions( + guideComputer: layoutComputer, + size: ViewSize(value: fittingSize, _proposal: proposal) + ) + ) } } diff --git a/Sources/OpenSwiftUI/Data/Environment/CachedEnvironment.swift b/Sources/OpenSwiftUI/Data/Environment/CachedEnvironment.swift index be8bb48c..85d117b0 100644 --- a/Sources/OpenSwiftUI/Data/Environment/CachedEnvironment.swift +++ b/Sources/OpenSwiftUI/Data/Environment/CachedEnvironment.swift @@ -28,6 +28,20 @@ struct CachedEnvironment { // resolvedFgStyles = [:] } + mutating func attribute(keyPath: KeyPath) -> Attribute { + #if canImport(Darwin) + if let item = items.first(where: { $0.key == keyPath }) { + return Attribute(identifier: item.value) + } else { + let value = environment[keyPath: keyPath] + items.append(Item(key: keyPath, value: value.identifier)) + return value + } + #else + fatalError("See #39") + #endif + } + func intern(_ value: Value, id: Int) -> Attribute { fatalError("TODO") } @@ -46,7 +60,7 @@ struct CachedEnvironment { extension CachedEnvironment { private struct Item { var key: PartialKeyPath - #if canImport(Darwin) + #if canImport(Darwin) // See #39 var value: OGAttribute #endif } diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferenceList.swift b/Sources/OpenSwiftUI/Data/Preference/PreferenceList.swift index d1565cd6..307b0e08 100644 --- a/Sources/OpenSwiftUI/Data/Preference/PreferenceList.swift +++ b/Sources/OpenSwiftUI/Data/Preference/PreferenceList.swift @@ -101,6 +101,9 @@ struct PreferenceList: CustomStringConvertible { first = node.copy(next: first) } } + + @inline(__always) + var mergedSeed: VersionSeed? { first?.mergedSeed } } extension PreferenceList { diff --git a/Sources/OpenSwiftUI/Data/Preference/PreferencesInputs.swift b/Sources/OpenSwiftUI/Data/Preference/PreferencesInputs.swift index 839b8d24..0590c0cb 100644 --- a/Sources/OpenSwiftUI/Data/Preference/PreferencesInputs.swift +++ b/Sources/OpenSwiftUI/Data/Preference/PreferencesInputs.swift @@ -10,6 +10,12 @@ internal import OpenGraphShims struct PreferencesInputs { private(set) var keys: PreferenceKeys var hostKeys: Attribute + + @inline(__always) + init(hostKeys: Attribute) { + self.keys = PreferenceKeys() + self.hostKeys = hostKeys + } mutating func add(_ key: Key.Type) { keys.add(key) diff --git a/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Direction/LayoutDirection.swift b/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Direction/LayoutDirection.swift new file mode 100644 index 00000000..b6be952e --- /dev/null +++ b/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Direction/LayoutDirection.swift @@ -0,0 +1,132 @@ +// +// LayoutDirection.swift +// OpenSwiftUI +// +// Audited for RELEASE_2021 +// Status: Complete +// ID: 9DE75C3EAC30FFAB943BCC50F6D5E8C1 + +import Foundation + +// MARK: - LayoutDirection + +/// A direction in which OpenSwiftUI can lay out content. +/// +/// OpenSwiftUI supports both left-to-right and right-to-left directions +/// for laying out content to support different languages and locales. +/// The system sets the value based on the user's locale, but +/// you can also use the ``View/environment(_:_:)`` modifier +/// to override the direction for a view and its child views: +/// +/// MyView() +/// .environment(\.layoutDirection, .rightToLeft) +/// +/// You can also read the ``EnvironmentValues/layoutDirection`` environment +/// value to find out which direction applies to a particular environment. +/// However, in many cases, you don't need to take any action based on this +/// value. OpenSwiftUI horizontally flips the x position of each view within its +/// parent, so layout calculations automatically produce the desired effect +/// for both modes without any changes. +public enum LayoutDirection: Hashable, CaseIterable { + /// A left-to-right layout direction. + case leftToRight + + /// A right-to-left layout direction. + case rightToLeft +} + +extension LayoutDirection: Sendable {} + +#if canImport(UIKit) +// MARK: - UIKit integration + +import UIKit + +extension LayoutDirection { + /// Create a direction from its UITraitEnvironmentLayoutDirection equivalent. + public init?(_ uiLayoutDirection: UITraitEnvironmentLayoutDirection) { + switch uiLayoutDirection { + case .unspecified: + return nil + case .leftToRight: + self = .leftToRight + case .rightToLeft: + self = .rightToLeft + @unknown default: + return nil + } + } +} + +extension UITraitEnvironmentLayoutDirection { + /// Creates a trait environment layout direction from the specified OpenSwiftUI layout direction. + public init(_ layoutDirection: LayoutDirection) { + switch layoutDirection { + case .leftToRight: self = .leftToRight + case .rightToLeft: self = .rightToLeft + } + } +} + +#endif + +// MARK: - CodableLayoutDirection + +struct CodableLayoutDirection: CodableProxy { + var base: LayoutDirection + + private enum CodingValue: Int, Codable { + case leftToRight + case rightToLeft + } + + @inline(__always) + init(base: LayoutDirection) { + self.base = base + } + + init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() + let value = try container.decode(CodingValue.self) + switch value { + case .leftToRight: base = .leftToRight + case .rightToLeft: base = .rightToLeft + } + } + + func encode(to encoder: any Encoder) throws { + var container = encoder.singleValueContainer() + let value: CodingValue = switch base { + case .leftToRight: .leftToRight + case .rightToLeft: .rightToLeft + } + try container.encode(value) + } +} + +// MARK: - LayoutDirection + CodableByProxy + +extension LayoutDirection: CodableByProxy { + var codingProxy: CodableLayoutDirection { + CodableLayoutDirection(base: self) + } + + static func unwrap(codingProxy: CodableLayoutDirection) -> LayoutDirection { + codingProxy.base + } +} + +// MARK: - LayoutDirectionKey + +private struct LayoutDirectionKey: EnvironmentKey { + static let defaultValue: LayoutDirection = .leftToRight +} + +extension EnvironmentValues { + /// The layout direction associated with the current environment. + public var layoutDirection: LayoutDirection { + get { self[LayoutDirectionKey.self] } + set { self[LayoutDirectionKey.self] = newValue } + _modify { yield &self[LayoutDirectionKey.self] } + } +} diff --git a/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/EdgeInsets.swift b/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/EdgeInsets.swift index 51b4a415..7688a978 100644 --- a/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/EdgeInsets.swift +++ b/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/EdgeInsets.swift @@ -65,7 +65,31 @@ extension EdgeInsets { } } +extension CGSize { + @inline(__always) + func inset(by insets: EdgeInsets) -> CGSize { + CGSize( + width: max(width - insets.leading - insets.trailing, 0), + height: max(height - insets.top - insets.bottom, 0) + ) + } + + func outset(by insets: EdgeInsets) -> CGSize { + CGSize( + width: max(width + insets.leading + insets.trailing, 0), + height: max(height + insets.top + insets.bottom, 0) + ) + } +} + +// MARK: - Sendable + +extension EdgeInsets: Sendable {} + #if canImport(Darwin) + +// MARK: - UIKit/AppKit integration + #if canImport(UIKit) import UIKit #elseif canImport(AppKit) @@ -99,6 +123,8 @@ extension NSDirectionalEdgeInsets { } #endif +// MARK: - EdgeInsets + Animatable + extension EdgeInsets: Animatable, _VectorMath { @inlinable public var animatableData: AnimatablePair>> { @@ -149,7 +175,3 @@ extension EdgeInsets: CodableByProxy { static func unwrap(codingProxy: CodableEdgeInsets) -> EdgeInsets { codingProxy.base } } - -// MARK: - Sendable - -extension EdgeInsets: Sendable {} diff --git a/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/SafeAreaInsets.swift b/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/SafeAreaInsets.swift new file mode 100644 index 00000000..315ef24a --- /dev/null +++ b/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/SafeAreaInsets.swift @@ -0,0 +1,16 @@ +// TODO +struct SafeAreaInsets { + var space: UniqueID + var elements: [Element] + var next: OptionalValue + + indirect enum OptionalValue { + case insets(SafeAreaInsets) + case empty + } + + struct Element { + var regions: SafeAreaRegions + var insets: EdgeInsets + } +} diff --git a/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/SafeAreaRegions.swift b/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/SafeAreaRegions.swift new file mode 100644 index 00000000..f3cfdfaf --- /dev/null +++ b/Sources/OpenSwiftUI/Layout/LayoutAdjustments/Edge/SafeAreaRegions.swift @@ -0,0 +1,28 @@ +// +// SafeAreaRegions.swift +// OpenSwiftUI +// +// Audited for RELEASE_2021 +// Status: Complete + +/// A set of symbolic safe area regions. +@frozen +public struct SafeAreaRegions: OptionSet { + public let rawValue: UInt + + @inlinable + public init(rawValue: UInt) { self.rawValue = rawValue } + + /// The safe area defined by the device and containers within the + /// user interface, including elements such as top and bottom bars. + public static let container = SafeAreaRegions(rawValue: 1 << 0) + + /// The safe area matching the current extent of any software + /// keyboard displayed over the view content. + public static let keyboard = SafeAreaRegions(rawValue: 1 << 1) + + /// All safe area regions. + public static let all = SafeAreaRegions(rawValue: .max) +} + +extension SafeAreaRegions: Sendable {} diff --git a/Sources/OpenSwiftUI/Layout/LayoutFundamentals/internal/ProposedSize.swift b/Sources/OpenSwiftUI/Layout/LayoutFundamentals/internal/ProposedSize.swift index b883f9c4..f1bed571 100644 --- a/Sources/OpenSwiftUI/Layout/LayoutFundamentals/internal/ProposedSize.swift +++ b/Sources/OpenSwiftUI/Layout/LayoutFundamentals/internal/ProposedSize.swift @@ -12,4 +12,26 @@ struct _ProposedSize: Hashable { var height: CGFloat? static let unspecified = _ProposedSize(width: nil, height: nil) + + @inline(__always) + static var zero: _ProposedSize { + _ProposedSize(width: .zero, height: .zero) + } + + @inline(__always) + static var infinity: _ProposedSize { + _ProposedSize(width: .infinity, height: .infinity) + } + + @inline(__always) + init(width: CGFloat? = nil, height: CGFloat? = nil) { + self.width = width + self.height = height + } + + @inline(__always) + init(size: CGSize) { + width = size.width + height = size.height + } } diff --git a/Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift b/Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift index c2a582c0..4ddcb939 100644 --- a/Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift +++ b/Sources/OpenSwiftUI/View/Debug/TODO/ViewDebug.swift @@ -26,9 +26,21 @@ public enum _ViewDebug { } extension _ViewDebug { - fileprivate static var properties = Properties() - fileprivate static var isInitialized = false - + private static var properties = Properties() + private static var isInitialized = false + + @inline(__always) + static func instantiateIfNeeded() { + if !isInitialized { + let debugValue = UInt32(bitPattern: EnvironmentHelper.value(for: "SWIFTUI_VIEW_DEBUG")) + properties = Properties(rawValue: debugValue) + isInitialized = true + } + if !properties.isEmpty { + // OGSubgraphSetShouldRecordTree() + } + } + // TODO: fileprivate static func reallyWrap(_: inout _ViewOutputs, value _: _GraphValue, inputs _: UnsafePointer<_ViewInputs>) {} diff --git a/Sources/OpenSwiftUI/View/View/EmptyView.swift b/Sources/OpenSwiftUI/View/View/EmptyView.swift index 0b5cd6af..e9a2ae4c 100644 --- a/Sources/OpenSwiftUI/View/View/EmptyView.swift +++ b/Sources/OpenSwiftUI/View/View/EmptyView.swift @@ -3,12 +3,12 @@ // OpenSwiftUI // // Audited for RELEASE_2021 -// Status: Empty +// Status: WIP -public struct EmptyView: View { +public struct EmptyView: PrimitiveView { public init() {} - - public var body: some View { - fatalError() + + public static func _makeView(view: _GraphValue, inputs: _ViewInputs) -> _ViewOutputs { + _ViewOutputs() } }