From d5b43344a1102df2f7f00bf736e58d59f9013534 Mon Sep 17 00:00:00 2001 From: david-swift Date: Thu, 7 Dec 2023 21:48:31 +0100 Subject: [PATCH] Support window overlays for a certain instance Specify the parent window in the `addWindow(_:parent:)` function --- Documentation/Reference/classes/GTUIApp.md | 7 ++++++- .../Adwaita/Model/User Interface/App/GTUIApp.swift | 11 +++++++++-- Tests/Demo.swift | 4 ++-- Tests/OverlayWindowDemo.swift | 3 ++- Tests/Page.swift | 4 ++-- user-manual/Basics/Windows.md | 14 +++++++++++++- 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Documentation/Reference/classes/GTUIApp.md b/Documentation/Reference/classes/GTUIApp.md index 83d67be..c2ec704 100644 --- a/Documentation/Reference/classes/GTUIApp.md +++ b/Documentation/Reference/classes/GTUIApp.md @@ -17,6 +17,10 @@ The app's content. The scenes that are displayed. +### `overwriteParentID` + +A string signaling that the parent should not be overwritten. + ## Methods ### `init(_:body:)` @@ -35,11 +39,12 @@ Focus the window with a certain id. Create the window if it doesn't already exis - Parameters: - id: The window's id. -### `addWindow(_:)` +### `addWindow(_:parent:)` Add a new window with the content of the window with a certain id. - Parameters: - id: The window's id. + - parent: The parent window. ### `setParentWindows()` diff --git a/Sources/Adwaita/Model/User Interface/App/GTUIApp.swift b/Sources/Adwaita/Model/User Interface/App/GTUIApp.swift index dd613f6..fc4ce66 100644 --- a/Sources/Adwaita/Model/User Interface/App/GTUIApp.swift +++ b/Sources/Adwaita/Model/User Interface/App/GTUIApp.swift @@ -17,6 +17,8 @@ public class GTUIApp: Application { var body: () -> App /// The scenes that are displayed. var sceneStorage: [WindowStorage] = [] + /// A string signaling that the parent should not be overwritten. + let overwriteParentID = "overwrite-parent" /// Initialize the GTUI application. /// - Parameters: @@ -48,11 +50,16 @@ public class GTUIApp: Application { /// Add a new window with the content of the window with a certain id. /// - Parameters: /// - id: The window's id. - public func addWindow(_ id: String) { + /// - parent: The parent window. + public func addWindow(_ id: String, parent: GTUIWindow? = nil) { State.updateViews() if let window = body().scene.windows().last(where: { $0.id == id }) { let window = window.createWindow(app: self) sceneStorage.append(window) + if let parent { + window.window.setParent(parent) + window.window.fields[overwriteParentID] = true + } setParentWindows() showWindow(id) } @@ -60,7 +67,7 @@ public class GTUIApp: Application { /// Set the parents of every window having a parent window. 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 }) { window.window.setParent(parent.window) } diff --git a/Tests/Demo.swift b/Tests/Demo.swift index 20c841e..ca3fd5f 100644 --- a/Tests/Demo.swift +++ b/Tests/Demo.swift @@ -76,7 +76,7 @@ struct Demo: App { } .keyboardShortcut("w".ctrl()) MenuSection { - MenuButton("About", window: false) { app.showWindow("about") } + MenuButton("About") { app.addWindow("about", parent: window); print(window.nativePtr) } MenuButton("Quit", window: false) { app.quit() } .keyboardShortcut("q".ctrl()) } @@ -90,7 +90,7 @@ struct Demo: App { icon: selection.icon, description: selection.description ) { - selection.view(app: app, toast: toast) + selection.view(app: app, window: window, toast: toast) } .topToolbar { HeaderBar.empty() diff --git a/Tests/OverlayWindowDemo.swift b/Tests/OverlayWindowDemo.swift index a079dea..0a9c7dc 100644 --- a/Tests/OverlayWindowDemo.swift +++ b/Tests/OverlayWindowDemo.swift @@ -12,11 +12,12 @@ import Adwaita struct OverlayWindowDemo: View { var app: GTUIApp! + var window: GTUIApplicationWindow var view: Body { VStack { Button("Show Window") { - app.showWindow("overlay") + app.addWindow("overlay", parent: window) } .style("pill") .frame(maxSize: 100) diff --git a/Tests/Page.swift b/Tests/Page.swift index 86aa7c6..52e15a0 100644 --- a/Tests/Page.swift +++ b/Tests/Page.swift @@ -65,7 +65,7 @@ enum Page: String, Identifiable, CaseIterable { } @ViewBuilder - func view(app: GTUIApp!, toast: Signal) -> Body { + func view(app: GTUIApp!, window: GTUIApplicationWindow, toast: Signal) -> Body { switch self { case .welcome: [] @@ -80,7 +80,7 @@ enum Page: String, Identifiable, CaseIterable { case .dice: DiceDemo() case .overlayWindow: - OverlayWindowDemo(app: app) + OverlayWindowDemo(app: app, window: window) case .toast: ToastDemo(toast: toast) } diff --git a/user-manual/Basics/Windows.md b/user-manual/Basics/Windows.md index b1be6b1..1546771 100644 --- a/user-manual/Basics/Windows.md +++ b/user-manual/Basics/Windows.md @@ -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. ## 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: ```swift @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 By default, every window type of the app's scene appears once when the app starts.