portico/Sources/Portico/App/MountableScene.swift

52 lines
2.1 KiB
Swift

import Adw
/// Identifies which conditional branch a scene tree selected.
///
/// Two scene values with equal identities select the same window slot, so the
/// runtime leaves the live window in place. The path is built outward: each
/// conditional wrapper prepends its own marker to the child's path.
@_spi(Portico) public struct SceneIdentity: Equatable, Sendable {
/// The branch markers, outermost first.
@_spi(Portico) public let path: [UInt8]
private init(path: [UInt8]) { self.path = path }
/// A scene that attaches a window directly, with no conditional above it.
@_spi(Portico) public static let leaf = SceneIdentity(path: [])
/// The selection made by an `if` whose condition is false and which has no `else`.
@_spi(Portico) public static let empty = SceneIdentity(path: [3])
/// Wraps `child` as the `if` branch of an `if`/`else`.
@_spi(Portico) public static func first(_ child: SceneIdentity) -> SceneIdentity {
SceneIdentity(path: [0] + child.path)
}
/// Wraps `child` as the `else` branch of an `if`/`else`.
@_spi(Portico) public static func second(_ child: SceneIdentity) -> SceneIdentity {
SceneIdentity(path: [1] + child.path)
}
/// Wraps `child` as the taken branch of a bare `if`.
@_spi(Portico) public static func present(_ child: SceneIdentity) -> SceneIdentity {
SceneIdentity(path: [2] + child.path)
}
}
/// SPI mount requirement for scenes - a standalone protocol (NOT a
/// refinement of `Scene`) so `Scene` stays public without exposing SPI
/// in its inheritance clause.
///
/// Dispatch uses `app.body as? MountableScene` (mirrors ``AnyView``'s
/// runtime-cast pattern). Conformers: ``ApplicationWindow``,
/// ``EitherScene``, and ``OptionalScene``.
@_spi(Portico) @MainActor public protocol MountableScene {
/// The branch-selection path of this scene tree.
var identity: SceneIdentity { get }
/// Builds and presents this scene's window.
///
/// - Returns: A handle for later dismantling, or `nil` when the scene
/// selects no window at all (a false bare `if`).
func attach(to app: Adw.Application) -> SceneHandle?
}