Add support for popovers

This commit is contained in:
david-swift 2024-02-10 16:00:56 +01:00
parent b4e88a4a42
commit 30482196b6
46 changed files with 557 additions and 38 deletions

View File

@ -51,6 +51,7 @@
- [Overlay](structs/Overlay.md) - [Overlay](structs/Overlay.md)
- [OverlaySplitView](structs/OverlaySplitView.md) - [OverlaySplitView](structs/OverlaySplitView.md)
- [PasswordEntryRow](structs/PasswordEntryRow.md) - [PasswordEntryRow](structs/PasswordEntryRow.md)
- [Popover](structs/Popover.md)
- [PreferencesGroup](structs/PreferencesGroup.md) - [PreferencesGroup](structs/PreferencesGroup.md)
- [PreferencesPage](structs/PreferencesPage.md) - [PreferencesPage](structs/PreferencesPage.md)
- [PreferencesRow](structs/PreferencesRow.md) - [PreferencesRow](structs/PreferencesRow.md)
@ -120,6 +121,7 @@
- [OpaquePointer](extensions/OpaquePointer.md) - [OpaquePointer](extensions/OpaquePointer.md)
- [OverlaySplitView](extensions/OverlaySplitView.md) - [OverlaySplitView](extensions/OverlaySplitView.md)
- [PasswordEntryRow](extensions/PasswordEntryRow.md) - [PasswordEntryRow](extensions/PasswordEntryRow.md)
- [Popover](extensions/Popover.md)
- [ProgressBar](extensions/ProgressBar.md) - [ProgressBar](extensions/ProgressBar.md)
- [ScrollView](extensions/ScrollView.md) - [ScrollView](extensions/ScrollView.md)
- [Set](extensions/Set.md) - [Set](extensions/Set.md)

View File

@ -0,0 +1,9 @@
**EXTENSION**
# `Popover`
## Methods
### `init(visible:)`
Initialize either a horizontal or vertical clamp.
- Parameter vertical: Whether it is a vertical clamp.

View File

@ -158,6 +158,14 @@ Set the view's visibility.
Remove all of the content modifiers for the wrapped views. Remove all of the content modifiers for the wrapped views.
- Returns: A view. - Returns: A view.
### `popover(visible:content:)`
Add a popover on top of the view.
- Parameters:
- visible: Whether the popover is displayed.
- content: The popover's content.
- Returns: The view.
### `toast(_:signal:)` ### `toast(_:signal:)`
Present a toast when the signal gets activated. Present a toast when the signal gets activated.

View File

@ -0,0 +1,172 @@
**STRUCT**
# `Popover`
`GtkPopover` is a bubble-like context popup.
![An example GtkPopover](popover.png)
It is primarily meant to provide context-dependent information
or options. Popovers are attached to a parent widget. By default,
they point to the whole widget area, although this behavior can be
changed with [method@Gtk.Popover.set_pointing_to].
The position of a popover relative to the widget it is attached to
can also be changed with [method@Gtk.Popover.set_position]
By default, `GtkPopover` performs a grab, in order to ensure input
events get redirected to it while it is shown, and also so the popover
is dismissed in the expected situations (clicks outside the popover,
or the Escape key being pressed). If no such modal behavior is desired
on a popover, [method@Gtk.Popover.set_autohide] may be called on it to
tweak its behavior.
## GtkPopover as menu replacement
`GtkPopover` is often used to replace menus. The best was to do this
is to use the [class@Gtk.PopoverMenu] subclass which supports being
populated from a `GMenuModel` with [ctor@Gtk.PopoverMenu.new_from_model].
```xml
<section><attribute name="display-hint">horizontal-buttons</attribute><item><attribute name="label">Cut</attribute><attribute name="action">app.cut</attribute><attribute name="verb-icon">edit-cut-symbolic</attribute></item><item><attribute name="label">Copy</attribute><attribute name="action">app.copy</attribute><attribute name="verb-icon">edit-copy-symbolic</attribute></item><item><attribute name="label">Paste</attribute><attribute name="action">app.paste</attribute><attribute name="verb-icon">edit-paste-symbolic</attribute></item></section>
```
# CSS nodes
```
popover.background[.menu]
├── arrow
╰── contents
╰── <child>
```
`GtkPopover` has a main node with name `popover`, an arrow with name `arrow`,
and another node for the content named `contents`. The `popover` node always
gets the `.background` style class. It also gets the `.menu` style class
if the popover is menu-like, e.g. is a [class@Gtk.PopoverMenu].
Particular uses of `GtkPopover`, such as touch selection popups or
magnifiers in `GtkEntry` or `GtkTextView` get style classes like
`.touch-selection` or `.magnifier` to differentiate from plain popovers.
When styling a popover directly, the `popover` node should usually
not have any background. The visible part of the popover can have
a shadow. To specify it in CSS, set the box-shadow of the `contents` node.
Note that, in order to accomplish appropriate arrow visuals, `GtkPopover`
uses custom drawing for the `arrow` node. This makes it possible for the
arrow to change its shape dynamically, but it also limits the possibilities
of styling it using CSS. In particular, the `arrow` gets drawn over the
`content` node's border and shadow, so they look like one shape, which
means that the border width of the `content` node and the `arrow` node should
be the same. The arrow also does not support any border shape other than
solid, no border-radius, only one border width (border-bottom-width is
used) and no box-shadow.
## Properties
### `updateFunctions`
Additional update functions for type extensions.
### `appearFunctions`
Additional appear functions for type extensions.
### `autohide`
Whether to dismiss the popover on outside clicks.
### `cascadePopdown`
Whether the popover pops down after a child popover.
This is used to implement the expected behavior of submenus.
### `child`
The child widget.
### `defaultWidget`
The default widget inside the popover.
### `hasArrow`
Whether to draw an arrow.
### `mnemonicsVisible`
Whether mnemonics are currently visible in this popover.
### `activateDefault`
Emitted whend the user activates the default widget.
This is a [keybinding signal](class.SignalAction.html).
### `closed`
Emitted when the popover is closed.
### `app`
The application.
### `window`
The window.
## Methods
### `init()`
Initialize `Popover`.
### `container(modifiers:)`
Get the widget's view storage.
- Parameter modifiers: The view modifiers.
- Returns: The view storage.
### `update(_:modifiers:updateProperties:)`
Update the widget's view storage.
- Parameters:
- storage: The view storage.
- modifiers: The view modifiers.
- updateProperties: Whether to update the view's properties.
### `autohide(_:)`
Whether to dismiss the popover on outside clicks.
### `cascadePopdown(_:)`
Whether the popover pops down after a child popover.
This is used to implement the expected behavior of submenus.
### `child(_:)`
The child widget.
### `defaultWidget(_:)`
The default widget inside the popover.
### `hasArrow(_:)`
Whether to draw an arrow.
### `mnemonicsVisible(_:)`
Whether mnemonics are currently visible in this popover.
### `activateDefault(_:)`
Emitted whend the user activates the default widget.
This is a [keybinding signal](class.SignalAction.html).
### `closed(_:)`
Emitted when the popover is closed.

View File

@ -2,7 +2,7 @@
// ActionRow.swift // ActionRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Avatar.swift // Avatar.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Banner.swift // Banner.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Bin.swift // Bin.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Box.swift // Box.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Button.swift // Button.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ButtonContent.swift // ButtonContent.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Carousel.swift // Carousel.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// CenterBox.swift // CenterBox.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// CheckButton.swift // CheckButton.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Clamp.swift // Clamp.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ComboRow.swift // ComboRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// EntryRow.swift // EntryRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ExpanderRow.swift // ExpanderRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// HeaderBar.swift // HeaderBar.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Label.swift // Label.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// LevelBar.swift // LevelBar.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// LinkButton.swift // LinkButton.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ListBox.swift // ListBox.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Menu.swift // Menu.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Overlay.swift // Overlay.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// OverlaySplitView.swift // OverlaySplitView.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// PasswordEntryRow.swift // PasswordEntryRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -0,0 +1,238 @@
//
// Popover.swift
// Adwaita
//
// Created by auto-generation on 10.02.24.
//
import CAdw
import LevenshteinTransformations
/// `GtkPopover` is a bubble-like context popup.
///
/// ![An example GtkPopover](popover.png)
///
/// It is primarily meant to provide context-dependent information
/// or options. Popovers are attached to a parent widget. By default,
/// they point to the whole widget area, although this behavior can be
/// changed with [method@Gtk.Popover.set_pointing_to].
///
/// The position of a popover relative to the widget it is attached to
/// can also be changed with [method@Gtk.Popover.set_position]
///
/// By default, `GtkPopover` performs a grab, in order to ensure input
/// events get redirected to it while it is shown, and also so the popover
/// is dismissed in the expected situations (clicks outside the popover,
/// or the Escape key being pressed). If no such modal behavior is desired
/// on a popover, [method@Gtk.Popover.set_autohide] may be called on it to
/// tweak its behavior.
///
/// ## GtkPopover as menu replacement
///
/// `GtkPopover` is often used to replace menus. The best was to do this
/// is to use the [class@Gtk.PopoverMenu] subclass which supports being
/// populated from a `GMenuModel` with [ctor@Gtk.PopoverMenu.new_from_model].
///
/// ```xml
/// <section><attribute name="display-hint">horizontal-buttons</attribute><item><attribute name="label">Cut</attribute><attribute name="action">app.cut</attribute><attribute name="verb-icon">edit-cut-symbolic</attribute></item><item><attribute name="label">Copy</attribute><attribute name="action">app.copy</attribute><attribute name="verb-icon">edit-copy-symbolic</attribute></item><item><attribute name="label">Paste</attribute><attribute name="action">app.paste</attribute><attribute name="verb-icon">edit-paste-symbolic</attribute></item></section>
/// ```
///
/// # CSS nodes
///
/// ```
/// popover.background[.menu]
/// arrow
/// contents
/// <child>
/// ```
///
/// `GtkPopover` has a main node with name `popover`, an arrow with name `arrow`,
/// and another node for the content named `contents`. The `popover` node always
/// gets the `.background` style class. It also gets the `.menu` style class
/// if the popover is menu-like, e.g. is a [class@Gtk.PopoverMenu].
///
/// Particular uses of `GtkPopover`, such as touch selection popups or
/// magnifiers in `GtkEntry` or `GtkTextView` get style classes like
/// `.touch-selection` or `.magnifier` to differentiate from plain popovers.
///
/// When styling a popover directly, the `popover` node should usually
/// not have any background. The visible part of the popover can have
/// a shadow. To specify it in CSS, set the box-shadow of the `contents` node.
///
/// Note that, in order to accomplish appropriate arrow visuals, `GtkPopover`
/// uses custom drawing for the `arrow` node. This makes it possible for the
/// arrow to change its shape dynamically, but it also limits the possibilities
/// of styling it using CSS. In particular, the `arrow` gets drawn over the
/// `content` node's border and shadow, so they look like one shape, which
/// means that the border width of the `content` node and the `arrow` node should
/// be the same. The arrow also does not support any border shape other than
/// solid, no border-radius, only one border width (border-bottom-width is
/// used) and no box-shadow.
public struct Popover: Widget {
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage) -> Void] = []
/// Whether to dismiss the popover on outside clicks.
var autohide: Bool?
/// Whether the popover pops down after a child popover.
///
/// This is used to implement the expected behavior of submenus.
var cascadePopdown: Bool?
/// The child widget.
var child: (() -> Body)?
/// The default widget inside the popover.
var defaultWidget: (() -> Body)?
/// Whether to draw an arrow.
var hasArrow: Bool?
/// Whether mnemonics are currently visible in this popover.
var mnemonicsVisible: Bool?
/// Emitted whend the user activates the default widget.
///
/// This is a [keybinding signal](class.SignalAction.html).
var activateDefault: (() -> Void)?
/// Emitted when the popover is closed.
var closed: (() -> Void)?
/// The application.
var app: GTUIApp?
/// The window.
var window: GTUIApplicationWindow?
/// Initialize `Popover`.
public init() {
}
/// Get the widget's view storage.
/// - Parameter modifiers: The view modifiers.
/// - Returns: The view storage.
public func container(modifiers: [(View) -> View]) -> ViewStorage {
let storage = ViewStorage(gtk_popover_new()?.opaque())
update(storage, modifiers: modifiers, updateProperties: true)
if let childStorage = child?().widget(modifiers: modifiers).storage(modifiers: modifiers) {
storage.content["child"] = [childStorage]
gtk_popover_set_child(storage.pointer?.cast(), childStorage.pointer?.cast())
}
if let defaultWidgetStorage = defaultWidget?().widget(modifiers: modifiers).storage(modifiers: modifiers) {
storage.content["defaultWidget"] = [defaultWidgetStorage]
gtk_popover_set_default_widget(storage.pointer?.cast(), defaultWidgetStorage.pointer?.cast())
}
for function in appearFunctions {
function(storage)
}
return storage
}
/// Update the widget's view storage.
/// - Parameters:
/// - storage: The view storage.
/// - modifiers: The view modifiers.
/// - updateProperties: Whether to update the view's properties.
public func update(_ storage: ViewStorage, modifiers: [(View) -> View], updateProperties: Bool) {
if let activateDefault {
storage.connectSignal(name: "activate-default", argCount: 0) {
activateDefault()
}
}
if let closed {
storage.connectSignal(name: "closed", argCount: 0) {
closed()
}
}
storage.modify { widget in
if let autohide, updateProperties {
gtk_popover_set_autohide(widget?.cast(), autohide.cBool)
}
if let cascadePopdown, updateProperties {
gtk_popover_set_cascade_popdown(widget?.cast(), cascadePopdown.cBool)
}
if let widget = storage.content["child"]?.first {
child?().widget(modifiers: modifiers).update(widget, modifiers: modifiers, updateProperties: updateProperties)
}
if let widget = storage.content["defaultWidget"]?.first {
defaultWidget?().widget(modifiers: modifiers).update(widget, modifiers: modifiers, updateProperties: updateProperties)
}
if let hasArrow, updateProperties {
gtk_popover_set_has_arrow(widget?.cast(), hasArrow.cBool)
}
if let mnemonicsVisible, updateProperties {
gtk_popover_set_mnemonics_visible(widget?.cast(), mnemonicsVisible.cBool)
}
}
for function in updateFunctions {
function(storage)
}
}
/// Whether to dismiss the popover on outside clicks.
public func autohide(_ autohide: Bool? = true) -> Self {
var newSelf = self
newSelf.autohide = autohide
return newSelf
}
/// Whether the popover pops down after a child popover.
///
/// This is used to implement the expected behavior of submenus.
public func cascadePopdown(_ cascadePopdown: Bool? = true) -> Self {
var newSelf = self
newSelf.cascadePopdown = cascadePopdown
return newSelf
}
/// The child widget.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
var newSelf = self
newSelf.child = child
return newSelf
}
/// The default widget inside the popover.
public func defaultWidget(@ViewBuilder _ defaultWidget: @escaping (() -> Body)) -> Self {
var newSelf = self
newSelf.defaultWidget = defaultWidget
return newSelf
}
/// Whether to draw an arrow.
public func hasArrow(_ hasArrow: Bool? = true) -> Self {
var newSelf = self
newSelf.hasArrow = hasArrow
return newSelf
}
/// Whether mnemonics are currently visible in this popover.
public func mnemonicsVisible(_ mnemonicsVisible: Bool? = true) -> Self {
var newSelf = self
newSelf.mnemonicsVisible = mnemonicsVisible
return newSelf
}
/// Emitted whend the user activates the default widget.
///
/// This is a [keybinding signal](class.SignalAction.html).
public func activateDefault(_ activateDefault: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.activateDefault = activateDefault
return newSelf
}
/// Emitted when the popover is closed.
public func closed(_ closed: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.closed = closed
return newSelf
}
}

View File

@ -2,7 +2,7 @@
// PreferencesGroup.swift // PreferencesGroup.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// PreferencesPage.swift // PreferencesPage.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// PreferencesRow.swift // PreferencesRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ProgressBar.swift // ProgressBar.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ScrolledWindow.swift // ScrolledWindow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// SpinRow.swift // SpinRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// Spinner.swift // Spinner.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// SplitButton.swift // SplitButton.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// StatusPage.swift // StatusPage.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// SwitchRow.swift // SwitchRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ToastOverlay.swift // ToastOverlay.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ToggleButton.swift // ToggleButton.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// ToolbarView.swift // ToolbarView.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -2,7 +2,7 @@
// WindowTitle.swift // WindowTitle.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 04.02.24. // Created by auto-generation on 10.02.24.
// //
import CAdw import CAdw

View File

@ -0,0 +1,53 @@
//
// Popover+.swift
// Adwaita
//
// Created by david-swift on 10.02.24.
//
import CAdw
extension Popover {
/// Initialize either a horizontal or vertical clamp.
/// - Parameter vertical: Whether it is a vertical clamp.
init(visible: Binding<Bool>) {
self.init()
appearFunctions.append { storage in
storage.fields["visible"] = visible
storage.connectSignal(name: "closed", id: "visible") {
if let binding = storage.fields["visible"] as? Binding<Bool> {
if binding.wrappedValue {
binding.wrappedValue = false
}
}
}
}
updateFunctions.append { storage in
if let binding = storage.fields["visible"] as? Binding<Bool> {
if binding.wrappedValue {
gtk_popover_popup(storage.pointer?.cast())
} else {
gtk_popover_popdown(storage.pointer?.cast())
}
}
}
}
}
extension View {
/// Add a popover on top of the view.
/// - Parameters:
/// - visible: Whether the popover is displayed.
/// - content: The popover's content.
/// - Returns: The view.
public func popover(visible: Binding<Bool>, @ViewBuilder content: @escaping () -> Body) -> View {
overlay {
Popover(visible: visible)
.child(content)
}
}
}

View File

@ -219,7 +219,8 @@ struct GenerationConfiguration {
"window-placement" "window-placement"
] ]
), ),
.init(class: "Overlay", staticWidgets: [.init(name: "overlay", add: "gtk_overlay_add_overlay")]) .init(class: "Overlay", staticWidgets: [.init(name: "overlay", add: "gtk_overlay_add_overlay")]),
.init(class: "Popover", excludeProperties: ["pointing-to", "position"], cast: true)
] ]
/// The unshortening map. /// The unshortening map.

View File

@ -23,6 +23,7 @@ enum Page: String, Identifiable, CaseIterable, Codable {
case carousel case carousel
case viewSwitcher case viewSwitcher
case form case form
case popover
var id: Self { var id: Self {
self self
@ -74,6 +75,8 @@ enum Page: String, Identifiable, CaseIterable, Codable {
return "Switch the window's view." return "Switch the window's view."
case .form: case .form:
return "Group controls used for data entry." return "Group controls used for data entry."
case .popover:
return "Present content in a bubble-like context popup."
} }
} }
@ -105,6 +108,8 @@ enum Page: String, Identifiable, CaseIterable, Codable {
ViewSwitcherDemo(app: app) ViewSwitcherDemo(app: app)
case .form: case .form:
FormDemo(app: app) FormDemo(app: app)
case .popover:
PopoverDemo()
} }
} }
// swiftlint:enable cyclomatic_complexity // swiftlint:enable cyclomatic_complexity

31
Tests/PopoverDemo.swift Normal file
View File

@ -0,0 +1,31 @@
//
// PopoverDemo.swift
// Adwaita
//
// Created by david-swift on 10.02.24.
//
// swiftlint:disable missing_docs
import Adwaita
struct PopoverDemo: View {
@State private var visible = false
var view: Body {
VStack {
Button("Present Popover") {
visible = true
}
.style("suggested-action")
.frame(maxSize: 100)
}
.popover(visible: $visible) {
CounterDemo()
}
}
}
// swiftlint:enable missing_docs