forked from aparoksha/adwaita-swift
Replace EitherView by the more powerful ViewStack
This commit is contained in:
parent
b9cdec32c9
commit
37252f7b8f
@ -20,7 +20,6 @@
|
|||||||
- [Button](structs/Button.md)
|
- [Button](structs/Button.md)
|
||||||
- [Clamp](structs/Clamp.md)
|
- [Clamp](structs/Clamp.md)
|
||||||
- [ContentModifier](structs/ContentModifier.md)
|
- [ContentModifier](structs/ContentModifier.md)
|
||||||
- [EitherView](structs/EitherView.md)
|
|
||||||
- [FileDialog](structs/FileDialog.md)
|
- [FileDialog](structs/FileDialog.md)
|
||||||
- [HStack](structs/HStack.md)
|
- [HStack](structs/HStack.md)
|
||||||
- [HeaderBar](structs/HeaderBar.md)
|
- [HeaderBar](structs/HeaderBar.md)
|
||||||
@ -43,6 +42,7 @@
|
|||||||
- [Toggle](structs/Toggle.md)
|
- [Toggle](structs/Toggle.md)
|
||||||
- [ToolbarView](structs/ToolbarView.md)
|
- [ToolbarView](structs/ToolbarView.md)
|
||||||
- [VStack](structs/VStack.md)
|
- [VStack](structs/VStack.md)
|
||||||
|
- [ViewStack](structs/ViewStack.md)
|
||||||
- [Window](structs/Window.md)
|
- [Window](structs/Window.md)
|
||||||
|
|
||||||
## Classes
|
## 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.
|
/// - Returns: A nonoptional component.
|
||||||
public static func buildOptional(_ component: Component?) -> Component {
|
public static func buildOptional(_ component: Component?) -> Component {
|
||||||
if let component {
|
if let component {
|
||||||
return .element(EitherView(true, { buildFinalResult(component) }, else: nil))
|
return .element(ViewStack(id: true) { _ in buildFinalResult(component) })
|
||||||
} else {
|
} else {
|
||||||
return .element(EitherView(false, nil) { [] })
|
return .element(ViewStack(id: false) { _ in [] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,14 +68,14 @@ public enum ViewBuilder {
|
|||||||
/// - Parameter component: A component.
|
/// - Parameter component: A component.
|
||||||
/// - Returns: The component.
|
/// - Returns: The component.
|
||||||
public static func buildEither(first component: Component) -> 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.
|
/// Enables support for `if`-`else` and `switch` statements.
|
||||||
/// - Parameter component: A component.
|
/// - Parameter component: A component.
|
||||||
/// - Returns: The component.
|
/// - Returns: The component.
|
||||||
public static func buildEither(second component: Component) -> 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.
|
/// 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 |
|
| Name | Description | Widget |
|
||||||
| -------------------- | ----------------------------------------------------------------- | ---------------------- |
|
| -------------------- | ----------------------------------------------------------------- | ---------------------- |
|
||||||
| Button | A widget that triggers a function when being clicked. | GtkButton |
|
| 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 |
|
| HeaderBar | A widget for creating custom title bars for windows. | GtkHeaderBar |
|
||||||
| Text | A widget for displaying a small amount of text. | GtkLabel |
|
| Text | A widget for displaying a small amount of text. | GtkLabel |
|
||||||
| VStack | A widget which arranges child widgets into a single column. | GtkBox |
|
| VStack | A widget which arranges child widgets into a single column. | GtkBox |
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user