Add support for command bars
This commit is contained in:
parent
29715462f8
commit
c7a0fccde0
@ -27,17 +27,19 @@ let package = Package(
|
|||||||
url: "https://git.aparoksha.dev/aparoksha/levenshtein-transformations",
|
url: "https://git.aparoksha.dev/aparoksha/levenshtein-transformations",
|
||||||
branch: "main"
|
branch: "main"
|
||||||
),
|
),
|
||||||
.package(url: "https://github.com/thebrowsercompany/swift-winui", branch: "main"),
|
|
||||||
.package(url: "https://github.com/thebrowsercompany/swift-windowsappsdk", branch: "main"),
|
.package(url: "https://github.com/thebrowsercompany/swift-windowsappsdk", branch: "main"),
|
||||||
.package(url: "https://github.com/thebrowsercompany/swift-windowsfoundation", branch: "main")
|
.package(url: "https://github.com/thebrowsercompany/swift-windowsfoundation", branch: "main"),
|
||||||
|
.package(url: "https://github.com/thebrowsercompany/swift-cwinrt", branch: "main"),
|
||||||
|
.package(url: "https://github.com/AparokshaUI/winui", branch: "main")
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(
|
.target(
|
||||||
name: "Core",
|
name: "Core",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.product(name: "WinUI", package: "swift-winui"),
|
.product(name: "WinUI", package: "winui"),
|
||||||
.product(name: "WinAppSDK", package: "swift-windowsappsdk"),
|
.product(name: "WinAppSDK", package: "swift-windowsappsdk"),
|
||||||
.product(name: "WindowsFoundation", package: "swift-windowsfoundation"),
|
.product(name: "WindowsFoundation", package: "swift-windowsfoundation"),
|
||||||
|
.product(name: "CWinRT", package: "swift-cwinrt"),
|
||||||
.product(name: "LevenshteinTransformations", package: "levenshtein-transformations"),
|
.product(name: "LevenshteinTransformations", package: "levenshtein-transformations"),
|
||||||
.product(name: "Meta", package: "meta")
|
.product(name: "Meta", package: "meta")
|
||||||
]
|
]
|
||||||
|
71
Sources/Core/CommandBarContent/CommandBarCollection.swift
Normal file
71
Sources/Core/CommandBarContent/CommandBarCollection.swift
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// CommandBarCollection.swift
|
||||||
|
// WinUI
|
||||||
|
//
|
||||||
|
// Created by david-swift on 01.11.2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import WindowsFoundation
|
||||||
|
import WinUI
|
||||||
|
|
||||||
|
/// A collection of command bar elements.
|
||||||
|
public struct CommandBarCollection: CommandBarWidget, Wrapper {
|
||||||
|
|
||||||
|
/// The content of the collection.
|
||||||
|
var content: Body
|
||||||
|
|
||||||
|
/// Initialize a command bar collection.
|
||||||
|
/// - Parameter content: The content of the collection.
|
||||||
|
public init(@ViewBuilder content: @escaping () -> Body) {
|
||||||
|
self.content = content()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The view storage.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - modifiers: Modify the views before updating.
|
||||||
|
/// - type: The type of the views.
|
||||||
|
/// - Returns: The view storage.
|
||||||
|
public func container<Data>(
|
||||||
|
data: WidgetData,
|
||||||
|
type: Data.Type
|
||||||
|
) -> ViewStorage where Data: ViewRenderData {
|
||||||
|
let storages = content.storages(data: data, type: type)
|
||||||
|
var items: [ICommandBarElement?] = []
|
||||||
|
getItems(items: &items, storages: storages)
|
||||||
|
return .init(items, content: [.mainContent: storages])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the stored content.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - storage: The storage to update.
|
||||||
|
/// - modifiers: Modify the views before updating.
|
||||||
|
/// - updateProperties: Whether to update the properties.
|
||||||
|
/// - type: The type of the views.
|
||||||
|
public func update<Data>(
|
||||||
|
_ storage: ViewStorage,
|
||||||
|
data: WidgetData,
|
||||||
|
updateProperties: Bool,
|
||||||
|
type: Data.Type
|
||||||
|
) where Data: ViewRenderData {
|
||||||
|
guard let storages = storage.content[.mainContent] else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
content.update(storages, data: data, updateProperties: updateProperties, type: type)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the child items of the collection.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - items: Pass the variable that will store the items.
|
||||||
|
/// - storages: The storages.
|
||||||
|
func getItems(items: inout [ICommandBarElement?], storages: [ViewStorage]) {
|
||||||
|
for item in storages {
|
||||||
|
if let item = item.pointer as? ICommandBarElement {
|
||||||
|
items.append(item)
|
||||||
|
} else {
|
||||||
|
items += item.pointer as? [ICommandBarElement] ?? []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
Sources/Core/CommandBarContent/CommandBarContext.swift
Normal file
21
Sources/Core/CommandBarContent/CommandBarContext.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// CommandBarContext.swift
|
||||||
|
// WinUI
|
||||||
|
//
|
||||||
|
// Created by david-swift on 01.11.24.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// The command bar context.
|
||||||
|
public enum CommandBarContext: ViewRenderData {
|
||||||
|
|
||||||
|
/// The type of the widgets.
|
||||||
|
public typealias WidgetType = CommandBarWidget
|
||||||
|
/// The wrapper type.
|
||||||
|
public typealias WrapperType = CommandBarCollection
|
||||||
|
/// The either view type.
|
||||||
|
public typealias EitherViewType = CommandBarEitherView
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type of the widgets.
|
||||||
|
public protocol CommandBarWidget: Meta.Widget { }
|
23
Sources/Core/CommandBarContent/CommandBarEitherView.swift
Normal file
23
Sources/Core/CommandBarContent/CommandBarEitherView.swift
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// CommandBarView.swift
|
||||||
|
// WinUI
|
||||||
|
//
|
||||||
|
// Created by david-swift on 01.11.2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Show one of two views depending on a condition.
|
||||||
|
public struct CommandBarEitherView: Meta.EitherView, SimpleView {
|
||||||
|
|
||||||
|
/// The view.
|
||||||
|
public var view: Body
|
||||||
|
|
||||||
|
/// Initialize an either view.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - condition: The condition.
|
||||||
|
/// - view1: The first view.
|
||||||
|
/// - view2: The second view.
|
||||||
|
public init(_ condition: Bool, view1: () -> Body, else view2: () -> Body) {
|
||||||
|
self.view = condition ? view1() : view2()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,15 +8,22 @@
|
|||||||
import WinUI
|
import WinUI
|
||||||
|
|
||||||
/// A button widget for menus.
|
/// A button widget for menus.
|
||||||
public struct Separator: MenuWidget {
|
public struct Separator: MenuWidget, CommandBarWidget {
|
||||||
|
|
||||||
/// Initialize a separator menu item.
|
/// Initialize a separator menu item.
|
||||||
public init() { }
|
public init() { }
|
||||||
|
|
||||||
/// Initialize the widget.
|
/// The view storage.
|
||||||
/// - Returns: The widget.
|
/// - Parameters:
|
||||||
public func initializeWidget() -> Any {
|
/// - data: The widget data.
|
||||||
MenuFlyoutSeparator()
|
/// - type: The view render data type.
|
||||||
|
/// - Returns: The view storage.
|
||||||
|
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data : ViewRenderData {
|
||||||
|
if type == CommandBarContext.self {
|
||||||
|
.init(AppBarSeparator())
|
||||||
|
} else {
|
||||||
|
.init(MenuFlyoutSeparator())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
57
Sources/Core/View/AppBar/AppBarButton.swift
Normal file
57
Sources/Core/View/AppBar/AppBarButton.swift
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// AppBarButton.swift
|
||||||
|
// WinUI
|
||||||
|
//
|
||||||
|
// Created by david-swift on 01.11.24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import CWinRT
|
||||||
|
import WinUI
|
||||||
|
|
||||||
|
/// A button.
|
||||||
|
public struct AppBarButton: WinUIWidget, CommandBarWidget {
|
||||||
|
|
||||||
|
/// The action to run when the button gets clicked.
|
||||||
|
@Property(
|
||||||
|
set: { button, closure, storage in
|
||||||
|
if storage.fields["click"] == nil {
|
||||||
|
button.click.addHandler { _, _ in
|
||||||
|
(storage.fields["click"] as? () -> Void)?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
storage.fields["click"] = closure
|
||||||
|
},
|
||||||
|
pointer: WinUI.AppBarButton.self
|
||||||
|
)
|
||||||
|
var action: (() -> Void)?
|
||||||
|
/// The label.
|
||||||
|
@Property(
|
||||||
|
set: { $0.label = $1 },
|
||||||
|
pointer: WinUI.AppBarButton.self
|
||||||
|
)
|
||||||
|
var label: String?
|
||||||
|
/// The icon.
|
||||||
|
@Property(
|
||||||
|
set: { $0.icon = $1.winIcon },
|
||||||
|
pointer: WinUI.AppBarButton.self
|
||||||
|
)
|
||||||
|
var icon: Icon?
|
||||||
|
|
||||||
|
/// Initialize an app bar button.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - label: The button's label.
|
||||||
|
/// - icon: An icon representing the action.
|
||||||
|
/// - action: The button's action.
|
||||||
|
public init(_ label: String, icon: Icon, action: @escaping () -> Void) {
|
||||||
|
self.action = action
|
||||||
|
self.label = label
|
||||||
|
self.icon = icon
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize the widget.
|
||||||
|
/// - Returns: The widget.
|
||||||
|
public func initializeWidget() -> Any {
|
||||||
|
WinUI.AppBarButton()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
105
Sources/Core/View/AppBar/CommandBar.swift
Normal file
105
Sources/Core/View/AppBar/CommandBar.swift
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
//
|
||||||
|
// CommandBar.swift
|
||||||
|
// WinUI
|
||||||
|
//
|
||||||
|
// Created by david-swift on 01.11.24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import CWinRT
|
||||||
|
import WinUI
|
||||||
|
|
||||||
|
/// A command bar.
|
||||||
|
public struct CommandBar: WinUIWidget {
|
||||||
|
|
||||||
|
/// The primary commands.
|
||||||
|
var primaryCommands: Body
|
||||||
|
/// The secondary commands.
|
||||||
|
var secondaryCommands: Body
|
||||||
|
/// Additional content.
|
||||||
|
var content: Body = []
|
||||||
|
/// Whether the labels are positioned right to the icon.
|
||||||
|
var rightLabelPosition = false
|
||||||
|
|
||||||
|
/// Initialize a command bar.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - primary: The primary commands.
|
||||||
|
/// - secondary: The secondary commands.
|
||||||
|
public init(@ViewBuilder primary: () -> Body, @ViewBuilder secondary: () -> Body = { [] }) {
|
||||||
|
primaryCommands = primary()
|
||||||
|
secondaryCommands = secondary()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The view storage.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - data: The widget data.
|
||||||
|
/// - type: The view render data type.
|
||||||
|
/// - Returns: The view storage.
|
||||||
|
public func container<Data>(
|
||||||
|
data: WidgetData,
|
||||||
|
type: Data.Type
|
||||||
|
) -> ViewStorage where Data: ViewRenderData {
|
||||||
|
let bar = WinUI.CommandBar()
|
||||||
|
let storage = ViewStorage(bar)
|
||||||
|
let primary = CommandBarCollection { primaryCommands }.container(data: data.noModifiers, type: CommandBarContext.self)
|
||||||
|
storage.content["primary"] = [primary]
|
||||||
|
if let primary = primary.pointer as? [ICommandBarElement?] {
|
||||||
|
primary.forEach { bar.primaryCommands.append($0) }
|
||||||
|
}
|
||||||
|
let secondary = CommandBarCollection { secondaryCommands }.container(data: data.noModifiers, type: CommandBarContext.self)
|
||||||
|
storage.content["secondary"] = [secondary]
|
||||||
|
if let secondary = secondary.pointer as? [ICommandBarElement?] {
|
||||||
|
secondary.forEach { bar.secondaryCommands.append($0) }
|
||||||
|
}
|
||||||
|
let content = content.storage(data: data, type: type)
|
||||||
|
storage.content[.mainContent] = [content]
|
||||||
|
bar.content = content.pointer as? UIElement
|
||||||
|
update(storage, data: data, updateProperties: true, type: type)
|
||||||
|
return storage
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the stored content.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - storage: The storage to update.
|
||||||
|
/// - data: The widget data.
|
||||||
|
/// - updateProperties: Whether to update the view's properties.
|
||||||
|
/// - type: The view render data type.
|
||||||
|
public func update<Data>(
|
||||||
|
_ storage: ViewStorage,
|
||||||
|
data: WidgetData,
|
||||||
|
updateProperties: Bool,
|
||||||
|
type: Data.Type
|
||||||
|
) where Data: ViewRenderData {
|
||||||
|
if let content = storage.content["primary"]?.first {
|
||||||
|
CommandBarCollection { primaryCommands }.updateStorage(
|
||||||
|
content,
|
||||||
|
data: data.noModifiers,
|
||||||
|
updateProperties: updateProperties,
|
||||||
|
type: CommandBarContext.self
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if let content = storage.content["secondary"]?.first {
|
||||||
|
CommandBarCollection { secondaryCommands }.updateStorage(
|
||||||
|
content,
|
||||||
|
data: data.noModifiers,
|
||||||
|
updateProperties: updateProperties,
|
||||||
|
type: CommandBarContext.self
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if let content = storage.content[.mainContent]?.first {
|
||||||
|
self.content.updateStorage(content, data: data, updateProperties: updateProperties, type: type)
|
||||||
|
}
|
||||||
|
if updateProperties, (storage.previousState as? Self)?.rightLabelPosition != rightLabelPosition {
|
||||||
|
(storage.pointer as? WinUI.CommandBar)?.defaultLabelPosition = rightLabelPosition ? .right : .bottom
|
||||||
|
storage.previousState = self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func content(@ViewBuilder content: () -> Body) -> Self {
|
||||||
|
modify { $0.content = content() }
|
||||||
|
}
|
||||||
|
|
||||||
|
public func rightLabelPosition(_ enabled: Bool = true) -> Self {
|
||||||
|
modify { $0.rightLabelPosition = enabled }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// VStack.swift
|
// Button.swift
|
||||||
// WinUI
|
// WinUI
|
||||||
//
|
//
|
||||||
// Created by david-swift on 11.10.24.
|
// Created by david-swift on 11.10.24.
|
||||||
|
64
Sources/Core/View/HStack.swift
Normal file
64
Sources/Core/View/HStack.swift
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// VStack.swift
|
||||||
|
// WinUI
|
||||||
|
//
|
||||||
|
// Created by david-swift on 11.10.24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import WinUI
|
||||||
|
|
||||||
|
/// A container arranging its children vertically.
|
||||||
|
public struct HStack: WinUIWidget {
|
||||||
|
|
||||||
|
/// The content.
|
||||||
|
var content: Body
|
||||||
|
|
||||||
|
/// Initialize the wrapper.
|
||||||
|
/// - Parameter content: The view content.
|
||||||
|
public init(@ViewBuilder content: () -> Body) {
|
||||||
|
self.content = content()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The view storage.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - data: The widget data.
|
||||||
|
/// - type: The view render data type.
|
||||||
|
/// - Returns: The view storage.
|
||||||
|
public func container<Data>(
|
||||||
|
data: WidgetData,
|
||||||
|
type: Data.Type
|
||||||
|
) -> ViewStorage where Data: ViewRenderData {
|
||||||
|
if content.count == 1, let view = content.first {
|
||||||
|
return view.storage(data: data, type: type)
|
||||||
|
}
|
||||||
|
let stack = StackPanel()
|
||||||
|
stack.orientation = .horizontal
|
||||||
|
let storages = content.storages(data: data, type: type)
|
||||||
|
for storage in storages {
|
||||||
|
stack.children.append(storage.pointer as? UIElement)
|
||||||
|
}
|
||||||
|
return .init(stack, content: [.mainContent: storages])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the stored content.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - storage: The storage to update.
|
||||||
|
/// - data: The widget data.
|
||||||
|
/// - updateProperties: Whether to update the view's properties.
|
||||||
|
/// - type: The view render data type.
|
||||||
|
public func update<Data>(
|
||||||
|
_ storage: ViewStorage,
|
||||||
|
data: WidgetData,
|
||||||
|
updateProperties: Bool,
|
||||||
|
type: Data.Type
|
||||||
|
) where Data: ViewRenderData {
|
||||||
|
if content.count == 1, let view = content.first {
|
||||||
|
view.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let storages = storage.content[.mainContent] {
|
||||||
|
content.update(storages, data: data, updateProperties: updateProperties, type: type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,7 +8,7 @@
|
|||||||
import WinUI
|
import WinUI
|
||||||
|
|
||||||
/// A wrapper view for modifiers.
|
/// A wrapper view for modifiers.
|
||||||
public struct ModifierWrapper: WinUIWidget {
|
public struct ModifierWrapper: WinUIWidget, CommandBarWidget {
|
||||||
|
|
||||||
/// The content view.
|
/// The content view.
|
||||||
var view: AnyView
|
var view: AnyView
|
||||||
@ -26,6 +26,8 @@ public struct ModifierWrapper: WinUIWidget {
|
|||||||
var verticalAlignment: VerticalAlignment?
|
var verticalAlignment: VerticalAlignment?
|
||||||
/// The grid column.
|
/// The grid column.
|
||||||
var gridColumn: Int?
|
var gridColumn: Int?
|
||||||
|
/// Whether the element is displayed.
|
||||||
|
var visible: Bool?
|
||||||
|
|
||||||
// swiftlint:disable large_tuple
|
// swiftlint:disable large_tuple
|
||||||
/// Initialize the modifier wrapper.
|
/// Initialize the modifier wrapper.
|
||||||
@ -37,6 +39,7 @@ public struct ModifierWrapper: WinUIWidget {
|
|||||||
/// - horizontalAlignment: The horizontal alignment.
|
/// - horizontalAlignment: The horizontal alignment.
|
||||||
/// - verticalAlignment: The vertical alignment.
|
/// - verticalAlignment: The vertical alignment.
|
||||||
/// - gridColumn: The grid column.
|
/// - gridColumn: The grid column.
|
||||||
|
/// - visible: Whether the view is visible.
|
||||||
public init(
|
public init(
|
||||||
view: AnyView,
|
view: AnyView,
|
||||||
width: Double? = nil,
|
width: Double? = nil,
|
||||||
@ -44,7 +47,8 @@ public struct ModifierWrapper: WinUIWidget {
|
|||||||
margin: (Double, Double, Double, Double)? = nil,
|
margin: (Double, Double, Double, Double)? = nil,
|
||||||
horizontalAlignment: HorizontalAlignment? = nil,
|
horizontalAlignment: HorizontalAlignment? = nil,
|
||||||
verticalAlignment: VerticalAlignment? = nil,
|
verticalAlignment: VerticalAlignment? = nil,
|
||||||
gridColumn: Int? = nil
|
gridColumn: Int? = nil,
|
||||||
|
visible: Bool? = nil
|
||||||
) {
|
) {
|
||||||
self.view = view
|
self.view = view
|
||||||
self.width = width
|
self.width = width
|
||||||
@ -53,6 +57,7 @@ public struct ModifierWrapper: WinUIWidget {
|
|||||||
self.horizontalAlignment = horizontalAlignment
|
self.horizontalAlignment = horizontalAlignment
|
||||||
self.verticalAlignment = verticalAlignment
|
self.verticalAlignment = verticalAlignment
|
||||||
self.gridColumn = gridColumn
|
self.gridColumn = gridColumn
|
||||||
|
self.visible = visible
|
||||||
}
|
}
|
||||||
// swiftlint:enable large_tuple
|
// swiftlint:enable large_tuple
|
||||||
|
|
||||||
@ -62,7 +67,9 @@ public struct ModifierWrapper: WinUIWidget {
|
|||||||
/// - type: The view render data type.
|
/// - type: The view render data type.
|
||||||
/// - Returns: The view storage.
|
/// - Returns: The view storage.
|
||||||
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
|
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
|
||||||
let storage = view.storage(data: data, type: type)
|
let content = view.storage(data: data, type: type)
|
||||||
|
let storage = ViewStorage(content.pointer)
|
||||||
|
storage.content[.mainContent] = [content]
|
||||||
update(storage, data: data, updateProperties: true, type: type)
|
update(storage, data: data, updateProperties: true, type: type)
|
||||||
return storage
|
return storage
|
||||||
}
|
}
|
||||||
@ -79,7 +86,9 @@ public struct ModifierWrapper: WinUIWidget {
|
|||||||
updateProperties: Bool,
|
updateProperties: Bool,
|
||||||
type: Data.Type
|
type: Data.Type
|
||||||
) where Data: ViewRenderData {
|
) where Data: ViewRenderData {
|
||||||
view.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
if let storage = storage.content[.mainContent]?.first {
|
||||||
|
view.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
||||||
|
}
|
||||||
guard updateProperties, let view = storage.pointer as? WinUI.FrameworkElement else {
|
guard updateProperties, let view = storage.pointer as? WinUI.FrameworkElement else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -102,6 +111,9 @@ public struct ModifierWrapper: WinUIWidget {
|
|||||||
if let gridColumn, previousState?.gridColumn != gridColumn {
|
if let gridColumn, previousState?.gridColumn != gridColumn {
|
||||||
WinUI.Grid.setColumn(view, .init(gridColumn))
|
WinUI.Grid.setColumn(view, .init(gridColumn))
|
||||||
}
|
}
|
||||||
|
if let visible, previousState?.visible != visible {
|
||||||
|
view.visibility = visible ? .visible : .collapsed
|
||||||
|
}
|
||||||
storage.previousState = self
|
storage.previousState = self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,32 @@ public struct NavigationView<Item>: WinUIWidget where Item: NavigationViewItem {
|
|||||||
var paneCustomContent: Body?
|
var paneCustomContent: Body?
|
||||||
/// The display mode of the navigation view.
|
/// The display mode of the navigation view.
|
||||||
var mode: NavigationViewMode = .sidebar
|
var mode: NavigationViewMode = .sidebar
|
||||||
|
/// The primary commands in the header.
|
||||||
|
var primaryCommands: Body = []
|
||||||
|
/// The secondary commands in the header.
|
||||||
|
var secondaryCommands: Body = []
|
||||||
|
/// The label for the settings item.
|
||||||
|
var settingsLabel: String?
|
||||||
|
|
||||||
|
/// The view's header.
|
||||||
|
var header: AnyView? {
|
||||||
|
if let settingsLabel {
|
||||||
|
Grid {
|
||||||
|
Text(selectedItem.description ?? settingsLabel)
|
||||||
|
ModifierWrapper(
|
||||||
|
view: CommandBar {
|
||||||
|
primaryCommands
|
||||||
|
} secondary: {
|
||||||
|
secondaryCommands
|
||||||
|
},
|
||||||
|
margin: (0, 0, 50, 0),
|
||||||
|
horizontalAlignment: .right
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Initialize the navigation view without the settings item.
|
/// Initialize the navigation view without the settings item.
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
@ -62,6 +88,16 @@ public struct NavigationView<Item>: WinUIWidget where Item: NavigationViewItem {
|
|||||||
/// A custom item.
|
/// A custom item.
|
||||||
case custom(item: Item)
|
case custom(item: Item)
|
||||||
|
|
||||||
|
/// The item's description.
|
||||||
|
var description: String? {
|
||||||
|
switch self {
|
||||||
|
case .settings:
|
||||||
|
nil
|
||||||
|
case let .custom(item):
|
||||||
|
item.description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The view storage.
|
/// The view storage.
|
||||||
@ -86,6 +122,10 @@ public struct NavigationView<Item>: WinUIWidget where Item: NavigationViewItem {
|
|||||||
storage.content["pane-custom-content"] = [customStorage]
|
storage.content["pane-custom-content"] = [customStorage]
|
||||||
view.paneCustomContent = customStorage.pointer as? UIElement
|
view.paneCustomContent = customStorage.pointer as? UIElement
|
||||||
}
|
}
|
||||||
|
if let header = header?.storage(data: data, type: type) {
|
||||||
|
view.header = header.pointer
|
||||||
|
storage.content["header"] = [header]
|
||||||
|
}
|
||||||
if settings {
|
if settings {
|
||||||
view.isSettingsVisible = true
|
view.isSettingsVisible = true
|
||||||
} else {
|
} else {
|
||||||
@ -113,6 +153,9 @@ public struct NavigationView<Item>: WinUIWidget where Item: NavigationViewItem {
|
|||||||
if let content = storage.content["pane-custom-content"]?.first {
|
if let content = storage.content["pane-custom-content"]?.first {
|
||||||
paneCustomContent?.updateStorage(content, data: data, updateProperties: updateProperties, type: type)
|
paneCustomContent?.updateStorage(content, data: data, updateProperties: updateProperties, type: type)
|
||||||
}
|
}
|
||||||
|
if let content = storage.content["header"]?.first {
|
||||||
|
header?.updateStorage(content, data: data, updateProperties: updateProperties, type: type)
|
||||||
|
}
|
||||||
guard let navigationView = storage.pointer as? WinUI.NavigationView else {
|
guard let navigationView = storage.pointer as? WinUI.NavigationView else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -163,6 +206,24 @@ public struct NavigationView<Item>: WinUIWidget where Item: NavigationViewItem {
|
|||||||
modify { $0.paneCustomContent = content() }
|
modify { $0.paneCustomContent = content() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The view's header.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - settingsLabel: The label for the settings item.
|
||||||
|
/// - primary: The primary command bar items.
|
||||||
|
/// - secondary: The secondary command bar items.
|
||||||
|
/// - Returns:
|
||||||
|
public func header(
|
||||||
|
settingsLabel: String,
|
||||||
|
@ViewBuilder primary: () -> Body,
|
||||||
|
@ViewBuilder secondary: () -> Body = { [] }
|
||||||
|
) -> Self {
|
||||||
|
modify { view in
|
||||||
|
view.settingsLabel = settingsLabel
|
||||||
|
view.primaryCommands = primary()
|
||||||
|
view.secondaryCommands = secondary()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The navigation selection type.
|
/// The navigation selection type.
|
||||||
|
@ -52,6 +52,12 @@ struct ContentView: View {
|
|||||||
.verticalAlignment(.center)
|
.verticalAlignment(.center)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.header(settingsLabel: "Settings") {
|
||||||
|
AppBarButton("Delete", icon: .systemIcon(unicode: "\u{E74D}")) {
|
||||||
|
print("Delete")
|
||||||
|
}
|
||||||
|
.visible(selectedItem != .shop)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder var menu: Body {
|
@ViewBuilder var menu: Body {
|
||||||
|
@ -53,4 +53,11 @@ extension AnyView {
|
|||||||
ModifierWrapper(view: self, gridColumn: column)
|
ModifierWrapper(view: self, gridColumn: column)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the view is visible.
|
||||||
|
/// - Parameter visible: Whether the view is visible.
|
||||||
|
/// - Returns: The view.
|
||||||
|
public func visible(_ visible: Bool? = true) -> AnyView {
|
||||||
|
ModifierWrapper(view: self, visible: visible)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user