Add support for pickers
All checks were successful
Deploy Docs / publish (push) Successful in 3m3s
SwiftLint / SwiftLint (push) Successful in 3s

This commit is contained in:
david-swift 2024-12-09 21:15:52 +01:00
parent 43f53e1681
commit badc0c12f6
4 changed files with 131 additions and 8 deletions

View File

@ -0,0 +1,59 @@
//
// Picker.swift
// MacBackend
//
// Created by david-swift on 08.12.2024.
//
import SwiftUI
/// A picker view.
public struct Picker<Item>: SwiftUIWidget where Item: Hashable, Item: CustomStringConvertible {
/// The selected item.
@Meta.Binding var selection: Item
/// The picker's label.
var label: String
/// The picker's items.
var items: [Item]
/// Whether to use the segmented picker stlye.
var segmented = false
/// Initialize the picker.
/// - Parameters:
/// - label: The picker's label.
/// - items: The picker's items.
/// - selection: The selected item.
public init(_ label: String, items: [Item], selection: Meta.Binding<Item>) {
self._selection = selection
self.label = label
self.items = items
}
/// Get the SwiftUI view.
/// - Parameter properties: The widget data.
/// - Returns: The SwiftUI view.
public static func view(properties: Picker<Item>) -> some SwiftUI.View {
let picker = SwiftUI.Picker(properties.label, selection: properties._selection.swiftUI) {
ForEach(properties.items, id: \.hashValue) { item in
SwiftUI.Text(item.description)
.tag(item.description)
}
}
if properties.segmented {
picker
.pickerStyle(.segmented)
} else {
picker
.pickerStyle(.automatic)
}
}
/// Make the picker segmented.
/// - Parameter segmented: Whether the picker is segmented.
/// - Returns: The picker.
public func segmented(_ segmented: Bool = true) -> Self {
modify { $0.segmented = segmented }
}
}

View File

@ -14,6 +14,8 @@ public struct ToolbarView: SwiftUIWidget {
var child: Meta.AnyView var child: Meta.AnyView
/// The toolbar views. /// The toolbar views.
var toolbarViews: Body var toolbarViews: Body
/// The toolbar type.
var toolbarType: ToolbarType = .end
/// The wrapped views. /// The wrapped views.
public var wrappedViews: [String: Meta.AnyView] { public var wrappedViews: [String: Meta.AnyView] {
@ -25,22 +27,61 @@ public struct ToolbarView: SwiftUIWidget {
/// Initialize the padding view. /// Initialize the padding view.
/// - Parameters: /// - Parameters:
/// - child: The wrapped view. /// - child: The wrapped view.
/// - type: The position.
/// - toolbarViews: The views in the toolbar. /// - toolbarViews: The views in the toolbar.
public init(child: Meta.AnyView, @Meta.ViewBuilder toolbarViews: () -> Body) { public init(child: Meta.AnyView, type: ToolbarType, @Meta.ViewBuilder toolbarViews: () -> Body) {
self.child = child self.child = child
self.toolbarViews = toolbarViews() self.toolbarViews = toolbarViews()
self.toolbarType = type
}
/// The type of toolbar.
public enum ToolbarType {
/// A leading toolbar.
case start
/// A trailing toolbar.
case end
/// A centered toolbar.
case center
} }
/// Get the SwiftUI view. /// Get the SwiftUI view.
/// - Parameter properties: The widget data. /// - Parameter properties: The widget data.
/// - Returns: The SwiftUI view. /// - Returns: The SwiftUI view.
public static func view(properties: Self) -> some SwiftUI.View { public static func view(properties: Self) -> some SwiftUI.View {
MacBackendView(.mainContent) switch properties.toolbarType {
.toolbar { case .end:
ForEach(properties.toolbarViews.indices, id: \.self) { index in MacBackendView(.mainContent)
MacBackendView("\(index)") .toolbar {
ForEach(properties.toolbarViews.indices, id: \.self) { index in
MacBackendView("\(index)")
}
} }
} case .start:
MacBackendView(.mainContent)
.toolbar {
ToolbarItem(placement: .navigation) {
SwiftUI.HStack {
ForEach(properties.toolbarViews.indices, id: \.self) { index in
MacBackendView("\(index)")
}
}
}
}
case .center:
MacBackendView(.mainContent)
.toolbar {
ToolbarItem(placement: .principal) {
SwiftUI.HStack {
ForEach(properties.toolbarViews.indices, id: \.self) { index in
MacBackendView("\(index)")
}
}
}
}
}
} }
} }

View File

@ -25,8 +25,17 @@ struct Demo: App {
@State private var selectedElement: String? @State private var selectedElement: String?
@State private var alert = false @State private var alert = false
@State private var menuPresented = false @State private var menuPresented = false
@State private var selection = "Hello"
var scene: Scene { var scene: Scene {
Window(id: "secondary") { _ in
Text(selection)
.centeredToolbar {
Picker("Test", items: ["Hello", "World"], selection: $selection)
.segmented()
}
}
.frame(width: .constant(800), height: .constant(600))
Window("Main", id: "main") { _ in Window("Main", id: "main") { _ in
NavigationSplitView { NavigationSplitView {
List(elements, selection: $selectedElement) { element in List(elements, selection: $selectedElement) { element in

View File

@ -39,11 +39,25 @@ extension AnyView {
MenuWrapper(content: { self }, isPresented: isPresented, menu: menu) MenuWrapper(content: { self }, isPresented: isPresented, menu: menu)
} }
/// Set the toolbar. /// Add toolbar items to the end.
/// - Parameter content: The toolbar's content. /// - Parameter content: The toolbar's content.
/// - Returns: The view. /// - Returns: The view.
public func toolbar(@ViewBuilder content: () -> Body) -> AnyView { public func toolbar(@ViewBuilder content: () -> Body) -> AnyView {
ToolbarView(child: self, toolbarViews: content) ToolbarView(child: self, type: .end, toolbarViews: content)
}
/// Add toolbar items to the start.
/// - Parameter content: The toolbar's content.
/// - Returns: The view.
public func leadingToolbar(@ViewBuilder content: () -> Body) -> AnyView {
ToolbarView(child: self, type: .start, toolbarViews: content)
}
/// Add centered toolbar items.
/// - Parameter content: The toolbar's content.
/// - Returns: The view.
public func centeredToolbar(@ViewBuilder content: () -> Body) -> AnyView {
ToolbarView(child: self, type: .center, toolbarViews: content)
} }
} }