Window.swift 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #if !os(WASI)
  2. import Foundation
  3. #endif
  4. /// A scene that presents a single window.
  5. public struct Window<Content: View>: WindowingScene {
  6. public typealias Node = WindowNode<Content>
  7. /// The title of the window (shown in the title bar on most OSes).
  8. var title: String
  9. /// The window's content.
  10. var content: () -> Content
  11. /// The window's ID.
  12. ///
  13. /// This should never change after creation.
  14. let id: String
  15. /// Creates a window scene specifying a title and an ID.
  16. public init(
  17. _ title: String,
  18. id: String,
  19. @ViewBuilder _ content: @escaping () -> Content
  20. ) {
  21. self.id = id
  22. self.title = title
  23. self.content = content
  24. }
  25. }
  26. /// The ``SceneGraphNode`` corresponding to a ``Window`` scene.
  27. public final class WindowNode<Content: View>: SceneGraphNode {
  28. public typealias NodeScene = Window<Content>
  29. /// The reference to the underlying window object, which also manages
  30. /// the window's view graph.
  31. ///
  32. /// `nil` if the window is closed.
  33. var windowReference: WindowReference<Window<Content>>? = nil
  34. /// The underlying scene.
  35. private var scene: Window<Content>
  36. public init<Backend: BaseAppBackend>(
  37. from scene: Window<Content>,
  38. backend: Backend,
  39. environment: EnvironmentValues
  40. ) {
  41. self.scene = scene
  42. let openOnAppLaunch =
  43. switch environment.defaultLaunchBehavior {
  44. case .presented: true
  45. case .automatic, .suppressed: false
  46. }
  47. if openOnAppLaunch {
  48. self.windowReference = WindowReference(
  49. scene: scene,
  50. backend: backend,
  51. environment: environment,
  52. onClose: { self.windowReference = nil },
  53. id: scene.id
  54. )
  55. }
  56. }
  57. public func updateNode(
  58. _ newScene: NodeScene?,
  59. environment: EnvironmentValues
  60. ) -> SceneNodeUpdateResult {
  61. if let newScene {
  62. self.scene = newScene
  63. }
  64. return .leafScene()
  65. }
  66. public func update<Backend: BaseAppBackend>(
  67. backend: Backend,
  68. environment: EnvironmentValues
  69. ) {
  70. environment.openWindowFunctionsByID.value[scene.id] = { [weak self] in
  71. guard let self else { return }
  72. if let windowReference {
  73. // the window is already open: activate it
  74. windowReference.activate(backend: backend)
  75. } else {
  76. // the window is not open: create a new instance
  77. let reference = WindowReference(
  78. scene: scene,
  79. backend: backend,
  80. environment: environment,
  81. onClose: { self.windowReference = nil },
  82. id: scene.id
  83. )
  84. windowReference = reference
  85. reference.update(
  86. nil,
  87. backend: backend,
  88. environment: environment
  89. )
  90. }
  91. }
  92. windowReference?.update(
  93. scene,
  94. backend: backend,
  95. environment: environment
  96. )
  97. }
  98. }