104 lines
3.5 KiB
Swift
104 lines
3.5 KiB
Swift
//
|
|
// EitherView.swift
|
|
// Adwaita
|
|
//
|
|
// Created by david-swift on 22.08.23.
|
|
//
|
|
|
|
import GTUI
|
|
|
|
/// 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.
|
|
/// - Parameter storage: The view storage.
|
|
public func update(_ storage: ViewStorage) {
|
|
let stack = storage.view as? Stack
|
|
updateContent(storage, state: true, stack: stack)
|
|
updateContent(storage, state: false, stack: stack)
|
|
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.
|
|
private func updateContent(_ storage: ViewStorage, state: Bool, stack: Stack?) {
|
|
let activeView = (state ? trueView : falseView)?.widget()
|
|
if let view = storage.content["\(state)"]?[safe: 0] {
|
|
activeView?.updateStorage(view)
|
|
} else if let view = activeView?.storage() {
|
|
_ = 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.
|
|
/// - Returns: The view storage.
|
|
public func container() -> ViewStorage {
|
|
let stack = Stack()
|
|
var content: [String: [ViewStorage]] = [:]
|
|
if let trueView {
|
|
let view = trueView.widget().storage()
|
|
_ = stack.append(view.view)
|
|
content["\(true)"] = [view]
|
|
}
|
|
if let falseView {
|
|
let view = falseView.widget().storage()
|
|
_ = 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)
|
|
}
|
|
|
|
}
|