From faffc6da0f18216c4b28250e6f0094b49eec2526 Mon Sep 17 00:00:00 2001 From: david-swift Date: Sun, 5 Jan 2025 11:07:46 +0100 Subject: [PATCH] Add support for frame --- .../Core/Model/Enumerations/Alignment.swift | 37 ++++++++ .../Enumerations/HorizontalAlignment.swift | 32 +++++++ .../Enumerations/VerticalAlignment.swift | 32 +++++++ Sources/Core/View/FrameWrapper.swift | 95 +++++++++++++++++++ Sources/MacBackend/AnyView.swift | 32 +++++++ 5 files changed, 228 insertions(+) create mode 100644 Sources/Core/Model/Enumerations/Alignment.swift create mode 100644 Sources/Core/Model/Enumerations/HorizontalAlignment.swift create mode 100644 Sources/Core/Model/Enumerations/VerticalAlignment.swift create mode 100644 Sources/Core/View/FrameWrapper.swift diff --git a/Sources/Core/Model/Enumerations/Alignment.swift b/Sources/Core/Model/Enumerations/Alignment.swift new file mode 100644 index 0000000..0a8a28e --- /dev/null +++ b/Sources/Core/Model/Enumerations/Alignment.swift @@ -0,0 +1,37 @@ +// +// Alignment.swift +// MacBackend +// +// Created by david-swift on 05.01.2025. +// + +import SwiftUI + +/// The two-dimensional alignment, consisting of the vertical and horizontal alignment. +public struct Alignment { + + /// The center alignment. + public static var center: Self { + .init(vertical: .center, horizontal: .center) + } + + /// The vertical alignment. + var vertical: VerticalAlignment + /// The horizontal alignment. + var horizontal: HorizontalAlignment + + /// The SwiftUI alignment. + var swiftUI: SwiftUI.Alignment { + .init(horizontal: horizontal.swiftUI, vertical: vertical.swiftUI) + } + + /// Initialize an alignment. + /// - Parameters: + /// - vertical: The vertical alignment. + /// - horizontal: The horizontal alignment. + public init(vertical: VerticalAlignment, horizontal: HorizontalAlignment) { + self.vertical = vertical + self.horizontal = horizontal + } + +} diff --git a/Sources/Core/Model/Enumerations/HorizontalAlignment.swift b/Sources/Core/Model/Enumerations/HorizontalAlignment.swift new file mode 100644 index 0000000..0ce7a2a --- /dev/null +++ b/Sources/Core/Model/Enumerations/HorizontalAlignment.swift @@ -0,0 +1,32 @@ +// +// HorizontalAlignment.swift +// MacBackend +// +// Created by david-swift on 05.01.25. +// + +import SwiftUI + +/// The horizontal alignment. +public enum HorizontalAlignment { + + /// The leading alignment. + case leading + /// The center alignment. + case center + /// The trailing alignment. + case trailing + + /// The SwiftUI alignment. + var swiftUI: SwiftUI.HorizontalAlignment { + switch self { + case .leading: + .leading + case .center: + .center + case .trailing: + .trailing + } + } + +} diff --git a/Sources/Core/Model/Enumerations/VerticalAlignment.swift b/Sources/Core/Model/Enumerations/VerticalAlignment.swift new file mode 100644 index 0000000..f63a5c2 --- /dev/null +++ b/Sources/Core/Model/Enumerations/VerticalAlignment.swift @@ -0,0 +1,32 @@ +// +// VerticalAlignment.swift +// MacBackend +// +// Created by david-swift on 05.01.25. +// + +import SwiftUI + +/// The vertical alignment. +public enum VerticalAlignment { + + /// The top alignment. + case top + /// The center alignment. + case center + /// The bottom alignment. + case bottom + + /// The SwiftUI alignment. + var swiftUI: SwiftUI.VerticalAlignment { + switch self { + case .top: + .top + case .center: + .center + case .bottom: + .bottom + } + } + +} diff --git a/Sources/Core/View/FrameWrapper.swift b/Sources/Core/View/FrameWrapper.swift new file mode 100644 index 0000000..bb4d006 --- /dev/null +++ b/Sources/Core/View/FrameWrapper.swift @@ -0,0 +1,95 @@ +// +// FrameWrapper.swift +// MacBackend +// +// Created by david-swift on 05.01.2025. +// + +import SwiftUI + +/// Wrap a view with a view that defines the wrapped view's frame. +public struct FrameWrapper: SwiftUIWidget { + + /// The wrapped view. + var content: Body + /// The minimum width. + var minWidth: Double? + /// The ideal width. + var idealWidth: Double? + /// The maximum width. + var maxWidth: Double? + /// The minimum height. + var minHeight: Double? + /// The ideal height. + var idealHeight: Double? + /// The maximum height. + var maxHeight: Double? + /// The alignment inside the frame. + var alignment: Alignment + + /// The wrapped views. + public var wrappedViews: [String: Meta.AnyView] { + [.mainContent: content] + } + + /// Initialize a wrapper view defining a view's frame. + /// - Parameters: + /// - minWidth: The minimum width. + /// - idealWidth: The ideal width. + /// - maxWidth: The maximum width. + /// - minHeight: The minimum height. + /// - idealHeight: The ideal height. + /// - maxHeight: The maximum height. + /// - alignment: The alignment inside the view's frame. + /// - content: The wrapped view. + public init( + minWidth: Double? = nil, + idealWidth: Double? = nil, + maxWidth: Double? = nil, + minHeight: Double? = nil, + idealHeight: Double? = nil, + maxHeight: Double? = nil, + alignment: Alignment = .center, + @Meta.ViewBuilder content: () -> Body + ) { + self.content = content() + self.minWidth = minWidth + self.idealWidth = idealWidth + self.maxWidth = maxWidth + self.minHeight = minHeight + self.idealHeight = idealHeight + self.maxHeight = maxHeight + self.alignment = alignment + } + + /// Get the SwiftUI view. + /// - Parameter properties: The widget data. + /// - Returns: The SwiftUI view. + public static func view(properties: Self) -> some SwiftUI.View { + MacBackendView(.mainContent) + .frame( + minWidth: .init(properties.minWidth), + idealWidth: .init(properties.idealWidth), + maxWidth: .init(properties.maxWidth), + minHeight: .init(properties.minHeight), + idealHeight: .init(properties.idealHeight), + maxHeight: .init(properties.maxHeight), + alignment: properties.alignment.swiftUI + ) + } + +} + +extension CGFloat { + + /// Initialize a `CGFloat` from a `Double`. + /// - Parameter value: The double value. + public init?(_ value: Double?) { + if let value { + self = .init(value) + } else { + return nil + } + } + +} diff --git a/Sources/MacBackend/AnyView.swift b/Sources/MacBackend/AnyView.swift index cb9a5ec..993c0c5 100644 --- a/Sources/MacBackend/AnyView.swift +++ b/Sources/MacBackend/AnyView.swift @@ -72,4 +72,36 @@ extension AnyView { .init(isPresented: isPresented, content: { self }, dialog: dialog) } + /// Define a view's frame. + /// - Parameters: + /// - minWidth: The minimum width. + /// - idealWidth: The ideal width. + /// - maxWidth: The maximum width. + /// - minHeight: The minimum height. + /// - idealHeight: The ideal height. + /// - maxHeight: The maximum height. + /// - alignment: The alignment inside the view's frame. + /// - Returns: The view. + public func frame( + minWidth: Double? = nil, + idealWidth: Double? = nil, + maxWidth: Double? = nil, + minHeight: Double? = nil, + idealHeight: Double? = nil, + maxHeight: Double? = nil, + alignment: Alignment = .center + ) -> AnyView { + FrameWrapper( + minWidth: minWidth, + idealWidth: idealWidth, + maxWidth: maxWidth, + minHeight: minHeight, + idealHeight: idealHeight, + maxHeight: maxHeight, + alignment: alignment + ) { + self + } + } + }