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
2 changes: 1 addition & 1 deletion Example/HostingExample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ class ViewController: NSViewController {

struct ContentView: View {
var body: some View {
DynamicLayoutViewExample()
MyViewThatFitsExample()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// MyViewThatFitsExample.swift
// SharedExample

#if OPENSWIFTUI
import OpenSwiftUI
#else
import SwiftUI
#endif

// The DL does not fully align since we have not implement canonicalize API yet.
// See https://github.com/OpenSwiftUIProject/OpenSwiftUI/issues/349
struct MyViewThatFitsExample: View {
@State private var showRed = false
var body: some View {
MyViewThatFitsByLayout {
Color.red.frame(width: 100, height: 200)
Color.blue.frame(width: 200, height: 100)
}
.frame(width: 100, height: showRed ? 200 : 100)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
showRed.toggle()
}
}
.id(showRed)
}
}
7 changes: 7 additions & 0 deletions Sources/OpenSwiftUICore/Animation/Animatable/Animatable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package import OpenAttributeGraphShims
// MARK: - Animatable

/// A type that describes how to animate a property of a view.
@available(OpenSwiftUI_v1_0, *)
public protocol Animatable {
/// The type defining the data to animate.
associatedtype AnimatableData: VectorArithmetic
Expand All @@ -25,13 +26,15 @@ public protocol Animatable {

// MARK: - Animateble + Extension

@available(OpenSwiftUI_v1_0, *)
extension Animatable where Self: VectorArithmetic {
public var animatableData: Self {
get { self }
set { self = newValue }
}
}

@available(OpenSwiftUI_v1_0, *)
extension Animatable where AnimatableData == EmptyAnimatableData {
public var animatableData: EmptyAnimatableData {
@inlinable
Expand Down Expand Up @@ -59,6 +62,7 @@ extension Attribute where Value: Animatable {
}
}

@available(OpenSwiftUI_v1_0, *)
extension Animatable {
public static func _makeAnimatable(value: inout _GraphValue<Self>, inputs: _GraphInputs) {
guard MemoryLayout<AnimatableData>.size != 0,
Expand All @@ -84,6 +88,7 @@ extension Animatable {
///
/// This type is suitable for use as the `animatableData` property of
/// types that do not have any animatable properties.
@available(OpenSwiftUI_v1_0, *)
@frozen
public struct EmptyAnimatableData: VectorArithmetic {
@inlinable
Expand Down Expand Up @@ -113,10 +118,12 @@ public struct EmptyAnimatableData: VectorArithmetic {
public static func == (_: EmptyAnimatableData, _: EmptyAnimatableData) -> Bool { true }
}

@available(OpenSwiftUI_v5_0, *)
extension Double: Animatable {
public typealias AnimatableData = Double
}

@available(OpenSwiftUI_v5_0, *)
extension CGFloat: Animatable {
public typealias AnimatableData = CGFloat
}
198 changes: 196 additions & 2 deletions Sources/OpenSwiftUICore/Animation/Transition/ContentTransition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

// TODO

public import OpenCoreGraphicsShims
package import OpenRenderBoxShims

@available(OpenSwiftUI_v4_0, *)
public struct ContentTransition: Equatable, Sendable {
package enum Storage: Equatable, @unchecked Sendable {
Expand Down Expand Up @@ -72,8 +75,199 @@ public struct ContentTransition: Equatable, Sendable {

// TODO: NumericTextConfiguration

@_spi(Private)
public struct EffectType: Equatable, Sendable {
package enum Arg: Equatable, Sendable {
case none
case float(Float)
case int(UInt32)
}

package var type: ORBTransitionEffectType
package var arg0: ContentTransition.EffectType.Arg, arg1: ContentTransition.EffectType.Arg

package init(
type: ORBTransitionEffectType,
arg0: ContentTransition.EffectType.Arg = .none,
arg1: ContentTransition.EffectType.Arg = .none
) {
self.type = type
self.arg0 = arg0
self.arg1 = arg1
}

public static var opacity: ContentTransition.EffectType {
self.init(type: .opacity, arg0: .none, arg1: .none)
}

@available(*, deprecated, message: "use opacity variable")
public static func opacity(_ opacity: Double = 0) -> ContentTransition.EffectType {
self.init(type: .opacity, arg0: .none, arg1: .none)
}

public static func blur(radius: CGFloat) -> ContentTransition.EffectType {
self.init(type: .blur, arg0: .float(Float(radius)), arg1: .none)
}

@available(OpenSwiftUI_v6_0, *)
public static func relativeBlur(scale: CGSize) -> ContentTransition.EffectType {
self.init(type: .relativeBlur, arg0: .float(Float(scale.width)), arg1: .float(Float(scale.height)))
}

public static func scale(_ scale: CGFloat = 0) -> ContentTransition.EffectType {
self.init(type: .scale, arg0: .float(Float(scale)), arg1: .none)
}

public static func translation(_ size: CGSize) -> ContentTransition.EffectType {
self.init(type: .translationSize, arg0: .float(Float(size.width)), arg1: .float(Float(size.height)))
}

@available(OpenSwiftUI_v6_0, *)
public static func translation(scale: CGSize) -> ContentTransition.EffectType {
self.init(type: .translationScale, arg0: .float(Float(scale.width)), arg1: .float(Float(scale.height)))
}

public static var matchMove: ContentTransition.EffectType {
self.init(type: .matchMove, arg0: .none, arg1: .none)
}
}

@_spi(Private)
@available(OpenSwiftUI_v6_0, *)
public enum SequenceDirection: Hashable, Sendable {
case leading, trailing, up, down
case forwards, backwards
}

@_spi(Private)
public struct Effect: Equatable, Sendable {
package var type: ContentTransition.EffectType
package var begin: Float
package var duration: Float
package var events: ORBTransitionEvents
package var flags: ORBTransitionEffectFlags

package init(
type: ContentTransition.EffectType,
begin: Float = 0,
duration: Float = 1,
events: ORBTransitionEvents = .addRemove,
flags: ORBTransitionEffectFlags = .init()
) {
self.type = type
self.begin = begin
self.duration = duration
self.events = events
self.flags = flags
}

public init(
_ type: ContentTransition.EffectType,
timeline: ClosedRange<Float> = 0 ... 1,
appliesOnInsertion: Bool = true,
appliesOnRemoval: Bool = true
) {
self.type = type
self.begin = timeline.lowerBound
self.duration = timeline.upperBound - timeline.lowerBound
self.events = [
appliesOnInsertion ? .add : [],
appliesOnRemoval ? .remove : [],
]
self.flags = []
}

@available(OpenSwiftUI_v6_0, *)
public static func sequence(
direction: ContentTransition.SequenceDirection,
delay: Double,
maxAllowedDurationMultiple: Double = .infinity,
appliesOnInsertion: Bool = true,
appliesOnRemoval: Bool = true
) -> ContentTransition.Effect {
_openSwiftUIUnimplementedFailure()
}

@available(OpenSwiftUI_v6_0, *)
public func removeInverts(_ state: Bool) -> ContentTransition.Effect {
_openSwiftUIUnimplementedFailure()
}
}

@_spi(Private)
public struct Method: Equatable, Sendable {
package var method: ORBTransitionMethod

package init(method: ORBTransitionMethod) {
self.method = method
}

public static let diff: ContentTransition.Method = .init(method: .diff)

public static let forwards: ContentTransition.Method = .init(method: .forwards)

public static let backwards: ContentTransition.Method = .init(method: .backwards)

public static let prefix: ContentTransition.Method = .init(method: .prefix)

public static let suffix: ContentTransition.Method = .init(method: .suffix)

public static let prefixAndSuffix: ContentTransition.Method = .init(method: .prefixAndSuffix)

public static let binary: ContentTransition.Method = .init(method: .binary)

public static let none: ContentTransition.Method = .init(method: .none)

public static func == (a: ContentTransition.Method, b: ContentTransition.Method) -> Bool {
a.method == b.method
}
}

// TODO
package enum Effect {}
package struct State {}
}

// FIXME: ORB

package enum ORBTransitionMethod: Int {
case empty
case diff
case forwards
case backwards
case prefix
case suffix
case binary
case none
case prefixAndSuffix
}

// ProtobufEnum
package struct ORBTransitionEvents: OptionSet {
package let rawValue: UInt32

package init(rawValue: UInt32) {
self.rawValue = rawValue
}

public static let add: ORBTransitionEvents = .init(rawValue: 1)
public static let remove: ORBTransitionEvents = .init(rawValue: 2)
public static let addRemove: ORBTransitionEvents = .init(rawValue: 3)
}

package struct ORBTransitionEffectFlags: OptionSet {
package let rawValue: UInt32

package init(rawValue: UInt32) {
self.rawValue = rawValue
}
}

package enum State {}
package enum ORBTransitionEffectType: UInt32, Equatable {
case opacity = 1
case scale = 2
case translationSize = 3
case blur = 4
case matchMove = 5
case translationScale = 15
case relativeBlur = 16
}
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ extension PreferencesOutputs {

extension DisplayList.Item {
package mutating func canonicalize(options: DisplayList.Options = .init()) {
// TODO
// TODO eg. .opacity(1.0) -> .identity
}

// package func matchesTopLevelStructure(of other: DisplayList.Item) -> Bool
Expand Down
Loading
Loading