From e294aefc3e64cd0baf3ddae75b6bdee1fbe35f42 Mon Sep 17 00:00:00 2001 From: bugperson Date: Sun, 4 Jun 2023 14:54:45 +0300 Subject: [PATCH] add axial alignment --- client/ios/Core/BasePublic/Alignment.swift | 13 -- .../Extensions/DivContainerExtensions.swift | 160 +++++++++++------- .../Blocks/Container/ContainerBlock.swift | 30 +++- .../Container/ContainerBlockExtensions.swift | 25 +-- .../Container/ContainerBlockLayout.swift | 4 +- ...ContainerBlock+UIViewRenderableBlock.swift | 2 +- .../TextBlock+UIViewRenderableBlock.swift | 4 - .../ViewModels/GalleryViewLayout.swift | 4 - .../ViewModels/PagerViewLayout.swift | 4 - .../Blocks/ContainerBlockLayoutTests.swift | 2 +- 10 files changed, 143 insertions(+), 105 deletions(-) diff --git a/client/ios/Core/BasePublic/Alignment.swift b/client/ios/Core/BasePublic/Alignment.swift index a31145b70..1c5140921 100644 --- a/client/ios/Core/BasePublic/Alignment.swift +++ b/client/ios/Core/BasePublic/Alignment.swift @@ -13,9 +13,6 @@ public enum Alignment { case center /// Child items are laid out at the right/bottom of the container case trailing - case spaceBetween - case spaceAround - case spaceEvenly } extension Alignment { @@ -30,10 +27,6 @@ extension Alignment { return ((availableSpace - contentSize) * 0.5).roundedToScreenScale case .trailing: return availableSpace - contentSize - // TODO: @bugperson should be implemented here DIVKIT-2378 - default: - assertionFailure("Others alignments not supported yet") - return 0 } } } @@ -47,12 +40,6 @@ extension Alignment: CustomDebugStringConvertible { return "Center" case .trailing: return "Trailing" - case .spaceBetween: - return "space-between" - case .spaceAround: - return "space-around" - case .spaceEvenly: - return "space-evenly" } } } diff --git a/client/ios/DivKit/Extensions/DivContainerExtensions.swift b/client/ios/DivKit/Extensions/DivContainerExtensions.swift index 8d6c01061..0422f1a03 100644 --- a/client/ios/DivKit/Extensions/DivContainerExtensions.swift +++ b/client/ios/DivKit/Extensions/DivContainerExtensions.swift @@ -150,16 +150,21 @@ extension DivContainer: DivBlockModeling { ) throws -> Block { let expressionResolver = context.expressionResolver let layoutDirection = orientation.layoutDirection - let axialAlignment: Alignment - let crossAlignment: ContainerBlock.CrossAlignment - switch layoutDirection { - case .horizontal: - axialAlignment = resolveContentAlignmentHorizontal(expressionResolver).alignment - crossAlignment = resolveContentAlignmentVertical(expressionResolver).crossAlignment - case .vertical: - axialAlignment = resolveContentAlignmentVertical(expressionResolver).alignment - crossAlignment = resolveContentAlignmentHorizontal(expressionResolver).crossAlignment - } + + let divContentAlignmentVertical = resolveContentAlignmentVertical(expressionResolver) + let divContentAlignmentHorizontal = resolveContentAlignmentHorizontal(expressionResolver) + + let axialAlignment = makeAxialAlignment( + layoutDirection, + verticalAlignment: divContentAlignmentVertical, + horizontalAlignment: divContentAlignmentHorizontal + ) + + let crossAlignment = makeCrossAlignment( + layoutDirection, + verticalAlignment: divContentAlignmentVertical, + horizontalAlignment: divContentAlignmentHorizontal + ) let fallbackWidth = getFallbackWidth( orientation: orientation, @@ -393,7 +398,7 @@ extension DivAlignmentVertical { } extension DivContentAlignmentHorizontal { - var alignment: Alignment { + fileprivate var alignment: Alignment { switch self { case .left: return .leading @@ -401,35 +406,15 @@ extension DivContentAlignmentHorizontal { return .center case .right: return .trailing - case .spaceBetween: - return .spaceBetween - case .spaceAround: - return .spaceAround - case .spaceEvenly: - return .spaceEvenly - } - } - - var crossAlignment: ContainerBlock.CrossAlignment { - switch self { - case .left: + case .spaceEvenly, .spaceAround, .spaceBetween: + DivKitLogger.warning("Alignment \(rawValue) is not supported") return .leading - case .center: - return .center - case .right: - return .trailing - case .spaceBetween: - return .spaceBetween - case .spaceAround: - return .spaceAround - case .spaceEvenly: - return .spaceEvenly } } } extension DivContentAlignmentVertical { - var alignment: Alignment { + fileprivate var alignment: Alignment { switch self { case .top: return .leading @@ -437,34 +422,9 @@ extension DivContentAlignmentVertical { return .center case .bottom: return .trailing - case .baseline: - DivKitLogger.warning("Baseline alignment not supported.") + case .spaceEvenly, .spaceAround, .spaceBetween, .baseline: + DivKitLogger.warning("Alignment \(rawValue) is not supported") return .leading - case .spaceBetween: - return .spaceBetween - case .spaceAround: - return .spaceAround - case .spaceEvenly: - return .spaceEvenly - } - } - - var crossAlignment: ContainerBlock.CrossAlignment { - switch self { - case .top: - return .leading - case .center: - return .center - case .bottom: - return .trailing - case .baseline: - return .baseline - case .spaceBetween: - return .spaceBetween - case .spaceAround: - return .spaceAround - case .spaceEvenly: - return .spaceEvenly } } } @@ -517,3 +477,81 @@ private let defaultFallbackSize = DivOverridenSize( original: .divMatchParentSize(DivMatchParentSize()), overriden: .divWrapContentSize(DivWrapContentSize(constrained: .value(true))) ) + + +fileprivate func makeCrossAlignment( + _ direction: ContainerBlock.LayoutDirection, + verticalAlignment: DivContentAlignmentVertical, + horizontalAlignment: DivContentAlignmentHorizontal +) -> ContainerBlock.CrossAlignment { + switch direction { + case .horizontal: + switch verticalAlignment { + case .top: + return .leading + case .center: + return .center + case .bottom: + return .trailing + case .baseline: + return .baseline + case .spaceBetween, .spaceEvenly, .spaceAround: + return .leading + } + case .vertical: + switch horizontalAlignment { + case .left: + return .leading + case .center: + return .center + case .right: + return .trailing + case .spaceBetween, .spaceEvenly, .spaceAround: + return .center + } + } +} + +fileprivate func makeAxialAlignment( + _ direction: ContainerBlock.LayoutDirection, + verticalAlignment: DivContentAlignmentVertical, + horizontalAlignment: DivContentAlignmentHorizontal +) -> ContainerBlock.AxialAlignment { + switch direction { + case .horizontal: + switch horizontalAlignment { + case .left: + return .leading + case .center: + return .center + case .right: + return .trailing + case .spaceBetween: + return .spaceBetween + case .spaceAround: + return .spaceAround + case .spaceEvenly: + return .spaceEvenly + } + case .vertical: + switch verticalAlignment { + case .top: + return .leading + case .center: + return .center + case .bottom: + return .trailing + case .baseline: + DivKitLogger.warning("Baseline alignment not supported.") + return .leading + case .spaceBetween: + return .spaceBetween + case .spaceAround: + return .spaceAround + case .spaceEvenly: + return .spaceEvenly + } + } +} + + diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift b/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift index baff8fceb..09e4ed3f1 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlock.swift @@ -46,6 +46,12 @@ public final class ContainerBlock: BlockWithLayout { case center case trailing case baseline + } + + public enum AxialAlignment { + case leading + case center + case trailing case spaceBetween case spaceAround case spaceEvenly @@ -86,7 +92,7 @@ public final class ContainerBlock: BlockWithLayout { public let layoutMode: LayoutMode public let widthTrait: LayoutTrait public let heightTrait: LayoutTrait - public let axialAlignment: Alignment + public let axialAlignment: AxialAlignment public let crossAlignment: CrossAlignment public let gaps: [CGFloat] public let children: [Child] @@ -105,7 +111,7 @@ public final class ContainerBlock: BlockWithLayout { layoutMode: LayoutMode = .noWrap, widthTrait: LayoutTrait = .resizable, heightTrait: LayoutTrait = .intrinsic, - axialAlignment: Alignment = .leading, + axialAlignment: AxialAlignment = .leading, crossAlignment: CrossAlignment = .leading, gaps: [CGFloat]? = nil, children: [Child], @@ -554,9 +560,23 @@ extension ContainerBlock.CrossAlignment { return ((availableSpace - contentSize) * 0.5).roundedToScreenScale case .trailing: return availableSpace - contentSize - // TODO: @bugperson should be implemented here DIVKIT-2378 - default: - assertionFailure("Others alignments not supported yet") + } + } +} + +extension ContainerBlock.AxialAlignment { + public func offset( + forAvailableSpace availableSpace: CGFloat, + contentSize: CGFloat = 0 + ) -> CGFloat { + switch self { + case .leading: + return 0 + case .center: + return ((availableSpace - contentSize) * 0.5).roundedToScreenScale + case .trailing: + return availableSpace - contentSize + case .spaceEvenly, .spaceBetween, .spaceAround: return 0 } } diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockExtensions.swift b/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockExtensions.swift index 04f2ea988..4da0abad9 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockExtensions.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockExtensions.swift @@ -9,7 +9,7 @@ extension ContainerBlock { layoutMode: LayoutMode? = nil, widthTrait: LayoutTrait? = nil, heightTrait: LayoutTrait? = nil, - axialAlignment: Alignment? = nil, + axialAlignment: AxialAlignment? = nil, crossAlignment: CrossAlignment? = nil, gaps: [CGFloat]? = nil, children: [Child]? = nil, @@ -51,15 +51,15 @@ extension ContainerBlock { clipContent: Bool = true, accessibilityElement: AccessibilityElement? = nil ) throws { - let axialAlignment: Alignment + let axialAlignment: AxialAlignment let crossAlignment: CrossAlignment switch layoutDirection { case .horizontal: - axialAlignment = horizontalChildrenAlignment + axialAlignment = horizontalChildrenAlignment.axialAlignment crossAlignment = verticalChildrenAlignment.crossAlignment case .vertical: - axialAlignment = verticalChildrenAlignment + axialAlignment = verticalChildrenAlignment.axialAlignment crossAlignment = horizontalChildrenAlignment.crossAlignment } @@ -94,12 +94,17 @@ extension Alignment { return .center case .trailing: return .trailing - case .spaceBetween: - return .spaceBetween - case .spaceAround: - return .spaceAround - case .spaceEvenly: - return .spaceEvenly + } + } + + fileprivate var axialAlignment: ContainerBlock.AxialAlignment { + switch self { + case .leading: + return .leading + case .center: + return .center + case .trailing: + return .trailing } } } diff --git a/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockLayout.swift b/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockLayout.swift index 30ccc8e5f..d0f3e82f3 100644 --- a/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockLayout.swift +++ b/client/ios/LayoutKit/LayoutKit/Blocks/Container/ContainerBlockLayout.swift @@ -33,7 +33,7 @@ struct ContainerBlockLayout { let gaps: [CGFloat] let layoutDirection: ContainerBlock.LayoutDirection let layoutMode: ContainerBlock.LayoutMode - let axialAlignment: Alignment + let axialAlignment: ContainerBlock.AxialAlignment let crossAlignment: ContainerBlock.CrossAlignment let size: CGSize @@ -44,7 +44,7 @@ struct ContainerBlockLayout { gaps: [CGFloat], layoutDirection: ContainerBlock.LayoutDirection, layoutMode: ContainerBlock.LayoutMode, - axialAlignment: Alignment, + axialAlignment: ContainerBlock.AxialAlignment, crossAlignment: ContainerBlock.CrossAlignment, size: CGSize ) { diff --git a/client/ios/LayoutKit/LayoutKit/UI/Blocks/ContainerBlock+UIViewRenderableBlock.swift b/client/ios/LayoutKit/LayoutKit/UI/Blocks/ContainerBlock+UIViewRenderableBlock.swift index 2da92c383..3d28b226c 100644 --- a/client/ios/LayoutKit/LayoutKit/UI/Blocks/ContainerBlock+UIViewRenderableBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/UI/Blocks/ContainerBlock+UIViewRenderableBlock.swift @@ -56,7 +56,7 @@ private final class ContainerBlockView: UIView, BlockViewProtocol, VisibleBounds let gaps: [CGFloat] let layoutDirection: ContainerBlock.LayoutDirection let layoutMode: ContainerBlock.LayoutMode - let axialAlignment: Alignment + let axialAlignment: ContainerBlock.AxialAlignment let crossAlignment: ContainerBlock.CrossAlignment let contentAnimation: BlockAnimation? let anchorPoint: AnchorPoint diff --git a/client/ios/LayoutKit/LayoutKit/UI/Blocks/TextBlock+UIViewRenderableBlock.swift b/client/ios/LayoutKit/LayoutKit/UI/Blocks/TextBlock+UIViewRenderableBlock.swift index 1fbbcdaa8..0028f69b8 100644 --- a/client/ios/LayoutKit/LayoutKit/UI/Blocks/TextBlock+UIViewRenderableBlock.swift +++ b/client/ios/LayoutKit/LayoutKit/UI/Blocks/TextBlock+UIViewRenderableBlock.swift @@ -458,10 +458,6 @@ extension Alignment { case .leading: return .top case .center: return .center case .trailing: return .bottom - // TODO: @bugperson should be implemented here DIVKIT-2378 - default: - assertionFailure("Others alignments not supported yet") - return .top } } } diff --git a/client/ios/LayoutKit/LayoutKit/ViewModels/GalleryViewLayout.swift b/client/ios/LayoutKit/LayoutKit/ViewModels/GalleryViewLayout.swift index d20a6a314..d65f87045 100644 --- a/client/ios/LayoutKit/LayoutKit/ViewModels/GalleryViewLayout.swift +++ b/client/ios/LayoutKit/LayoutKit/ViewModels/GalleryViewLayout.swift @@ -271,10 +271,6 @@ extension Alignment { return floor((minimum + maximum - dimension) / 2) case .trailing: return maximum - dimension - // TODO: @bugperson should be implemented here DIVKIT-2378 - default: - assertionFailure("Others alignments not supported yet") - return minimum } } } diff --git a/client/ios/LayoutKit/LayoutKit/ViewModels/PagerViewLayout.swift b/client/ios/LayoutKit/LayoutKit/ViewModels/PagerViewLayout.swift index 6f1dfc807..6db1cd67b 100644 --- a/client/ios/LayoutKit/LayoutKit/ViewModels/PagerViewLayout.swift +++ b/client/ios/LayoutKit/LayoutKit/ViewModels/PagerViewLayout.swift @@ -258,10 +258,6 @@ extension Alignment { return floor((minimum + maximum - dimension) / 2) case .trailing: return maximum - dimension - // TODO: @bugperson should be implemented here DIVKIT-2378 - default: - assertionFailure("Others alignments not supported yet") - return minimum } } } diff --git a/client/ios/LayoutKit/LayoutKitTests/Blocks/ContainerBlockLayoutTests.swift b/client/ios/LayoutKit/LayoutKitTests/Blocks/ContainerBlockLayoutTests.swift index 8cbd8f997..2822a47eb 100644 --- a/client/ios/LayoutKit/LayoutKitTests/Blocks/ContainerBlockLayoutTests.swift +++ b/client/ios/LayoutKit/LayoutKitTests/Blocks/ContainerBlockLayoutTests.swift @@ -12,7 +12,7 @@ extension ContainerBlockLayout { layoutDirection: ContainerBlock.LayoutDirection, layoutMode: ContainerBlock.LayoutMode = .noWrap, crossAlignment: ContainerBlock.CrossAlignment = .leading, - axialAlignment: Alignment = .leading, + axialAlignment: ContainerBlock.AxialAlignment = .leading, size: CGSize ) { self.init(