From 98c1c24ea86a025aa49373c8f1f81a2f1c85ab02 Mon Sep 17 00:00:00 2001 From: Luke Zhao Date: Thu, 11 Nov 2021 13:46:15 -0800 Subject: [PATCH] Improve Badge and add before and after alignment --- .../Components/Layout/Other/Badge.swift | 48 ++++++++++++------- .../Layout/Stack/StackRenderNode.swift | 35 ++++++++++++++ .../Model/Component/Component+Modifier.swift | 12 ++--- 3 files changed, 72 insertions(+), 23 deletions(-) diff --git a/Sources/UIComponent/Components/Layout/Other/Badge.swift b/Sources/UIComponent/Components/Layout/Other/Badge.swift index bcd54a72..1c0a9889 100644 --- a/Sources/UIComponent/Components/Layout/Other/Badge.swift +++ b/Sources/UIComponent/Components/Layout/Other/Badge.swift @@ -13,22 +13,25 @@ import BaseToolbox /// /// Instead of using it directly, you can easily create a` Badge` component by using the `.badge` modifier. /// ```swift -/// someComponent.badge(someOtherComponent, offset: CGVector(dx: 8, dy: -8)) +/// someComponent.badge(someOtherComponent, offset: CGPoint(x: 8, y: -8)) /// ``` /// or /// ```swift -/// someComponent.badge(offset: CGVector(dx: 8, dy: -8)) { +/// someComponent.badge(offset: CGPoint(x: 8, y: -8)) { /// someOtherComponent /// } /// ``` /// /// Checkout the `ComplexLayoutViewController.swift` for other examples. public struct Badge: Component { + public enum Alignment: CaseIterable { + case start, end, center, stretch, before, after + } let child: Component let overlay: Component - let verticalAlignment: CrossAxisAlignment - let horizontalAlignment: CrossAxisAlignment - let offset: CGVector + let verticalAlignment: Alignment + let horizontalAlignment: Alignment + let offset: CGPoint public func layout(_ constraint: Constraint) -> RenderNode { let childRenderNode = child.layout(constraint) @@ -38,32 +41,43 @@ public struct Badge: Component { width: horizontalAlignment == .stretch ? childRenderNode.size.width : -.infinity, height: verticalAlignment == .stretch ? childRenderNode.size.height : -.infinity ), - maxSize: childRenderNode.size + maxSize: CGSize( + width: horizontalAlignment == .stretch ? childRenderNode.size.width : .infinity, + height: verticalAlignment == .stretch ? childRenderNode.size.height : .infinity + ) ) ) - let beagePosition: (x: CGFloat, y: CGFloat) + let badgePosition: (x: CGFloat, y: CGFloat) switch horizontalAlignment { case .start: - beagePosition.x = 0 + badgePosition.x = 0 case .end: - beagePosition.x = (childRenderNode.size.width - badgeRenderNode.size.width) + badgePosition.x = (childRenderNode.size.width - badgeRenderNode.size.width) case .center: - beagePosition.x = (childRenderNode.size.width / 2 - badgeRenderNode.size.width / 2) + badgePosition.x = (childRenderNode.size.width / 2 - badgeRenderNode.size.width / 2) case .stretch: - beagePosition.x = 0 + badgePosition.x = 0 + case .before: + badgePosition.x = -badgeRenderNode.size.width + case .after: + badgePosition.x = childRenderNode.size.width } switch verticalAlignment { case .start: - beagePosition.y = 0 + badgePosition.y = 0 case .end: - beagePosition.y = (childRenderNode.size.height - badgeRenderNode.size.height) + badgePosition.y = (childRenderNode.size.height - badgeRenderNode.size.height) case .center: - beagePosition.y = (childRenderNode.size.height / 2 - badgeRenderNode.size.height / 2) + badgePosition.y = (childRenderNode.size.height / 2 - badgeRenderNode.size.height / 2) case .stretch: - beagePosition.y = 0 + badgePosition.y = 0 + case .before: + badgePosition.y = -badgeRenderNode.size.height + case .after: + badgePosition.y = childRenderNode.size.height } - let finallyBadgePosition = CGPoint(x: beagePosition.x + offset.dx, y: beagePosition.y + offset.dy) + let finallyBadgePosition = CGPoint(x: badgePosition.x + offset.x, y: badgePosition.y + offset.y) - return SlowRenderNode(size: childRenderNode.size, children: [childRenderNode, badgeRenderNode], positions: [.zero, finallyBadgePosition]) + return AlwaysRenderNode(size: childRenderNode.size, children: [childRenderNode, badgeRenderNode], positions: [.zero, finallyBadgePosition]) } } diff --git a/Sources/UIComponent/Components/Layout/Stack/StackRenderNode.swift b/Sources/UIComponent/Components/Layout/Stack/StackRenderNode.swift index 26e00822..042c07fb 100644 --- a/Sources/UIComponent/Components/Layout/Stack/StackRenderNode.swift +++ b/Sources/UIComponent/Components/Layout/Stack/StackRenderNode.swift @@ -1,6 +1,7 @@ // Created by Luke Zhao on 8/22/20. import UIKit +import BaseToolbox public protocol StackRenderNode: RenderNode, BaseLayoutProtocol { var size: CGSize { get } @@ -73,3 +74,37 @@ public struct SlowRenderNode: RenderNode { return IndexSet(result) } } + +public struct AlwaysRenderNode: RenderNode { + public let size: CGSize + public let children: [RenderNode] + public let positions: [CGPoint] + + public init(size: CGSize, children: [RenderNode], positions: [CGPoint]) { + self.size = size + self.children = children + self.positions = positions + } + + public func visibleRenderables(in frame: CGRect) -> [Renderable] { + var result = [Renderable]() + for i in 0.. Badge { Badge( child: self, @@ -52,9 +52,9 @@ extension Component { ) } public func badge( - verticalAlignment: CrossAxisAlignment = .start, - horizontalAlignment: CrossAxisAlignment = .end, - offset: CGVector = .zero, + verticalAlignment: Badge.Alignment = .start, + horizontalAlignment: Badge.Alignment = .end, + offset: CGPoint = .zero, _ component: () -> Component ) -> Badge { Badge(