diff --git a/Documentation/Reference/README.md b/Documentation/Reference/README.md index 0f5fdd7..c66696f 100644 --- a/Documentation/Reference/README.md +++ b/Documentation/Reference/README.md @@ -31,6 +31,7 @@ - [MenuSection](structs/MenuSection.md) - [ModifierStopper](structs/ModifierStopper.md) - [NavigationSplitView](structs/NavigationSplitView.md) +- [OverlaySplitView](structs/OverlaySplitView.md) - [ScrollView](structs/ScrollView.md) - [Signal](structs/Signal.md) - [State](structs/State.md) diff --git a/Documentation/Reference/structs/OverlaySplitView.md b/Documentation/Reference/structs/OverlaySplitView.md new file mode 100644 index 0000000..210096b --- /dev/null +++ b/Documentation/Reference/structs/OverlaySplitView.md @@ -0,0 +1,57 @@ +**STRUCT** + +# `OverlaySplitView` + +An overlay split view widget. + +## Properties +### `sidebar` + +The sidebar's content. + +### `content` + +The split view's main content. + +### `trailing` + +Whether the sidebar is at the trailing position. + +### `sidebarID` + +The sidebar content's id. + +### `contentID` + +The main content's id. + +## Methods +### `init(sidebar:content:)` + +Initialize an overlay split view. +- Parameters: + - sidebar: The sidebar content. + - content: The main content. + +### `trailingSidebar(_:)` + +The position of the sidebar. +- Parameter trailing: Whether the sidebar is at the trailing position. +- Returns: The navigation split view. + +### `container(modifiers:)` + +Get the container of the overlay split view widget. +- Parameter modifiers: Modify views before being updated. +- Returns: The view storage. + +### `update(_:modifiers:)` + +Update the view storage of the overlay split view widget. +- Parameters: + - storage: The view storage. + - modifiers: Modify views before being updated. + +### `updatePosition(_:)` + +Update the sidebar's position in the split view. diff --git a/Sources/Adwaita/View/OverlaySplitView.swift b/Sources/Adwaita/View/OverlaySplitView.swift new file mode 100644 index 0000000..b4d0308 --- /dev/null +++ b/Sources/Adwaita/View/OverlaySplitView.swift @@ -0,0 +1,84 @@ +// +// OverlaySplitView.swift +// Adwaita +// +// Created by david-swift on 19.12.23. +// + +import Libadwaita + +/// An overlay split view widget. +public struct OverlaySplitView: Widget { + + /// The sidebar's content. + var sidebar: () -> Body + /// The split view's main content. + var content: () -> Body + /// Whether the sidebar is at the trailing position. + var trailing = false + + /// The sidebar content's id. + let sidebarID = "sidebar" + /// The main content's id. + let contentID = "content" + + /// Initialize an overlay split view. + /// - Parameters: + /// - sidebar: The sidebar content. + /// - content: The main content. + public init(@ViewBuilder sidebar: @escaping () -> Body, @ViewBuilder content: @escaping () -> Body) { + self.sidebar = sidebar + self.content = content + } + + /// The position of the sidebar. + /// - Parameter trailing: Whether the sidebar is at the trailing position. + /// - Returns: The navigation split view. + public func trailingSidebar(_ trailing: Bool = true) -> Self { + var newSelf = self + newSelf.trailing = trailing + return newSelf + } + + /// Get the container of the overlay split view widget. + /// - Parameter modifiers: Modify views before being updated. + /// - Returns: The view storage. + public func container(modifiers: [(View) -> View]) -> ViewStorage { + let splitView: Libadwaita.OverlaySplitView = .init() + var content: [String: [ViewStorage]] = [:] + + let sidebar = sidebar().widget(modifiers: modifiers).container(modifiers: modifiers) + _ = splitView.sidebar(sidebar.view) + content[sidebarID] = [sidebar] + + let mainContent = self.content().widget(modifiers: modifiers).container(modifiers: modifiers) + _ = splitView.content(mainContent.view) + content[contentID] = [mainContent] + + updatePosition(splitView) + + return .init(splitView, content: content) + } + + /// Update the view storage of the overlay split view widget. + /// - 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(modifiers: modifiers).update(storage, modifiers: modifiers) + } + if let storage = storage.content[sidebarID]?[safe: 0] { + sidebar().widget(modifiers: modifiers).update(storage, modifiers: modifiers) + } + if let splitView = storage.view as? Libadwaita.OverlaySplitView { + updatePosition(splitView) + } + } + + /// Update the sidebar's position in the split view. + func updatePosition(_ splitView: Libadwaita.OverlaySplitView) { + _ = splitView.position(trailing: trailing) + } + +} diff --git a/user-manual/Information/Widgets.md b/user-manual/Information/Widgets.md index ace0bb3..47f0c2c 100644 --- a/user-manual/Information/Widgets.md +++ b/user-manual/Information/Widgets.md @@ -13,6 +13,7 @@ This is an overview of the available widgets and other components in _Adwaita_. | List | A widget which arranges child widgets vertically into rows. | GtkListBox | | Menu | A widget showing a button that toggles the appearance of a menu. | GtkMenuButton | | NavigationSplitView | A widget presenting sidebar and content side by side. | AdwNavigationSplitView | +| OverlaySplitView | A widget presenting sidebar and content side by side. | AdwOverlaySplitView | | ScrollView | A container that makes its child scrollable. | GtkScrolledWindow | | StatusPage | A page with an icon, title, and optionally description and widget.| AdwStatusPage | | StateWrapper | A wrapper not affecting the UI which stores state information. | - | @@ -57,6 +58,11 @@ This is an overview of the available widgets and other components in _Adwaita_. | ---------------------------- | --------------------------------------------------------------------------------------- | | `sidebarStyle()` | Change the style of the list to match a sidebar. | +### `OverlaySplitView` Modifiers +| Syntax | Description | +| ---------------------------- | --------------------------------------------------------------------------------------- | +| `trailingSidebar(_:)` | Whether the sidebar is trailing to the content view. | + ### Window Types | Name | Description | Widget | | -------------------- | ----------------------------------------------------------------- | ---------------------- |