Replace EitherView by the more powerful ViewStack
This commit is contained in:
parent
b9cdec32c9
commit
37252f7b8f
@ -20,7 +20,6 @@
|
||||
- [Button](structs/Button.md)
|
||||
- [Clamp](structs/Clamp.md)
|
||||
- [ContentModifier](structs/ContentModifier.md)
|
||||
- [EitherView](structs/EitherView.md)
|
||||
- [FileDialog](structs/FileDialog.md)
|
||||
- [HStack](structs/HStack.md)
|
||||
- [HeaderBar](structs/HeaderBar.md)
|
||||
@ -43,6 +42,7 @@
|
||||
- [Toggle](structs/Toggle.md)
|
||||
- [ToolbarView](structs/ToolbarView.md)
|
||||
- [VStack](structs/VStack.md)
|
||||
- [ViewStack](structs/ViewStack.md)
|
||||
- [Window](structs/Window.md)
|
||||
|
||||
## Classes
|
||||
|
||||
42
Documentation/Reference/structs/ViewStack.md
Normal file
42
Documentation/Reference/structs/ViewStack.md
Normal file
@ -0,0 +1,42 @@
|
||||
**STRUCT**
|
||||
|
||||
# `ViewStack`
|
||||
|
||||
A widget holding multiple children but only displaying one.
|
||||
|
||||
## Properties
|
||||
### `content`
|
||||
|
||||
The stack's active content.
|
||||
|
||||
### `id`
|
||||
|
||||
The stack's active identifier.
|
||||
|
||||
## Methods
|
||||
### `init(id:view:)`
|
||||
|
||||
Initialize the stack.
|
||||
- Parameters:
|
||||
- id: The identifier of the current view.
|
||||
- view: The current view.
|
||||
|
||||
### `init(element:view:)`
|
||||
|
||||
Initialize the stack.
|
||||
- Parameters:
|
||||
- element: The current identifiable element.
|
||||
- view: The current view.
|
||||
|
||||
### `container(modifiers:)`
|
||||
|
||||
Get a stack's view storage.
|
||||
- Parameter modifiers: Modify views before being updated.
|
||||
- Returns: The stack's view storage.
|
||||
|
||||
### `update(_:modifiers:)`
|
||||
|
||||
Update a stack's view storage.
|
||||
- Parameters:
|
||||
- storage: The view storage.
|
||||
- modifiers: Modify views before being updated.
|
||||
@ -58,9 +58,9 @@ public enum ViewBuilder {
|
||||
/// - Returns: A nonoptional component.
|
||||
public static func buildOptional(_ component: Component?) -> Component {
|
||||
if let component {
|
||||
return .element(EitherView(true, { buildFinalResult(component) }, else: nil))
|
||||
return .element(ViewStack(id: true) { _ in buildFinalResult(component) })
|
||||
} else {
|
||||
return .element(EitherView(false, nil) { [] })
|
||||
return .element(ViewStack(id: false) { _ in [] })
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,14 +68,14 @@ public enum ViewBuilder {
|
||||
/// - Parameter component: A component.
|
||||
/// - Returns: The component.
|
||||
public static func buildEither(first component: Component) -> Component {
|
||||
.element(EitherView(true, { buildFinalResult(component) }, else: nil))
|
||||
.element(ViewStack(id: true) { _ in buildFinalResult(component) })
|
||||
}
|
||||
|
||||
/// Enables support for `if`-`else` and `switch` statements.
|
||||
/// - Parameter component: A component.
|
||||
/// - Returns: The component.
|
||||
public static func buildEither(second component: Component) -> Component {
|
||||
.element(EitherView(false, nil) { buildFinalResult(component) })
|
||||
.element(ViewStack(id: false) { _ in buildFinalResult(component) })
|
||||
}
|
||||
|
||||
/// Convert a component to an array of elements.
|
||||
|
||||
@ -1,107 +0,0 @@
|
||||
//
|
||||
// EitherView.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by david-swift on 22.08.23.
|
||||
//
|
||||
|
||||
import Libadwaita
|
||||
|
||||
/// An equivalent to GtkStack for two views.
|
||||
public struct EitherView: Widget {
|
||||
|
||||
/// The view that is displayed when `isTrue` is true.
|
||||
var trueView: Body?
|
||||
/// The view that is displayed when `isTrue` is false.
|
||||
var falseView: Body?
|
||||
/// The state.
|
||||
var isTrue: Bool
|
||||
|
||||
/// Initialize an `EitherView`.
|
||||
/// - Parameters:
|
||||
/// - isTrue: The state.
|
||||
/// - _: The view that is presented if `isTrue` is true.
|
||||
/// - else: The view that is presented if `isTrue` is false.
|
||||
public init(
|
||||
_ isTrue: Bool,
|
||||
@ViewBuilder _ trueView: @escaping () -> Body,
|
||||
@ViewBuilder else falseView: @escaping () -> Body
|
||||
) {
|
||||
self.init(isTrue, .some(trueView), else: .some(falseView))
|
||||
}
|
||||
|
||||
/// Initialize an `EitherView`.
|
||||
/// - Parameters:
|
||||
/// - isTrue: The state.
|
||||
/// - trueView: The view that is presented if `isTrue` is true.
|
||||
/// - falseView: The view that is presented if `isTrue` is false.
|
||||
init(_ isTrue: Bool, _ trueView: (() -> Body)? = nil, else falseView: (() -> Body)? = nil) {
|
||||
self.trueView = trueView?()
|
||||
self.falseView = falseView?()
|
||||
self.isTrue = isTrue
|
||||
}
|
||||
|
||||
/// Update an `EitherView`'s storage.
|
||||
/// - Parameters:
|
||||
/// - storage: The view storage.
|
||||
/// - modifiers: Modify views before being updated.
|
||||
public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) {
|
||||
let stack = storage.view as? Stack
|
||||
updateContent(storage, state: true, stack: stack, modifiers: modifiers)
|
||||
updateContent(storage, state: false, stack: stack, modifiers: modifiers)
|
||||
if isTrue, let trueView = storage.content["\(true)"]?.last?.view {
|
||||
setVisible(stack, view: trueView)
|
||||
} else if !isTrue, let falseView = storage.content["\(false)"]?.last?.view {
|
||||
setVisible(stack, view: falseView)
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the content of a view in the view storage.
|
||||
/// - Parameters:
|
||||
/// - storage: The view storage.
|
||||
/// - state: Whether it is the true or false view.
|
||||
/// - stack: The stack.
|
||||
/// - modifiers: Modify views before being updated.
|
||||
private func updateContent(_ storage: ViewStorage, state: Bool, stack: Stack?, modifiers: [(View) -> View]) {
|
||||
let activeView = (state ? trueView : falseView)?.widget(modifiers: modifiers)
|
||||
if let view = storage.content["\(state)"]?[safe: 0] {
|
||||
activeView?.updateStorage(view, modifiers: modifiers)
|
||||
} else if let view = activeView?.storage(modifiers: modifiers) {
|
||||
_ = stack?.append(view.view)
|
||||
storage.content["\(state)"] = [view]
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the visible content page.
|
||||
/// - Parameters:
|
||||
/// - stack: The stack.
|
||||
/// - view: The visible view.
|
||||
private func setVisible(_ stack: Stack?, view: NativeWidgetPeer) {
|
||||
stack?.setVisible(view, transition: view.fields[.transition] as? Transition)
|
||||
}
|
||||
|
||||
/// Get a GtkStack view storage.
|
||||
/// - Parameter modifiers: Modify views before being updated.
|
||||
/// - Returns: The view storage.
|
||||
public func container(modifiers: [(View) -> View]) -> ViewStorage {
|
||||
let stack = Stack()
|
||||
var content: [String: [ViewStorage]] = [:]
|
||||
if let trueView {
|
||||
let view = trueView.widget(modifiers: modifiers).storage(modifiers: modifiers)
|
||||
_ = stack.append(view.view)
|
||||
content["\(true)"] = [view]
|
||||
}
|
||||
if let falseView {
|
||||
let view = falseView.widget(modifiers: modifiers).storage(modifiers: modifiers)
|
||||
_ = stack.append(view.view)
|
||||
content["\(false)"] = [view]
|
||||
}
|
||||
if isTrue, let trueView = content["\(true)"]?.last?.view {
|
||||
stack.setVisible(trueView)
|
||||
} else if let falseView = content["\(false)"]?.last?.view {
|
||||
stack.setVisible(falseView)
|
||||
}
|
||||
return .init(stack, content: content)
|
||||
}
|
||||
|
||||
}
|
||||
72
Sources/Adwaita/View/ViewStack.swift
Normal file
72
Sources/Adwaita/View/ViewStack.swift
Normal file
@ -0,0 +1,72 @@
|
||||
//
|
||||
// ViewStack.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by david-swift on 30.12.23.
|
||||
//
|
||||
|
||||
import Libadwaita
|
||||
|
||||
/// A widget holding multiple children but only displaying one.
|
||||
public struct ViewStack: Widget {
|
||||
|
||||
/// The stack's active content.
|
||||
var content: Body
|
||||
/// The stack's active identifier.
|
||||
var id: CustomStringConvertible
|
||||
|
||||
/// Initialize the stack.
|
||||
/// - Parameters:
|
||||
/// - id: The identifier of the current view.
|
||||
/// - view: The current view.
|
||||
public init<Identifier>(
|
||||
id: Identifier,
|
||||
@ViewBuilder view: @escaping (Identifier) -> Body
|
||||
) where Identifier: CustomStringConvertible {
|
||||
content = view(id)
|
||||
self.id = id
|
||||
}
|
||||
|
||||
/// Initialize the stack.
|
||||
/// - Parameters:
|
||||
/// - element: The current identifiable element.
|
||||
/// - view: The current view.
|
||||
public init<Element>(
|
||||
element: Element,
|
||||
@ViewBuilder view: @escaping (Element) -> Body
|
||||
) where Element: Identifiable, Element.ID: CustomStringConvertible {
|
||||
content = view(element)
|
||||
self.id = element.id
|
||||
}
|
||||
|
||||
/// Get a stack's view storage.
|
||||
/// - Parameter modifiers: Modify views before being updated.
|
||||
/// - Returns: The stack's view storage.
|
||||
public func container(modifiers: [(View) -> View]) -> ViewStorage {
|
||||
let stack = Stack()
|
||||
let storage = ViewStorage(stack)
|
||||
update(storage, modifiers: modifiers)
|
||||
return storage
|
||||
}
|
||||
|
||||
/// Update a stack's view storage.
|
||||
/// - Parameters:
|
||||
/// - storage: The view storage.
|
||||
/// - modifiers: Modify views before being updated.
|
||||
public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) {
|
||||
if let stack = storage.view as? Stack {
|
||||
let widget = content.widget(modifiers: modifiers)
|
||||
if let view = storage.content[id.description]?.first {
|
||||
widget.updateStorage(view, modifiers: modifiers)
|
||||
} else {
|
||||
let view = widget.storage(modifiers: modifiers)
|
||||
_ = stack.append(view.view)
|
||||
storage.content[id.description] = [view]
|
||||
}
|
||||
if let visibleView = storage.content[id.description]?.first?.view {
|
||||
_ = stack.setVisible(visibleView, transition: visibleView.fields[.transition] as? Transition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,7 @@ This is an overview of the available widgets and other components in _Adwaita_.
|
||||
| Name | Description | Widget |
|
||||
| -------------------- | ----------------------------------------------------------------- | ---------------------- |
|
||||
| Button | A widget that triggers a function when being clicked. | GtkButton |
|
||||
| EitherView | A widget that displays one of its child views based on a boolean. | GtkStack |
|
||||
| ViewStack | A widget that displays one of its child views based on an id. | GtkStack |
|
||||
| HeaderBar | A widget for creating custom title bars for windows. | GtkHeaderBar |
|
||||
| Text | A widget for displaying a small amount of text. | GtkLabel |
|
||||
| VStack | A widget which arranges child widgets into a single column. | GtkBox |
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user