From ae6f3836dce830f12325830151a356f7c5c3454b Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 10 Nov 2024 22:34:13 +0800 Subject: [PATCH] Add AbsoluteEdge support --- .../LayoutAdjustments/Edge/AbsoluteEdge.swift | 68 +++++++++++++++++++ .../Alignment/AlignmentIDTests.swift | 5 +- .../Edge/AbsoluteEdgeTests.swift | 55 +++++++++++++++ 3 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 Sources/OpenSwiftUICore/Layout/LayoutAdjustments/Edge/AbsoluteEdge.swift create mode 100644 Tests/OpenSwiftUICoreTests/Layout/LayoutAdjustments/Edge/AbsoluteEdgeTests.swift diff --git a/Sources/OpenSwiftUICore/Layout/LayoutAdjustments/Edge/AbsoluteEdge.swift b/Sources/OpenSwiftUICore/Layout/LayoutAdjustments/Edge/AbsoluteEdge.swift new file mode 100644 index 00000000..46b849a7 --- /dev/null +++ b/Sources/OpenSwiftUICore/Layout/LayoutAdjustments/Edge/AbsoluteEdge.swift @@ -0,0 +1,68 @@ +// +// AbsoluteEdge.swift +// OpenSwiftUICore +// +// Audited for iOS 18.0 +// Status: Complete + +package enum AbsoluteEdge: Int8, CaseIterable, Hashable { + case top, left, bottom, right + + package struct Set: OptionSet { + package let rawValue: Int8 + package init(rawValue: Int8) { self.rawValue = rawValue } + package static let top: AbsoluteEdge.Set = .init(.top) + package static let left: AbsoluteEdge.Set = .init(.left) + package static let bottom: AbsoluteEdge.Set = .init(.bottom) + package static let right: AbsoluteEdge.Set = .init(.right) + package static let all: AbsoluteEdge.Set = [.top, .left, .bottom, .right] + package static let horizontal: AbsoluteEdge.Set = [.left, .right] + package static let vertical: AbsoluteEdge.Set = [.top, .bottom] + package init(_ e: AbsoluteEdge) { + self.init(rawValue: 1 << e.rawValue) + } + package func contains(_ e: AbsoluteEdge) -> Bool { + self.contains(.init(e)) + } + } +} + +extension AbsoluteEdge.Set { + package init(_ edges: Edge.Set, layoutDirection: LayoutDirection) { + var result: AbsoluteEdge.Set = [] + if edges.contains(.top) { + result.insert(.top) + } + if edges.contains(.leading) { + switch layoutDirection { + case .leftToRight: result.insert(.left) + case .rightToLeft: result.insert(.right) + } + } + if edges.contains(.bottom) { + result.insert(.bottom) + } + if edges.contains(.trailing) { + switch layoutDirection { + case .leftToRight: result.insert(.right) + case .rightToLeft: result.insert(.left) + } + } + self = result + } +} + +extension AbsoluteEdge { + package var horizontal: Bool { + self == .left || self == .right + } + + package var opposite: AbsoluteEdge { + switch self { + case .top: .bottom + case .left: .right + case .bottom: .top + case .right: .left + } + } +} diff --git a/Tests/OpenSwiftUICoreTests/Layout/LayoutAdjustments/Alignment/AlignmentIDTests.swift b/Tests/OpenSwiftUICoreTests/Layout/LayoutAdjustments/Alignment/AlignmentIDTests.swift index 518d491f..0763dc0a 100644 --- a/Tests/OpenSwiftUICoreTests/Layout/LayoutAdjustments/Alignment/AlignmentIDTests.swift +++ b/Tests/OpenSwiftUICoreTests/Layout/LayoutAdjustments/Alignment/AlignmentIDTests.swift @@ -1,9 +1,6 @@ // // AlignmentIDTests.swift -// -// -// Created by Kyle on 2023/12/16. -// +// OpenSwiftUICoreTests @testable import OpenSwiftUICore import Testing diff --git a/Tests/OpenSwiftUICoreTests/Layout/LayoutAdjustments/Edge/AbsoluteEdgeTests.swift b/Tests/OpenSwiftUICoreTests/Layout/LayoutAdjustments/Edge/AbsoluteEdgeTests.swift new file mode 100644 index 00000000..f7394323 --- /dev/null +++ b/Tests/OpenSwiftUICoreTests/Layout/LayoutAdjustments/Edge/AbsoluteEdgeTests.swift @@ -0,0 +1,55 @@ +// +// AbsoluteEdgeTests.swift +// OpenSwiftUICoreTests + +import Testing +import OpenSwiftUICore + +struct AbsoluteEdgeTests { + @Test + func testEdgeValues() { + #expect(AbsoluteEdge.top.rawValue == 0) + #expect(AbsoluteEdge.left.rawValue == 1) + #expect(AbsoluteEdge.bottom.rawValue == 2) + #expect(AbsoluteEdge.right.rawValue == 3) + } + + @Test + func testEdgeSetInitialization() { + let topSet = AbsoluteEdge.Set(.top) + let leftSet = AbsoluteEdge.Set(.left) + let bottomSet = AbsoluteEdge.Set(.bottom) + let rightSet = AbsoluteEdge.Set(.right) + + #expect(topSet.rawValue == 1 << 0) + #expect(leftSet.rawValue == 1 << 1) + #expect(bottomSet.rawValue == 1 << 2) + #expect(rightSet.rawValue == 1 << 3) + } + + @Test + func testEdgeSetContains() { + let horizontalSet = AbsoluteEdge.Set.horizontal + #expect(horizontalSet.contains(.left)) + #expect(horizontalSet.contains(.right)) + #expect(!horizontalSet.contains(.top)) + #expect(!horizontalSet.contains(.bottom)) + } + + @Test + func testEdgeSetFromEdgeSet() { + // Test LTR layout direction + let ltrSet = AbsoluteEdge.Set(.leading, layoutDirection: .leftToRight) + #expect(ltrSet.contains(.left)) + #expect(!ltrSet.contains(.right)) + #expect(!ltrSet.contains(.top)) + #expect(!ltrSet.contains(.bottom)) + + // Test RTL layout direction + let rtlSet = AbsoluteEdge.Set(.leading, layoutDirection: .rightToLeft) + #expect(rtlSet.contains(.right)) + #expect(!rtlSet.contains(.left)) + #expect(!rtlSet.contains(.top)) + #expect(!rtlSet.contains(.bottom)) + } +}