diff --git a/Documentation/Reference/README.md b/Documentation/Reference/README.md index b54e66b..4da1ff6 100644 --- a/Documentation/Reference/README.md +++ b/Documentation/Reference/README.md @@ -16,6 +16,7 @@ - [Binding](structs/Binding.md) - [Button](structs/Button.md) - [Clamp](structs/Clamp.md) +- [ContentModifier](structs/ContentModifier.md) - [EitherView](structs/EitherView.md) - [HStack](structs/HStack.md) - [HeaderBar](structs/HeaderBar.md) @@ -24,6 +25,7 @@ - [Menu](structs/Menu.md) - [MenuButton](structs/MenuButton.md) - [MenuSection](structs/MenuSection.md) +- [ModifierStopper](structs/ModifierStopper.md) - [NavigationSplitView](structs/NavigationSplitView.md) - [ScrollView](structs/ScrollView.md) - [State](structs/State.md) diff --git a/Documentation/Reference/classes/GTUIApp.md b/Documentation/Reference/classes/GTUIApp.md index d3c5cde..83d67be 100644 --- a/Documentation/Reference/classes/GTUIApp.md +++ b/Documentation/Reference/classes/GTUIApp.md @@ -40,3 +40,7 @@ Focus the window with a certain id. Create the window if it doesn't already exis Add a new window with the content of the window with a certain id. - Parameters: - id: The window's id. + +### `setParentWindows()` + +Set the parents of every window having a parent window. diff --git a/Documentation/Reference/classes/WindowStorage.md b/Documentation/Reference/classes/WindowStorage.md index ada758c..9f8b8fd 100644 --- a/Documentation/Reference/classes/WindowStorage.md +++ b/Documentation/Reference/classes/WindowStorage.md @@ -9,6 +9,10 @@ A storage for an app's window. The window's identifier. +### `parentID` + +The identifier of the window's parent window. + ### `destroy` Whether the reference to the window should disappear in the next update. diff --git a/Documentation/Reference/extensions/Array.md b/Documentation/Reference/extensions/Array.md index be7bef5..5454d45 100644 --- a/Documentation/Reference/extensions/Array.md +++ b/Documentation/Reference/extensions/Array.md @@ -8,16 +8,18 @@ The array's view body is the array itself. ## Methods -### `widget()` +### `widget(modifiers:)` Get a widget from a collection of views. +- Parameter modifiers: Modify views before being updated. - Returns: A widget. -### `update(_:)` +### `update(_:modifiers:)` Update a collection of views with a collection of view storages. - Parameters: - storage: The collection of view storages. + - modifiers: Modify views before being updated. ### `windows()` diff --git a/Documentation/Reference/extensions/NativeWidgetPeer.md b/Documentation/Reference/extensions/NativeWidgetPeer.md index d23eb98..d27e721 100644 --- a/Documentation/Reference/extensions/NativeWidgetPeer.md +++ b/Documentation/Reference/extensions/NativeWidgetPeer.md @@ -3,14 +3,17 @@ # `NativeWidgetPeer` ## Methods -### `update(_:)` +### `update(_:modifiers:)` A `GTUI.NativeWidgetPeer` is static. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` A `GTUI.NativeWidgetPeer`'s container is itself. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. ### `modifier(code:)` diff --git a/Documentation/Reference/extensions/View.md b/Documentation/Reference/extensions/View.md index cc9ab2a..c8da187 100644 --- a/Documentation/Reference/extensions/View.md +++ b/Documentation/Reference/extensions/View.md @@ -3,27 +3,41 @@ # `View` ## Methods -### `widget()` +### `widget(modifiers:)` Wrap the view into a widget. +- Parameter modifiers: Modify views before being updated. - Returns: The widget. -### `updateStorage(_:)` +### `updateStorage(_:modifiers:)` Update a storage to a view. -- Parameter storage: The storage. +- Parameters: + - storage: The storage. + - modifiers: Modify views before being updated. -### `storage()` +### `storage(modifiers:)` Get a storage. +- Parameter modifiers: Modify views before being updated. - Returns: The storage. +### `getModified(modifiers:)` + ### `frame(maxSize:)` Set the view's maximal size. - Parameter maxSize: The maximal size. - Returns: A view. +### `modifyContent(_:modify:)` + +Replace every occurrence of a certain view type in the content. +- Parameters: + - type: The view type. + - modify: Modify the view. +- Returns: A view. + ### `inspect(_:)` Modify a GTUI widget before being displayed and when being updated. @@ -94,6 +108,11 @@ Run a function when the view appears for the first time. - Parameter closure: The function. - Returns: A view. +### `stopModifiers()` + +Remove all of the content modifiers for the wrapped views. +- Returns: A view. + ### `topToolbar(visible:_:)` Add a top toolbar to the view. diff --git a/Documentation/Reference/protocols/Widget.md b/Documentation/Reference/protocols/Widget.md index 02ba9e2..7182129 100644 --- a/Documentation/Reference/protocols/Widget.md +++ b/Documentation/Reference/protocols/Widget.md @@ -5,11 +5,14 @@ A widget is a view that know about its GTUI widget. ## Methods -### `container()` +### `container(modifiers:)` The view storage. +- Parameter modifiers: Modify views before being updated. -### `update(_:)` +### `update(_:modifiers:)` Update the stored content. -- Parameter storage: The storage to update. +- Parameters: + - storage: The storage to update. + - modifiers: Modify views before being updated diff --git a/Documentation/Reference/protocols/WindowScene.md b/Documentation/Reference/protocols/WindowScene.md index 4ecddbc..a9ab1e9 100644 --- a/Documentation/Reference/protocols/WindowScene.md +++ b/Documentation/Reference/protocols/WindowScene.md @@ -9,6 +9,10 @@ A structure representing the content for a certain window type. The window type's identifier. +### `parentID` + +The identifier of the window's parent window. + ### `open` The number of instances of the window at the startup. diff --git a/Documentation/Reference/structs/Button.md b/Documentation/Reference/structs/Button.md index 61dd5c7..6c4dd03 100644 --- a/Documentation/Reference/structs/Button.md +++ b/Documentation/Reference/structs/Button.md @@ -33,14 +33,17 @@ Initialize a button. - label: The buttons label. - handler: The button's action handler. -### `update(_:)` +### `update(_:modifiers:)` Update a button's view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get a button's view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The button's view storage. ### `keyboardShortcut(_:window:)` diff --git a/Documentation/Reference/structs/Clamp.md b/Documentation/Reference/structs/Clamp.md index 7ee1b9f..f74c4fa 100644 --- a/Documentation/Reference/structs/Clamp.md +++ b/Documentation/Reference/structs/Clamp.md @@ -14,12 +14,15 @@ The content. The maximum size. ## Methods -### `update(_:)` +### `update(_:modifiers:)` Update a view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get a view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. diff --git a/Documentation/Reference/structs/ContentModifier.md b/Documentation/Reference/structs/ContentModifier.md new file mode 100644 index 0000000..2a0e703 --- /dev/null +++ b/Documentation/Reference/structs/ContentModifier.md @@ -0,0 +1,33 @@ +**STRUCT** + +# `ContentModifier` + +A widget which replaces views of a specific type in its content. + +## Properties +### `content` + +The wrapped view. + +### `modify` + +The closure for the modification. + +## Methods +### `container(modifiers:)` + +Get the content's container. +- Parameter modifiers: Modify views before being updated. +- Returns: The content's container. + +### `update(_:modifiers:)` + +Update the content. +- Parameters: + - storage: The content's storage. + - modifiers: Modify views before being updated. + +### `modifyView(_:)` + +Apply the modifier to a view. +- Parameter view: The view. diff --git a/Documentation/Reference/structs/EitherView.md b/Documentation/Reference/structs/EitherView.md index 14a59b6..6183301 100644 --- a/Documentation/Reference/structs/EitherView.md +++ b/Documentation/Reference/structs/EitherView.md @@ -34,18 +34,21 @@ Initialize an `EitherView`. - trueView: The view that is presented if `isTrue` is true. - falseView: The view that is presented if `isTrue` is false. -### `update(_:)` +### `update(_:modifiers:)` Update an `EitherView`'s storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `updateContent(_:state:stack:)` +### `updateContent(_:state:stack:modifiers:)` 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. + - modifiers: Modify views before being updated. ### `setVisible(_:view:)` @@ -54,7 +57,8 @@ Set the visible content page. - stack: The stack. - view: The visible view. -### `container()` +### `container(modifiers:)` Get a GtkStack view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. diff --git a/Documentation/Reference/structs/HStack.md b/Documentation/Reference/structs/HStack.md index dfa5f93..1045eb8 100644 --- a/Documentation/Reference/structs/HStack.md +++ b/Documentation/Reference/structs/HStack.md @@ -15,12 +15,15 @@ The content. Initialize a `HStack`. - Parameter content: The view content. -### `update(_:)` +### `update(_:modifiers:)` Update a view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get a view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. diff --git a/Documentation/Reference/structs/HeaderBar.md b/Documentation/Reference/structs/HeaderBar.md index 425a3db..fcd55fc 100644 --- a/Documentation/Reference/structs/HeaderBar.md +++ b/Documentation/Reference/structs/HeaderBar.md @@ -59,14 +59,17 @@ Initialize a header bar with only views at the end. - Parameter start: The views. - Returns: The header bar. -### `update(_:)` +### `update(_:modifiers:)` Update a header bar's view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get the container for a header bar. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. ### `headerBarTitle(view:)` diff --git a/Documentation/Reference/structs/InspectorWrapper.md b/Documentation/Reference/structs/InspectorWrapper.md index ffe72f5..0bdb525 100644 --- a/Documentation/Reference/structs/InspectorWrapper.md +++ b/Documentation/Reference/structs/InspectorWrapper.md @@ -14,12 +14,15 @@ The custom code to edit the widget. The wrapped view. ## Methods -### `container()` +### `container(modifiers:)` Get the content's container. +- Parameter modifiers: Modify views before being updated. - Returns: The content's container. -### `update(_:)` +### `update(_:modifiers:)` Update the content. -- Parameter storage: The content's storage. +- Parameters: + - storage: The content's storage. + - modifiers: Modify views before being updated. diff --git a/Documentation/Reference/structs/List.md b/Documentation/Reference/structs/List.md index 10fdf90..faa8c7d 100644 --- a/Documentation/Reference/structs/List.md +++ b/Documentation/Reference/structs/List.md @@ -26,14 +26,17 @@ Initialize `List`. - selection: The identifier of the selected element. - content: The view for an element. -### `update(_:)` +### `update(_:modifiers:)` Update a view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get a view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. ### `updateSelection(box:)` diff --git a/Documentation/Reference/structs/Menu.md b/Documentation/Reference/structs/Menu.md index 6fddd0b..4ae44ee 100644 --- a/Documentation/Reference/structs/Menu.md +++ b/Documentation/Reference/structs/Menu.md @@ -45,12 +45,15 @@ Initialize a menu button. - window: The application window. - content: The menu's content. -### `update(_:)` +### `update(_:modifiers:)` Update a button's view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get a button's view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The button's view storage. diff --git a/Documentation/Reference/structs/ModifierStopper.md b/Documentation/Reference/structs/ModifierStopper.md new file mode 100644 index 0000000..d286f66 --- /dev/null +++ b/Documentation/Reference/structs/ModifierStopper.md @@ -0,0 +1,24 @@ +**STRUCT** + +# `ModifierStopper` + +Remove all of the content modifiers for the wrapped views. + +## Properties +### `content` + +The wrapped view. + +## Methods +### `container(modifiers:)` + +Get the content's container. +- Parameter modifiers: Modify views before being updated. +- Returns: The content's container. + +### `update(_:modifiers:)` + +Update the content. +- Parameters: + - storage: The content's storage. + - modifiers: Modify views before being updated. diff --git a/Documentation/Reference/structs/NavigationSplitView.md b/Documentation/Reference/structs/NavigationSplitView.md index a58e25c..53996e5 100644 --- a/Documentation/Reference/structs/NavigationSplitView.md +++ b/Documentation/Reference/structs/NavigationSplitView.md @@ -29,12 +29,15 @@ Initialize a navigation split view. - sidebar: The sidebar content. - content: The main content. -### `container()` +### `container(modifiers:)` Get the container of the navigation split view widget. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. -### `update(_:)` +### `update(_:modifiers:)` Update the view storage of the navigation split view widget. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. diff --git a/Documentation/Reference/structs/ScrollView.md b/Documentation/Reference/structs/ScrollView.md index 2d978ab..24ed87f 100644 --- a/Documentation/Reference/structs/ScrollView.md +++ b/Documentation/Reference/structs/ScrollView.md @@ -15,12 +15,15 @@ The content. Initialize a `ScrollView`. - Parameter content: The view content. -### `update(_:)` +### `update(_:modifiers:)` Update a view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get a view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. diff --git a/Documentation/Reference/structs/StateWrapper.md b/Documentation/Reference/structs/StateWrapper.md index 4346fb8..d225433 100644 --- a/Documentation/Reference/structs/StateWrapper.md +++ b/Documentation/Reference/structs/StateWrapper.md @@ -26,12 +26,15 @@ Initialize a `StateWrapper`. - content: The view content. - state: The state information. -### `update(_:)` +### `update(_:modifiers:)` Update a view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get a view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. diff --git a/Documentation/Reference/structs/StatusPage.md b/Documentation/Reference/structs/StatusPage.md index 5ba82f0..8726045 100644 --- a/Documentation/Reference/structs/StatusPage.md +++ b/Documentation/Reference/structs/StatusPage.md @@ -31,12 +31,15 @@ Initialize a status page widget. - description: Additional details. - content: Additional content. -### `update(_:)` +### `update(_:modifiers:)` Update the view storage of the text widget. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get the container of the text widget. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. diff --git a/Documentation/Reference/structs/Text.md b/Documentation/Reference/structs/Text.md index 8a17bad..91c4b57 100644 --- a/Documentation/Reference/structs/Text.md +++ b/Documentation/Reference/structs/Text.md @@ -15,12 +15,14 @@ The content. Initialize a text widget. - Parameter text: The content. -### `update(_:)` +### `update(_:modifiers:)` Update the view storage of the text widget. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get the container of the text widget. - Returns: The view storage. diff --git a/Documentation/Reference/structs/ToolbarView.md b/Documentation/Reference/structs/ToolbarView.md index 4268a4e..ab6c37d 100644 --- a/Documentation/Reference/structs/ToolbarView.md +++ b/Documentation/Reference/structs/ToolbarView.md @@ -26,12 +26,15 @@ Whether the toolbar is visible. The identifier of the toolbar content. ## Methods -### `container()` +### `container(modifiers:)` Get the container of the toolbar view widget. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. -### `update(_:)` +### `update(_:modifiers:)` Update the view storage of the toolbar view widget. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. diff --git a/Documentation/Reference/structs/UpdateObserver.md b/Documentation/Reference/structs/UpdateObserver.md index 5ee8160..937b8c6 100644 --- a/Documentation/Reference/structs/UpdateObserver.md +++ b/Documentation/Reference/structs/UpdateObserver.md @@ -14,12 +14,15 @@ The function. The content. ## Methods -### `container()` +### `container(modifiers:)` Get the content's container. +- Parameter modifiers: Modify views before being updated. - Returns: The content's container. -### `update(_:)` +### `update(_:modifiers:)` Update the content. -- Parameter storage: The content's storage. +- Parameters: + - storage: The content's storage. + - modifiers: Modify views before being updated. diff --git a/Documentation/Reference/structs/VStack.md b/Documentation/Reference/structs/VStack.md index 89a7b65..fa604a3 100644 --- a/Documentation/Reference/structs/VStack.md +++ b/Documentation/Reference/structs/VStack.md @@ -15,12 +15,15 @@ The content. Initialize a `VStack`. - Parameter content: The view content. -### `update(_:)` +### `update(_:modifiers:)` Update a view storage. -- Parameter storage: The view storage. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. -### `container()` +### `container(modifiers:)` Get a view storage. +- Parameter modifiers: Modify views before being updated. - Returns: The view storage. diff --git a/Documentation/Reference/structs/Window.md b/Documentation/Reference/structs/Window.md index 0a56a26..255a2c2 100644 --- a/Documentation/Reference/structs/Window.md +++ b/Documentation/Reference/structs/Window.md @@ -19,6 +19,10 @@ The window's content. Whether an instance of the window type should be opened when the app is starting up. +### `parentID` + +The identifier of the window's parent. + ### `shortcuts` The keyboard shortcuts. @@ -59,6 +63,12 @@ Get the storage of the content view. Update a window storage's content. - Parameter storage: The storage to update. +### `overlay(windows:)` + +Add windows that overlay the last instance of this window if presented. +- Parameter windows: The windows. +- Returns: The new windows and this window. + ### `keyboardShortcut(_:action:)` Add a keyboard shortcut. diff --git a/README.md b/README.md index 2c631c1..80b9ac5 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,8 @@ If you want to use _Adwaita_ in a project, but there are widgets missing, open a | `onAppear(_:)` | Run when the view is rendered for the first time. | | `topToolbar(visible:_:)` | Add a native toolbar to the view. Normally, it contains a HeaderBar. | | `bottomToolbar(visible:_:)` | Add a native bottom toolbar to the view. | +| `modifyContent(_:modify:)` | Replace all occurrences of a certain view type with another view. | +| `stopModifiers()` | Ignore all the `modifyContent(_:modify:)` modifiers from higher above in the view tree. | ### `Button` Modifiers | Syntax | Description | diff --git a/Sources/Adwaita/Model/Extensions/Array.swift b/Sources/Adwaita/Model/Extensions/Array.swift index 05e08cf..e034196 100644 --- a/Sources/Adwaita/Model/Extensions/Array.swift +++ b/Sources/Adwaita/Model/Extensions/Array.swift @@ -13,22 +13,30 @@ extension Array: View where Element == View { public var view: Body { self } /// Get a widget from a collection of views. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: A widget. - public func widget() -> Widget { - if count == 1, let widget = self[safe: 0]?.widget() { + public func widget(modifiers: [(View) -> View]) -> Widget { + if count == 1, let widget = self[safe: 0]?.widget(modifiers: modifiers) { return widget } else { - return VStack { self } + var modified = self + for (index, view) in modified.enumerated() { + for modifier in modifiers { + modified[index] = modifier(view) + } + } + return VStack { modified } } } /// Update a collection of views with a collection of view storages. /// - Parameters: /// - storage: The collection of view storages. - public func update(_ storage: [ViewStorage]) { + /// - modifiers: Modify views before being updated. + public func update(_ storage: [ViewStorage], modifiers: [(View) -> View]) { for (index, element) in enumerated() { if let storage = storage[safe: index] { - element.widget().updateStorage(storage) + element.widget(modifiers: modifiers).updateStorage(storage, modifiers: modifiers) } } } diff --git a/Sources/Adwaita/Model/Extensions/NativeWidgetPeer.swift b/Sources/Adwaita/Model/Extensions/NativeWidgetPeer.swift index f253c30..6bac6cd 100644 --- a/Sources/Adwaita/Model/Extensions/NativeWidgetPeer.swift +++ b/Sources/Adwaita/Model/Extensions/NativeWidgetPeer.swift @@ -10,12 +10,15 @@ import GTUI extension NativeWidgetPeer: Widget { /// A `GTUI.NativeWidgetPeer` is static. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { } + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { } /// A `GTUI.NativeWidgetPeer`'s container is itself. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { let bold = "\(modifier(code: 1))" let yellow = 33 let warning = "\(modifier(code: yellow))\(bold)" diff --git a/Sources/Adwaita/Model/User Interface/App/GTUIApp.swift b/Sources/Adwaita/Model/User Interface/App/GTUIApp.swift index 6c228e1..2ff2333 100644 --- a/Sources/Adwaita/Model/User Interface/App/GTUIApp.swift +++ b/Sources/Adwaita/Model/User Interface/App/GTUIApp.swift @@ -61,7 +61,7 @@ public class GTUIApp: Application { /// Set the parents of every window having a parent window. func setParentWindows() { for window in sceneStorage { - if let parent = sceneStorage.first { $0.id == window.parentID } { + if let parent = sceneStorage.first(where: { $0.id == window.parentID }) { window.window.setParent(parent.window) } } diff --git a/Sources/Adwaita/Model/User Interface/View/View.swift b/Sources/Adwaita/Model/User Interface/View/View.swift index a9ba7aa..8a0acac 100644 --- a/Sources/Adwaita/Model/User Interface/View/View.swift +++ b/Sources/Adwaita/Model/User Interface/View/View.swift @@ -30,9 +30,11 @@ public protocol View { extension View { /// Wrap the view into a widget. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The widget. - public func widget() -> Widget { - if let peer = self as? Widget { + public func widget(modifiers: [(View) -> View]) -> Widget { + let modified = getModified(modifiers: modifiers) + if let peer = modified as? Widget { return peer } else { var state: [String: StateProtocol] = [:] @@ -46,19 +48,31 @@ extension View { } /// Update a storage to a view. - /// - Parameter storage: The storage. - func updateStorage(_ storage: ViewStorage) { - if let widget = self as? Widget { - widget.update(storage) + /// - Parameters: + /// - storage: The storage. + /// - modifiers: Modify views before being updated. + func updateStorage(_ storage: ViewStorage, modifiers: [(View) -> View]) { + let modified = getModified(modifiers: modifiers) + if let widget = modified as? Widget { + widget.update(storage, modifiers: modifiers) } else { - StateWrapper { self }.update(storage) + StateWrapper { self }.update(storage, modifiers: modifiers) } } /// Get a storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The storage. - func storage() -> ViewStorage { - widget().container() + func storage(modifiers: [(View) -> View]) -> ViewStorage { + widget(modifiers: modifiers).container(modifiers: modifiers) + } + + func getModified(modifiers: [(View) -> View]) -> View { + var modified: View = self + for modifier in modifiers { + modified = modifier(modified) + } + return modified } } diff --git a/Sources/Adwaita/Model/User Interface/View/Widget.swift b/Sources/Adwaita/Model/User Interface/View/Widget.swift index 1f71db5..5df62a5 100644 --- a/Sources/Adwaita/Model/User Interface/View/Widget.swift +++ b/Sources/Adwaita/Model/User Interface/View/Widget.swift @@ -11,10 +11,13 @@ import GTUI public protocol Widget: View { /// The view storage. - func container() -> ViewStorage + /// - Parameter modifiers: Modify views before being updated. + func container(modifiers: [(View) -> View]) -> ViewStorage /// Update the stored content. - /// - Parameter storage: The storage to update. - func update(_ storage: ViewStorage) + /// - Parameters: + /// - storage: The storage to update. + /// - modifiers: Modify views before being updated + func update(_ storage: ViewStorage, modifiers: [(View) -> View]) } diff --git a/Sources/Adwaita/View/Button.swift b/Sources/Adwaita/View/Button.swift index 747d1d2..da72a31 100644 --- a/Sources/Adwaita/View/Button.swift +++ b/Sources/Adwaita/View/Button.swift @@ -40,8 +40,10 @@ public struct Button: Widget { } /// Update a button's view storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let button = storage.view as? GTUI.Button { let content = button.getContent() if let label { @@ -58,8 +60,9 @@ public struct Button: Widget { } /// Get a button's view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The button's view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { if let icon { return .init(GTUI.Button(label, icon: icon).handler(handler)) } else { diff --git a/Sources/Adwaita/View/EitherView.swift b/Sources/Adwaita/View/EitherView.swift index f973592..e026f95 100644 --- a/Sources/Adwaita/View/EitherView.swift +++ b/Sources/Adwaita/View/EitherView.swift @@ -42,11 +42,13 @@ public struct EitherView: Widget { } /// Update an `EitherView`'s storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { let stack = storage.view as? Stack - updateContent(storage, state: true, stack: stack) - updateContent(storage, state: false, stack: stack) + updateContent(storage, state: true, stack: stack, modifiers: modifiers) + updateContent(storage, state: false, stack: stack, modifiers: modifiers) if isTrue, let trueView = storage.content["\(true)"]?.last?.view { setVisible(stack, view: trueView) } else if !isTrue, let falseView = storage.content["\(false)"]?.last?.view { @@ -59,11 +61,12 @@ public struct EitherView: Widget { /// - 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() + /// - modifiers: Modify views before being updated. + private func updateContent(_ storage: ViewStorage, state: Bool, stack: Stack?, modifiers: [(View) -> View]) { + let activeView = (state ? trueView : falseView)?.widget(modifiers: modifiers) if let view = storage.content["\(state)"]?[safe: 0] { - activeView?.updateStorage(view) - } else if let view = activeView?.storage() { + activeView?.updateStorage(view, modifiers: modifiers) + } else if let view = activeView?.storage(modifiers: modifiers) { _ = stack?.append(view.view) storage.content["\(state)"] = [view] } @@ -78,17 +81,18 @@ public struct EitherView: Widget { } /// Get a GtkStack view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { let stack = Stack() var content: [String: [ViewStorage]] = [:] if let trueView { - let view = trueView.widget().storage() + let view = trueView.widget(modifiers: modifiers).storage(modifiers: modifiers) _ = stack.append(view.view) content["\(true)"] = [view] } if let falseView { - let view = falseView.widget().storage() + let view = falseView.widget(modifiers: modifiers).storage(modifiers: modifiers) _ = stack.append(view.view) content["\(false)"] = [view] } diff --git a/Sources/Adwaita/View/HStack.swift b/Sources/Adwaita/View/HStack.swift index 9b461cf..a440d3e 100644 --- a/Sources/Adwaita/View/HStack.swift +++ b/Sources/Adwaita/View/HStack.swift @@ -20,18 +20,21 @@ public struct HStack: Widget { } /// Update a view storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { - content().update(storage.content[.mainContent] ?? []) + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { + content().update(storage.content[.mainContent] ?? [], modifiers: modifiers) } /// Get a view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { let box: Box = .init(horizontal: true) var content: [ViewStorage] = [] for element in self.content() { - let widget = element.storage() + let widget = element.storage(modifiers: modifiers) _ = box.append(widget.view) content.append(widget) } diff --git a/Sources/Adwaita/View/HeaderBar.swift b/Sources/Adwaita/View/HeaderBar.swift index 681e56a..d10c2d4 100644 --- a/Sources/Adwaita/View/HeaderBar.swift +++ b/Sources/Adwaita/View/HeaderBar.swift @@ -58,35 +58,38 @@ public struct HeaderBar: Widget { } /// Update a header bar's view storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let bar = storage.view as? GTUI.HeaderBar { _ = bar.showTitleButtons(titleButtons) } - start.update(storage.content[startID] ?? []) - end.update(storage.content[endID] ?? []) + start.update(storage.content[startID] ?? [], modifiers: modifiers) + end.update(storage.content[endID] ?? [], modifiers: modifiers) if let first = storage.content[titleID]?.first { - headerBarTitle?.widget().update(first) + headerBarTitle?.widget(modifiers: modifiers).update(first, modifiers: modifiers) } } /// Get the container for a header bar. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { let bar: GTUI.HeaderBar = .init() var startContent: [ViewStorage] = [] var endContent: [ViewStorage] = [] for element in start { - let element = element.storage() + let element = element.storage(modifiers: modifiers) _ = bar.packStart(element.view) startContent.append(element) } for element in end { - let element = element.storage() + let element = element.storage(modifiers: modifiers) _ = bar.packEnd(element.view) endContent.append(element) } - let title = headerBarTitle?.widget().container() + let title = headerBarTitle?.widget(modifiers: modifiers).container(modifiers: modifiers) let titleStorage: [ViewStorage] if let title { _ = bar.titleWidget(title.view) diff --git a/Sources/Adwaita/View/List.swift b/Sources/Adwaita/View/List.swift index d395720..8a3feb0 100644 --- a/Sources/Adwaita/View/List.swift +++ b/Sources/Adwaita/View/List.swift @@ -33,20 +33,23 @@ public struct List: Widget where Element: Identifiable { } /// Update a view storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let box = storage.view as? ListBox { updateSelection(box: box) } } /// Get a view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { let box: ListBox = .init() var content: [ViewStorage] = [] for element in elements { - let widget = self.content(element).widget().container() + let widget = self.content(element).widget(modifiers: modifiers).container(modifiers: modifiers) _ = box.append(widget.view) content.append(widget) } diff --git a/Sources/Adwaita/View/Menu.swift b/Sources/Adwaita/View/Menu.swift index 6fbb504..5897a16 100644 --- a/Sources/Adwaita/View/Menu.swift +++ b/Sources/Adwaita/View/Menu.swift @@ -63,8 +63,10 @@ public struct Menu: Widget { } /// Update a button's view storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let button = storage.view as? GTUI.MenuButton { let content = button.getContent() if let label { @@ -81,8 +83,9 @@ public struct Menu: Widget { } /// Get a button's view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The button's view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { let button: GTUI.MenuButton if let icon { button = .init(label, icon: icon) diff --git a/Sources/Adwaita/View/Modifiers/Clamp.swift b/Sources/Adwaita/View/Modifiers/Clamp.swift index f25c633..814b57f 100644 --- a/Sources/Adwaita/View/Modifiers/Clamp.swift +++ b/Sources/Adwaita/View/Modifiers/Clamp.swift @@ -16,20 +16,23 @@ struct Clamp: Widget { var maxSize: Int /// Update a view storage. - /// - Parameter storage: The view storage. - func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let clamp = storage.view as? GTUI.Clamp { _ = clamp.maximumSize(maxSize) } if let storage = storage.content[.mainContent]?[safe: 0] { - content.widget().update(storage) + content.widget(modifiers: modifiers).update(storage, modifiers: modifiers) } } /// Get a view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - func container() -> ViewStorage { - let container = content.storage() + func container(modifiers: [(View) -> View]) -> ViewStorage { + let container = content.storage(modifiers: modifiers) let clamp: GTUI.Clamp = .init(container.view) _ = clamp.maximumSize(maxSize) return .init(clamp, content: [.mainContent: [container]]) diff --git a/Sources/Adwaita/View/Modifiers/ContentModifier.swift b/Sources/Adwaita/View/Modifiers/ContentModifier.swift new file mode 100644 index 0000000..f3513bb --- /dev/null +++ b/Sources/Adwaita/View/Modifiers/ContentModifier.swift @@ -0,0 +1,60 @@ +// +// ContentModifier.swift +// Adwaita +// +// Created by david-swift on 11.11.23. +// + +import GTUI + +/// A widget which replaces views of a specific type in its content. +struct ContentModifier: Widget where Content: View { + + /// The wrapped view. + var content: View + /// The closure for the modification. + var modify: (Content) -> View + + /// Get the content's container. + /// - Parameter modifiers: Modify views before being updated. + /// - Returns: The content's container. + func container(modifiers: [(View) -> View]) -> ViewStorage { + let storage = content.storage(modifiers: modifiers + [modifyView]) + return storage + } + + /// Update the content. + /// - Parameters: + /// - storage: The content's storage. + /// - modifiers: Modify views before being updated. + func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { + content.updateStorage(storage, modifiers: modifiers + [modifyView]) + } + + /// Apply the modifier to a view. + /// - Parameter view: The view. + func modifyView(_ view: View) -> View { + if let view = view as? Content { + return modify(view).stopModifiers() + } else { + return view + } + } + +} + +extension View { + + /// Replace every occurrence of a certain view type in the content. + /// - Parameters: + /// - type: The view type. + /// - modify: Modify the view. + /// - Returns: A view. + public func modifyContent( + _ type: Content.Type, + modify: @escaping (Content) -> View + ) -> View where Content: View { + ContentModifier(content: self, modify: modify) + } + +} diff --git a/Sources/Adwaita/View/Modifiers/InspectorWrapper.swift b/Sources/Adwaita/View/Modifiers/InspectorWrapper.swift index 1e9df46..cfa85c3 100644 --- a/Sources/Adwaita/View/Modifiers/InspectorWrapper.swift +++ b/Sources/Adwaita/View/Modifiers/InspectorWrapper.swift @@ -16,17 +16,20 @@ struct InspectorWrapper: Widget { var content: View /// Get the content's container. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The content's container. - func container() -> ViewStorage { - let storage = content.storage() + func container(modifiers: [(View) -> View]) -> ViewStorage { + let storage = content.storage(modifiers: modifiers) modify(storage.view) return storage } /// Update the content. - /// - Parameter storage: The content's storage. - func update(_ storage: ViewStorage) { - content.updateStorage(storage) + /// - Parameters: + /// - storage: The content's storage. + /// - modifiers: Modify views before being updated. + func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { + content.updateStorage(storage, modifiers: modifiers) modify(storage.view) } diff --git a/Sources/Adwaita/View/Modifiers/ModifierStopper.swift b/Sources/Adwaita/View/Modifiers/ModifierStopper.swift new file mode 100644 index 0000000..22393e0 --- /dev/null +++ b/Sources/Adwaita/View/Modifiers/ModifierStopper.swift @@ -0,0 +1,42 @@ +// +// ModifierStopper.swift +// Adwaita +// +// Created by david-swift on 11.11.23. +// + +import GTUI + +/// Remove all of the content modifiers for the wrapped views. +struct ModifierStopper: Widget { + + /// The wrapped view. + var content: View + + /// Get the content's container. + /// - Parameter modifiers: Modify views before being updated. + /// - Returns: The content's container. + func container(modifiers: [(View) -> View]) -> ViewStorage { + let storage = content.storage(modifiers: []) + return storage + } + + /// Update the content. + /// - Parameters: + /// - storage: The content's storage. + /// - modifiers: Modify views before being updated. + func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { + content.updateStorage(storage, modifiers: []) + } + +} + +extension View { + + /// Remove all of the content modifiers for the wrapped views. + /// - Returns: A view. + public func stopModifiers() -> View { + ModifierStopper(content: self) + } + +} diff --git a/Sources/Adwaita/View/Modifiers/ToolbarView.swift b/Sources/Adwaita/View/Modifiers/ToolbarView.swift index 6efa8dc..9224941 100644 --- a/Sources/Adwaita/View/Modifiers/ToolbarView.swift +++ b/Sources/Adwaita/View/Modifiers/ToolbarView.swift @@ -23,13 +23,14 @@ struct ToolbarView: Widget { let toolbarID = "toolbar" /// Get the container of the toolbar view widget. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - func container() -> ViewStorage { - let content = content.storage() + func container(modifiers: [(View) -> View]) -> ViewStorage { + let content = content.storage(modifiers: modifiers) let view = GTUI.ToolbarView(content.view) var toolbarContent: [ViewStorage] = [] for item in toolbar() { - let storage = item.storage() + let storage = item.storage(modifiers: modifiers) toolbarContent.append(storage) if bottom { _ = view.addBottomBar(storage.view) @@ -46,14 +47,16 @@ struct ToolbarView: Widget { } /// Update the view storage of the toolbar view widget. - /// - Parameter storage: The view storage. - func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let mainContent = storage.content[.mainContent]?.first { - content.widget().update(mainContent) + content.widget(modifiers: modifiers).update(mainContent, modifiers: modifiers) } if let toolbar = storage.content[toolbarID] { for (index, content) in toolbar.enumerated() { - self.toolbar()[safe: index]?.updateStorage(content) + self.toolbar()[safe: index]?.updateStorage(content, modifiers: modifiers) } } if let view = storage.view as? GTUI.ToolbarView { diff --git a/Sources/Adwaita/View/Modifiers/UpdateObserver.swift b/Sources/Adwaita/View/Modifiers/UpdateObserver.swift index a3be26a..cb3eea5 100644 --- a/Sources/Adwaita/View/Modifiers/UpdateObserver.swift +++ b/Sources/Adwaita/View/Modifiers/UpdateObserver.swift @@ -16,17 +16,20 @@ struct UpdateObserver: Widget { var content: View /// Get the content's container. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The content's container. - func container() -> ViewStorage { + func container(modifiers: [(View) -> View]) -> ViewStorage { onUpdate() - return content.storage() + return content.storage(modifiers: modifiers) } /// Update the content. - /// - Parameter storage: The content's storage. - func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The content's storage. + /// - modifiers: Modify views before being updated. + func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { onUpdate() - content.updateStorage(storage) + content.updateStorage(storage, modifiers: modifiers) } } diff --git a/Sources/Adwaita/View/NavigationSplitView.swift b/Sources/Adwaita/View/NavigationSplitView.swift index 752b1ec..1dc44f8 100644 --- a/Sources/Adwaita/View/NavigationSplitView.swift +++ b/Sources/Adwaita/View/NavigationSplitView.swift @@ -30,17 +30,18 @@ public struct NavigationSplitView: Widget { } /// Get the container of the navigation split view widget. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { let splitView: GTUI.NavigationSplitView = .init() var content: [String: [ViewStorage]] = [:] - let sidebar = sidebar().widget().container() + let sidebar = sidebar().widget(modifiers: modifiers).container(modifiers: modifiers) let label = sidebar.view.fields[.navigationLabel] as? String ?? "" _ = splitView.sidebar(sidebar.view, title: label) content[sidebarID] = [sidebar] - let mainContent = self.content().widget().container() + let mainContent = self.content().widget(modifiers: modifiers).container(modifiers: modifiers) let mainLabel = mainContent.view.fields[.navigationLabel] as? String ?? "" _ = splitView.content(mainContent.view, title: mainLabel) content[contentID] = [mainContent] @@ -49,13 +50,15 @@ public struct NavigationSplitView: Widget { } /// Update the view storage of the navigation split view widget. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let storage = storage.content[contentID]?[safe: 0] { - content().widget().update(storage) + content().widget(modifiers: modifiers).update(storage, modifiers: modifiers) } if let storage = storage.content[sidebarID]?[safe: 0] { - sidebar().widget().update(storage) + sidebar().widget(modifiers: modifiers).update(storage, modifiers: modifiers) } } diff --git a/Sources/Adwaita/View/ScrollView.swift b/Sources/Adwaita/View/ScrollView.swift index bd44b4c..d4549cc 100644 --- a/Sources/Adwaita/View/ScrollView.swift +++ b/Sources/Adwaita/View/ScrollView.swift @@ -20,17 +20,20 @@ public struct ScrollView: Widget { } /// Update a view storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let first = storage.content[.mainContent]?.first { - content().widget().update(first) + content().widget(modifiers: modifiers).update(first, modifiers: modifiers) } } /// Get a view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { - let container = content().widget().container() + public func container(modifiers: [(View) -> View]) -> ViewStorage { + let container = content().widget(modifiers: modifiers).container(modifiers: modifiers) return .init(Scrolled().setChild(container.view), content: [.mainContent: [container]]) } diff --git a/Sources/Adwaita/View/StateWrapper.swift b/Sources/Adwaita/View/StateWrapper.swift index e9d94bf..e2cc5b3 100644 --- a/Sources/Adwaita/View/StateWrapper.swift +++ b/Sources/Adwaita/View/StateWrapper.swift @@ -31,22 +31,25 @@ public struct StateWrapper: Widget { } /// Update a view storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { for property in state { if let value = storage.state[property.key]?.value { property.value.value = value } } if let storage = storage.content[.mainContent]?.first { - content().widget().update(storage) + content().widget(modifiers: modifiers).update(storage, modifiers: modifiers) } } /// Get a view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { - let content = content().widget().container() + public func container(modifiers: [(View) -> View]) -> ViewStorage { + let content = content().widget(modifiers: modifiers).container(modifiers: modifiers) return .init(content.view, content: [.mainContent: [content]], state: state) } diff --git a/Sources/Adwaita/View/StatusPage.swift b/Sources/Adwaita/View/StatusPage.swift index 4eda7a9..022a24a 100644 --- a/Sources/Adwaita/View/StatusPage.swift +++ b/Sources/Adwaita/View/StatusPage.swift @@ -38,20 +38,23 @@ public struct StatusPage: Widget { } /// Update the view storage of the text widget. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let statusPage = storage.view as? GTUI.StatusPage { _ = statusPage.title(title).description(description).icon(icon) } if let storage = storage.content[.mainContent]?.first { - content.widget().update(storage) + content.widget(modifiers: modifiers).update(storage, modifiers: modifiers) } } /// Get the container of the text widget. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { - let child = content.widget().container() + public func container(modifiers: [(View) -> View]) -> ViewStorage { + let child = content.widget(modifiers: []).container(modifiers: modifiers) return .init( GTUI.StatusPage().title(title).description(description).icon(icon).child(child.view), content: [.mainContent: [child]] diff --git a/Sources/Adwaita/View/Text.swift b/Sources/Adwaita/View/Text.swift index 08ae833..94f3c79 100644 --- a/Sources/Adwaita/View/Text.swift +++ b/Sources/Adwaita/View/Text.swift @@ -20,8 +20,10 @@ public struct Text: Widget { } /// Update the view storage of the text widget. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { if let label = storage.view as? MarkupLabel { label.setText(text) } @@ -29,7 +31,7 @@ public struct Text: Widget { /// Get the container of the text widget. /// - Returns: The view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { .init(MarkupLabel(self.text)) } diff --git a/Sources/Adwaita/View/VStack.swift b/Sources/Adwaita/View/VStack.swift index 7807b7b..47f06a9 100644 --- a/Sources/Adwaita/View/VStack.swift +++ b/Sources/Adwaita/View/VStack.swift @@ -20,18 +20,21 @@ public struct VStack: Widget { } /// Update a view storage. - /// - Parameter storage: The view storage. - public func update(_ storage: ViewStorage) { - content().update(storage.content[.mainContent] ?? []) + /// - Parameters: + /// - storage: The view storage. + /// - modifiers: Modify views before being updated. + public func update(_ storage: ViewStorage, modifiers: [(View) -> View]) { + content().update(storage.content[.mainContent] ?? [], modifiers: modifiers) } /// Get a view storage. + /// - Parameter modifiers: Modify views before being updated. /// - Returns: The view storage. - public func container() -> ViewStorage { + public func container(modifiers: [(View) -> View]) -> ViewStorage { let box: Box = .init(horizontal: false) var content: [ViewStorage] = [] for element in self.content() { - let widget = element.storage() + let widget = element.storage(modifiers: modifiers) _ = box.append(widget.view) content.append(widget) } diff --git a/Sources/Adwaita/Window/Window.swift b/Sources/Adwaita/Window/Window.swift index 1cc9f9b..8675ca4 100644 --- a/Sources/Adwaita/Window/Window.swift +++ b/Sources/Adwaita/Window/Window.swift @@ -66,7 +66,7 @@ public struct Window: WindowScene { /// - Returns: The storage of the content of the window. func getViewStorage(window: GTUIApplicationWindow) -> ViewStorage { let content = content(window) - let storage = content.widget().container() + let storage = content.widget(modifiers: []).container(modifiers: []) window.setChild(storage.view) updateShortcuts(window: window) return storage @@ -77,7 +77,7 @@ public struct Window: WindowScene { public func update(_ storage: WindowStorage, app: GTUIApp) { if let window = storage.window as? GTUIApplicationWindow { let content = content(window) - content.widget().updateStorage(storage.view) + content.widget(modifiers: []).updateStorage(storage.view, modifiers: []) updateShortcuts(window: window) updateAppShortcuts(app: app) } diff --git a/Tests/Demo.swift b/Tests/Demo.swift index 5ba6a28..7f7dc52 100644 --- a/Tests/Demo.swift +++ b/Tests/Demo.swift @@ -46,7 +46,7 @@ struct Demo: App { struct DemoContent: View { - @State private var selection: Page = .welcome + @State private var selection: Page = .transition var window: GTUIApplicationWindow var app: GTUIApp! diff --git a/Tests/TransitionDemo.swift b/Tests/TransitionDemo.swift index 2135529..7a94428 100644 --- a/Tests/TransitionDemo.swift +++ b/Tests/TransitionDemo.swift @@ -16,15 +16,16 @@ struct TransitionDemo: View { var view: Body { VStack { if firstView { - content("First View") + Text("First View") .transition(.slideDown) .style("accent") } else { - content("Second View") + Text("Second View") .transition(.slideUp) .style("success") } } + .modifyContent(Text.self) { $0.style("title-2").padding() } .style("card") .frame(maxSize: 200) .padding() @@ -36,12 +37,6 @@ struct TransitionDemo: View { .frame(maxSize: 100) } - private func content(_ text: String) -> View { - Text(text) - .style("title-2") - .padding() - } - } // swiftlint:enable missing_docs no_magic_numbers