Support window overlays for a certain instance

Specify the parent window in the `addWindow(_:parent:)` function
This commit is contained in:
david-swift 2023-12-07 21:48:31 +01:00
parent e4737558b2
commit d5b43344a1
6 changed files with 34 additions and 9 deletions

View File

@ -17,6 +17,10 @@ The app's content.
The scenes that are displayed. The scenes that are displayed.
### `overwriteParentID`
A string signaling that the parent should not be overwritten.
## Methods ## Methods
### `init(_:body:)` ### `init(_:body:)`
@ -35,11 +39,12 @@ Focus the window with a certain id. Create the window if it doesn't already exis
- Parameters: - Parameters:
- id: The window's id. - id: The window's id.
### `addWindow(_:)` ### `addWindow(_:parent:)`
Add a new window with the content of the window with a certain id. Add a new window with the content of the window with a certain id.
- Parameters: - Parameters:
- id: The window's id. - id: The window's id.
- parent: The parent window.
### `setParentWindows()` ### `setParentWindows()`

View File

@ -17,6 +17,8 @@ public class GTUIApp: Application {
var body: () -> App var body: () -> App
/// The scenes that are displayed. /// The scenes that are displayed.
var sceneStorage: [WindowStorage] = [] var sceneStorage: [WindowStorage] = []
/// A string signaling that the parent should not be overwritten.
let overwriteParentID = "overwrite-parent"
/// Initialize the GTUI application. /// Initialize the GTUI application.
/// - Parameters: /// - Parameters:
@ -48,11 +50,16 @@ public class GTUIApp: Application {
/// Add a new window with the content of the window with a certain id. /// Add a new window with the content of the window with a certain id.
/// - Parameters: /// - Parameters:
/// - id: The window's id. /// - id: The window's id.
public func addWindow(_ id: String) { /// - parent: The parent window.
public func addWindow(_ id: String, parent: GTUIWindow? = nil) {
State<Any>.updateViews() State<Any>.updateViews()
if let window = body().scene.windows().last(where: { $0.id == id }) { if let window = body().scene.windows().last(where: { $0.id == id }) {
let window = window.createWindow(app: self) let window = window.createWindow(app: self)
sceneStorage.append(window) sceneStorage.append(window)
if let parent {
window.window.setParent(parent)
window.window.fields[overwriteParentID] = true
}
setParentWindows() setParentWindows()
showWindow(id) showWindow(id)
} }
@ -60,7 +67,7 @@ public class GTUIApp: Application {
/// Set the parents of every window having a parent window. /// Set the parents of every window having a parent window.
func setParentWindows() { func setParentWindows() {
for window in sceneStorage { for window in sceneStorage where !(window.window.fields[overwriteParentID] as? Bool ?? false) {
if let parent = sceneStorage.first(where: { $0.id == window.parentID }) { if let parent = sceneStorage.first(where: { $0.id == window.parentID }) {
window.window.setParent(parent.window) window.window.setParent(parent.window)
} }

View File

@ -76,7 +76,7 @@ struct Demo: App {
} }
.keyboardShortcut("w".ctrl()) .keyboardShortcut("w".ctrl())
MenuSection { MenuSection {
MenuButton("About", window: false) { app.showWindow("about") } MenuButton("About") { app.addWindow("about", parent: window); print(window.nativePtr) }
MenuButton("Quit", window: false) { app.quit() } MenuButton("Quit", window: false) { app.quit() }
.keyboardShortcut("q".ctrl()) .keyboardShortcut("q".ctrl())
} }
@ -90,7 +90,7 @@ struct Demo: App {
icon: selection.icon, icon: selection.icon,
description: selection.description description: selection.description
) { ) {
selection.view(app: app, toast: toast) selection.view(app: app, window: window, toast: toast)
} }
.topToolbar { .topToolbar {
HeaderBar.empty() HeaderBar.empty()

View File

@ -12,11 +12,12 @@ import Adwaita
struct OverlayWindowDemo: View { struct OverlayWindowDemo: View {
var app: GTUIApp! var app: GTUIApp!
var window: GTUIApplicationWindow
var view: Body { var view: Body {
VStack { VStack {
Button("Show Window") { Button("Show Window") {
app.showWindow("overlay") app.addWindow("overlay", parent: window)
} }
.style("pill") .style("pill")
.frame(maxSize: 100) .frame(maxSize: 100)

View File

@ -65,7 +65,7 @@ enum Page: String, Identifiable, CaseIterable {
} }
@ViewBuilder @ViewBuilder
func view(app: GTUIApp!, toast: Signal) -> Body { func view(app: GTUIApp!, window: GTUIApplicationWindow, toast: Signal) -> Body {
switch self { switch self {
case .welcome: case .welcome:
[] []
@ -80,7 +80,7 @@ enum Page: String, Identifiable, CaseIterable {
case .dice: case .dice:
DiceDemo() DiceDemo()
case .overlayWindow: case .overlayWindow:
OverlayWindowDemo(app: app) OverlayWindowDemo(app: app, window: window)
case .toast: case .toast:
ToastDemo(toast: toast) ToastDemo(toast: toast)
} }

View File

@ -69,7 +69,7 @@ It should be used for opening windows that cannot be presented more than once
and for moving a window that is already open into the foreground. and for moving a window that is already open into the foreground.
## Adding Windows ## Adding Windows
You can call the `addWindow(_:)` function instead of the `showWindow(_:)` You can call the `addWindow(_:parent:)` function instead of the `showWindow(_:)`
if you want to add and focus another instance of a window type: if you want to add and focus another instance of a window type:
```swift ```swift
@main @main
@ -96,6 +96,18 @@ struct HelloWorld: App {
} }
``` ```
It can be used to add an overlay window to a certain instance of a window type
by specifying the `parent` parameter, e.g. in the example above:
```swift
Window(id: "control") { window in
HeaderBar.empty()
Button("Add Child Window") {
// Add the new instance as a child window of this window
app.addWindow("content", parent: window)
}
.padding()
}
```
## Customizing the Initial Number of Windows ## Customizing the Initial Number of Windows
By default, every window type of the app's scene appears once when the app starts. By default, every window type of the app's scene appears once when the app starts.