Add support for flow boxes
This commit is contained in:
parent
30482196b6
commit
5cf2be2f54
@ -34,6 +34,7 @@
|
||||
- [EntryRow](structs/EntryRow.md)
|
||||
- [ExpanderRow](structs/ExpanderRow.md)
|
||||
- [FileDialog](structs/FileDialog.md)
|
||||
- [FlowBox](structs/FlowBox.md)
|
||||
- [ForEach](structs/ForEach.md)
|
||||
- [Form](structs/Form.md)
|
||||
- [HStack](structs/HStack.md)
|
||||
@ -111,6 +112,7 @@
|
||||
- [Clamp](extensions/Clamp.md)
|
||||
- [ComboRow](extensions/ComboRow.md)
|
||||
- [EntryRow](extensions/EntryRow.md)
|
||||
- [FlowBox](extensions/FlowBox.md)
|
||||
- [FormSection](extensions/FormSection.md)
|
||||
- [HeaderBar](extensions/HeaderBar.md)
|
||||
- [Int](extensions/Int.md)
|
||||
|
||||
21
Documentation/Reference/extensions/FlowBox.md
Normal file
21
Documentation/Reference/extensions/FlowBox.md
Normal file
@ -0,0 +1,21 @@
|
||||
**EXTENSION**
|
||||
|
||||
# `FlowBox`
|
||||
|
||||
## Properties
|
||||
### `selectionField`
|
||||
|
||||
The ID for the field storing the selection value.
|
||||
|
||||
### `elementsField`
|
||||
|
||||
The ID for the field storing the elements.
|
||||
|
||||
## Methods
|
||||
### `init(_:selection:content:)`
|
||||
|
||||
Initialize `FlowBox`.
|
||||
- Parameters:
|
||||
- elements: The elements.
|
||||
- selection: The identifier of the selected element. Selection disabled if `nil`.
|
||||
- content: The view for an element.
|
||||
290
Documentation/Reference/structs/FlowBox.md
Normal file
290
Documentation/Reference/structs/FlowBox.md
Normal file
@ -0,0 +1,290 @@
|
||||
**STRUCT**
|
||||
|
||||
# `FlowBox`
|
||||
|
||||
A `GtkFlowBox` puts child widgets in reflowing grid.
|
||||
|
||||
For instance, with the horizontal orientation, the widgets will be
|
||||
arranged from left to right, starting a new row under the previous
|
||||
row when necessary. Reducing the width in this case will require more
|
||||
rows, so a larger height will be requested.
|
||||
|
||||
Likewise, with the vertical orientation, the widgets will be arranged
|
||||
from top to bottom, starting a new column to the right when necessary.
|
||||
Reducing the height will require more columns, so a larger width will
|
||||
be requested.
|
||||
|
||||
The size request of a `GtkFlowBox` alone may not be what you expect;
|
||||
if you need to be able to shrink it along both axes and dynamically
|
||||
reflow its children, you may have to wrap it in a `GtkScrolledWindow`
|
||||
to enable that.
|
||||
|
||||
The children of a `GtkFlowBox` can be dynamically sorted and filtered.
|
||||
|
||||
Although a `GtkFlowBox` must have only `GtkFlowBoxChild` children, you
|
||||
can add any kind of widget to it via [method@Gtk.FlowBox.insert], and a
|
||||
`GtkFlowBoxChild` widget will automatically be inserted between the box
|
||||
and the widget.
|
||||
|
||||
Also see [class@Gtk.ListBox].
|
||||
|
||||
# CSS nodes
|
||||
|
||||
```
|
||||
flowbox
|
||||
├── flowboxchild
|
||||
│ ╰── <child>├── flowboxchild
|
||||
│ ╰── <child>┊
|
||||
╰── [rubberband]
|
||||
```
|
||||
|
||||
`GtkFlowBox` uses a single CSS node with name flowbox. `GtkFlowBoxChild`
|
||||
uses a single CSS node with name flowboxchild. For rubberband selection,
|
||||
a subnode with name rubberband is used.
|
||||
|
||||
# Accessibility
|
||||
|
||||
`GtkFlowBox` uses the %GTK_ACCESSIBLE_ROLE_GRID role, and `GtkFlowBoxChild`
|
||||
uses the %GTK_ACCESSIBLE_ROLE_GRID_CELL role.
|
||||
|
||||
## Properties
|
||||
### `updateFunctions`
|
||||
|
||||
Additional update functions for type extensions.
|
||||
|
||||
### `appearFunctions`
|
||||
|
||||
Additional appear functions for type extensions.
|
||||
|
||||
### `acceptUnpairedRelease`
|
||||
|
||||
accept-unpaired-release
|
||||
|
||||
### `activateOnSingleClick`
|
||||
|
||||
Determines whether children can be activated with a single
|
||||
click, or require a double-click.
|
||||
|
||||
### `columnSpacing`
|
||||
|
||||
The amount of horizontal space between two children.
|
||||
|
||||
### `homogeneous`
|
||||
|
||||
Determines whether all children should be allocated the
|
||||
same size.
|
||||
|
||||
### `maxChildrenPerLine`
|
||||
|
||||
The maximum amount of children to request space for consecutively
|
||||
in the given orientation.
|
||||
|
||||
### `minChildrenPerLine`
|
||||
|
||||
The minimum number of children to allocate consecutively
|
||||
in the given orientation.
|
||||
|
||||
Setting the minimum children per line ensures
|
||||
that a reasonably small height will be requested
|
||||
for the overall minimum width of the box.
|
||||
|
||||
### `rowSpacing`
|
||||
|
||||
The amount of vertical space between two children.
|
||||
|
||||
### `activateCursorChild`
|
||||
|
||||
Emitted when the user activates the @box.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
|
||||
### `childActivated`
|
||||
|
||||
Emitted when a child has been activated by the user.
|
||||
|
||||
### `moveCursor`
|
||||
|
||||
Emitted when the user initiates a cursor movement.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
Applications should not connect to it, but may emit it with
|
||||
g_signal_emit_by_name() if they need to control the cursor
|
||||
programmatically.
|
||||
|
||||
The default bindings for this signal come in two variants,
|
||||
the variant with the Shift modifier extends the selection,
|
||||
the variant without the Shift modifier does not.
|
||||
There are too many key combinations to list them all here.
|
||||
|
||||
- <kbd>←</kbd>, <kbd>→</kbd>, <kbd>↑</kbd>, <kbd>↓</kbd>
|
||||
move by individual children
|
||||
- <kbd>Home</kbd>, <kbd>End</kbd> move to the ends of the box
|
||||
- <kbd>PgUp</kbd>, <kbd>PgDn</kbd> move vertically by pages
|
||||
|
||||
### `selectAll`
|
||||
|
||||
Emitted to select all children of the box,
|
||||
if the selection mode permits it.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
|
||||
The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>a</kbd>.
|
||||
|
||||
### `selectedChildrenChanged`
|
||||
|
||||
Emitted when the set of selected children changes.
|
||||
|
||||
Use [method@Gtk.FlowBox.selected_foreach] or
|
||||
[method@Gtk.FlowBox.get_selected_children] to obtain the
|
||||
selected children.
|
||||
|
||||
### `toggleCursorChild`
|
||||
|
||||
Emitted to toggle the selection of the child that has the focus.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
|
||||
The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>Space</kbd>.
|
||||
|
||||
### `unselectAll`
|
||||
|
||||
Emitted to unselect all children of the box,
|
||||
if the selection mode permits it.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
|
||||
The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>Shift</kbd>-<kbd>a</kbd>.
|
||||
|
||||
### `elements`
|
||||
|
||||
The dynamic widget elements.
|
||||
|
||||
### `content`
|
||||
|
||||
The dynamic widget content.
|
||||
|
||||
### `app`
|
||||
|
||||
The application.
|
||||
|
||||
### `window`
|
||||
|
||||
The window.
|
||||
|
||||
## Methods
|
||||
### `init(_:content:)`
|
||||
|
||||
Initialize `FlowBox`.
|
||||
|
||||
### `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.
|
||||
|
||||
### `acceptUnpairedRelease(_:)`
|
||||
|
||||
accept-unpaired-release
|
||||
|
||||
### `activateOnSingleClick(_:)`
|
||||
|
||||
Determines whether children can be activated with a single
|
||||
click, or require a double-click.
|
||||
|
||||
### `columnSpacing(_:)`
|
||||
|
||||
The amount of horizontal space between two children.
|
||||
|
||||
### `homogeneous(_:)`
|
||||
|
||||
Determines whether all children should be allocated the
|
||||
same size.
|
||||
|
||||
### `maxChildrenPerLine(_:)`
|
||||
|
||||
The maximum amount of children to request space for consecutively
|
||||
in the given orientation.
|
||||
|
||||
### `minChildrenPerLine(_:)`
|
||||
|
||||
The minimum number of children to allocate consecutively
|
||||
in the given orientation.
|
||||
|
||||
Setting the minimum children per line ensures
|
||||
that a reasonably small height will be requested
|
||||
for the overall minimum width of the box.
|
||||
|
||||
### `rowSpacing(_:)`
|
||||
|
||||
The amount of vertical space between two children.
|
||||
|
||||
### `activateCursorChild(_:)`
|
||||
|
||||
Emitted when the user activates the @box.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
|
||||
### `childActivated(_:)`
|
||||
|
||||
Emitted when a child has been activated by the user.
|
||||
|
||||
### `moveCursor(_:)`
|
||||
|
||||
Emitted when the user initiates a cursor movement.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
Applications should not connect to it, but may emit it with
|
||||
g_signal_emit_by_name() if they need to control the cursor
|
||||
programmatically.
|
||||
|
||||
The default bindings for this signal come in two variants,
|
||||
the variant with the Shift modifier extends the selection,
|
||||
the variant without the Shift modifier does not.
|
||||
There are too many key combinations to list them all here.
|
||||
|
||||
- <kbd>←</kbd>, <kbd>→</kbd>, <kbd>↑</kbd>, <kbd>↓</kbd>
|
||||
move by individual children
|
||||
- <kbd>Home</kbd>, <kbd>End</kbd> move to the ends of the box
|
||||
- <kbd>PgUp</kbd>, <kbd>PgDn</kbd> move vertically by pages
|
||||
|
||||
### `selectAll(_:)`
|
||||
|
||||
Emitted to select all children of the box,
|
||||
if the selection mode permits it.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
|
||||
The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>a</kbd>.
|
||||
|
||||
### `selectedChildrenChanged(_:)`
|
||||
|
||||
Emitted when the set of selected children changes.
|
||||
|
||||
Use [method@Gtk.FlowBox.selected_foreach] or
|
||||
[method@Gtk.FlowBox.get_selected_children] to obtain the
|
||||
selected children.
|
||||
|
||||
### `toggleCursorChild(_:)`
|
||||
|
||||
Emitted to toggle the selection of the child that has the focus.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
|
||||
The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>Space</kbd>.
|
||||
|
||||
### `unselectAll(_:)`
|
||||
|
||||
Emitted to unselect all children of the box,
|
||||
if the selection mode permits it.
|
||||
|
||||
This is a [keybinding signal](class.SignalAction.html).
|
||||
|
||||
The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>Shift</kbd>-<kbd>a</kbd>.
|
||||
59
Sources/Adwaita/View/FlowBox+.swift
Normal file
59
Sources/Adwaita/View/FlowBox+.swift
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// FlowBox+.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by david-swift on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
extension FlowBox {
|
||||
|
||||
/// The ID for the field storing the selection value.
|
||||
static var selectionField: String { "selection" }
|
||||
/// The ID for the field storing the elements.
|
||||
static var elementsField: String { "element" }
|
||||
|
||||
/// Initialize `FlowBox`.
|
||||
/// - Parameters:
|
||||
/// - elements: The elements.
|
||||
/// - selection: The identifier of the selected element. Selection disabled if `nil`.
|
||||
/// - content: The view for an element.
|
||||
public init(
|
||||
_ elements: [Element],
|
||||
selection: Binding<Element.ID>?,
|
||||
@ViewBuilder content: @escaping (Element) -> Body
|
||||
) {
|
||||
self.init(elements, content: content)
|
||||
let id: (ViewStorage, [Element]) -> Element.ID? = { storage, elements in
|
||||
if let child = g_list_nth_data(gtk_flow_box_get_selected_children(storage.pointer), 0) {
|
||||
let element = gtk_flow_box_child_get_child(child.cast())
|
||||
return elements[safe: storage.content[.mainContent]?.firstIndex { $0.pointer?.cast() == element }]?.id
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if let selection {
|
||||
appearFunctions.append { storage in
|
||||
storage.fields[Self.selectionField] = selection
|
||||
storage.connectSignal(name: "selected_children_changed", id: Self.selectionField) {
|
||||
if let binding = storage.fields[Self.selectionField] as? Binding<Element.ID>,
|
||||
let elements = storage.fields[Self.elementsField] as? [Element],
|
||||
let id = id(storage, elements) {
|
||||
binding.wrappedValue = id
|
||||
}
|
||||
}
|
||||
}
|
||||
updateFunctions.append { storage in
|
||||
if selection.wrappedValue != id(storage, elements),
|
||||
let index = elements.firstIndex(where: { $0.id == selection.wrappedValue })?.cInt {
|
||||
gtk_flow_box_select_child(storage.pointer, gtk_flow_box_get_child_at_index(storage.pointer, index))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appearFunctions.append { storage in
|
||||
gtk_flow_box_set_selection_mode(storage.pointer, GTK_SELECTION_NONE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// ActionRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Avatar.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Banner.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Bin.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Box.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Button.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ButtonContent.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Carousel.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// CenterBox.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// CheckButton.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Clamp.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ComboRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// EntryRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ExpanderRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
401
Sources/Adwaita/View/Generated/FlowBox.swift
Normal file
401
Sources/Adwaita/View/Generated/FlowBox.swift
Normal file
@ -0,0 +1,401 @@
|
||||
//
|
||||
// FlowBox.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// A `GtkFlowBox` puts child widgets in reflowing grid.
|
||||
///
|
||||
/// For instance, with the horizontal orientation, the widgets will be
|
||||
/// arranged from left to right, starting a new row under the previous
|
||||
/// row when necessary. Reducing the width in this case will require more
|
||||
/// rows, so a larger height will be requested.
|
||||
///
|
||||
/// Likewise, with the vertical orientation, the widgets will be arranged
|
||||
/// from top to bottom, starting a new column to the right when necessary.
|
||||
/// Reducing the height will require more columns, so a larger width will
|
||||
/// be requested.
|
||||
///
|
||||
/// The size request of a `GtkFlowBox` alone may not be what you expect;
|
||||
/// if you need to be able to shrink it along both axes and dynamically
|
||||
/// reflow its children, you may have to wrap it in a `GtkScrolledWindow`
|
||||
/// to enable that.
|
||||
///
|
||||
/// The children of a `GtkFlowBox` can be dynamically sorted and filtered.
|
||||
///
|
||||
/// Although a `GtkFlowBox` must have only `GtkFlowBoxChild` children, you
|
||||
/// can add any kind of widget to it via [method@Gtk.FlowBox.insert], and a
|
||||
/// `GtkFlowBoxChild` widget will automatically be inserted between the box
|
||||
/// and the widget.
|
||||
///
|
||||
/// Also see [class@Gtk.ListBox].
|
||||
///
|
||||
/// # CSS nodes
|
||||
///
|
||||
/// ```
|
||||
/// flowbox
|
||||
/// ├── flowboxchild
|
||||
/// │ ╰── <child>├── flowboxchild
|
||||
/// │ ╰── <child>┊
|
||||
/// ╰── [rubberband]
|
||||
/// ```
|
||||
///
|
||||
/// `GtkFlowBox` uses a single CSS node with name flowbox. `GtkFlowBoxChild`
|
||||
/// uses a single CSS node with name flowboxchild. For rubberband selection,
|
||||
/// a subnode with name rubberband is used.
|
||||
///
|
||||
/// # Accessibility
|
||||
///
|
||||
/// `GtkFlowBox` uses the %GTK_ACCESSIBLE_ROLE_GRID role, and `GtkFlowBoxChild`
|
||||
/// uses the %GTK_ACCESSIBLE_ROLE_GRID_CELL role.
|
||||
public struct FlowBox<Element>: Widget where Element: Identifiable {
|
||||
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage) -> Void] = []
|
||||
|
||||
/// accept-unpaired-release
|
||||
var acceptUnpairedRelease: Bool?
|
||||
/// Determines whether children can be activated with a single
|
||||
/// click, or require a double-click.
|
||||
var activateOnSingleClick: Bool?
|
||||
/// The amount of horizontal space between two children.
|
||||
var columnSpacing: UInt?
|
||||
/// Determines whether all children should be allocated the
|
||||
/// same size.
|
||||
var homogeneous: Bool?
|
||||
/// The maximum amount of children to request space for consecutively
|
||||
/// in the given orientation.
|
||||
var maxChildrenPerLine: UInt?
|
||||
/// The minimum number of children to allocate consecutively
|
||||
/// in the given orientation.
|
||||
///
|
||||
/// Setting the minimum children per line ensures
|
||||
/// that a reasonably small height will be requested
|
||||
/// for the overall minimum width of the box.
|
||||
var minChildrenPerLine: UInt?
|
||||
/// The amount of vertical space between two children.
|
||||
var rowSpacing: UInt?
|
||||
/// Emitted when the user activates the @box.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
var activateCursorChild: (() -> Void)?
|
||||
/// Emitted when a child has been activated by the user.
|
||||
var childActivated: (() -> Void)?
|
||||
/// Emitted when the user initiates a cursor movement.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
/// Applications should not connect to it, but may emit it with
|
||||
/// g_signal_emit_by_name() if they need to control the cursor
|
||||
/// programmatically.
|
||||
///
|
||||
/// The default bindings for this signal come in two variants,
|
||||
/// the variant with the Shift modifier extends the selection,
|
||||
/// the variant without the Shift modifier does not.
|
||||
/// There are too many key combinations to list them all here.
|
||||
///
|
||||
/// - <kbd>←</kbd>, <kbd>→</kbd>, <kbd>↑</kbd>, <kbd>↓</kbd>
|
||||
/// move by individual children
|
||||
/// - <kbd>Home</kbd>, <kbd>End</kbd> move to the ends of the box
|
||||
/// - <kbd>PgUp</kbd>, <kbd>PgDn</kbd> move vertically by pages
|
||||
var moveCursor: (() -> Void)?
|
||||
/// Emitted to select all children of the box,
|
||||
/// if the selection mode permits it.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
///
|
||||
/// The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>a</kbd>.
|
||||
var selectAll: (() -> Void)?
|
||||
/// Emitted when the set of selected children changes.
|
||||
///
|
||||
/// Use [method@Gtk.FlowBox.selected_foreach] or
|
||||
/// [method@Gtk.FlowBox.get_selected_children] to obtain the
|
||||
/// selected children.
|
||||
var selectedChildrenChanged: (() -> Void)?
|
||||
/// Emitted to toggle the selection of the child that has the focus.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
///
|
||||
/// The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>Space</kbd>.
|
||||
var toggleCursorChild: (() -> Void)?
|
||||
/// Emitted to unselect all children of the box,
|
||||
/// if the selection mode permits it.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
///
|
||||
/// The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>Shift</kbd>-<kbd>a</kbd>.
|
||||
var unselectAll: (() -> Void)?
|
||||
/// The dynamic widget elements.
|
||||
var elements: [Element]
|
||||
/// The dynamic widget content.
|
||||
var content: (Element) -> Body
|
||||
/// The application.
|
||||
var app: GTUIApp?
|
||||
/// The window.
|
||||
var window: GTUIApplicationWindow?
|
||||
|
||||
/// Initialize `FlowBox`.
|
||||
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
|
||||
self.elements = elements
|
||||
self.content = content
|
||||
}
|
||||
|
||||
/// 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_flow_box_new()?.opaque())
|
||||
update(storage, modifiers: modifiers, updateProperties: true)
|
||||
|
||||
|
||||
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 activateCursorChild {
|
||||
storage.connectSignal(name: "activate-cursor-child", argCount: 0) {
|
||||
activateCursorChild()
|
||||
}
|
||||
}
|
||||
if let childActivated {
|
||||
storage.connectSignal(name: "child-activated", argCount: 1) {
|
||||
childActivated()
|
||||
}
|
||||
}
|
||||
if let moveCursor {
|
||||
storage.connectSignal(name: "move-cursor", argCount: 4) {
|
||||
moveCursor()
|
||||
}
|
||||
}
|
||||
if let selectAll {
|
||||
storage.connectSignal(name: "select-all", argCount: 0) {
|
||||
selectAll()
|
||||
}
|
||||
}
|
||||
if let selectedChildrenChanged {
|
||||
storage.connectSignal(name: "selected-children-changed", argCount: 0) {
|
||||
selectedChildrenChanged()
|
||||
}
|
||||
}
|
||||
if let toggleCursorChild {
|
||||
storage.connectSignal(name: "toggle-cursor-child", argCount: 0) {
|
||||
toggleCursorChild()
|
||||
}
|
||||
}
|
||||
if let unselectAll {
|
||||
storage.connectSignal(name: "unselect-all", argCount: 0) {
|
||||
unselectAll()
|
||||
}
|
||||
}
|
||||
storage.modify { widget in
|
||||
if let activateOnSingleClick, updateProperties {
|
||||
gtk_flow_box_set_activate_on_single_click(widget, activateOnSingleClick.cBool)
|
||||
}
|
||||
if let columnSpacing, updateProperties {
|
||||
gtk_flow_box_set_column_spacing(widget, columnSpacing.cInt)
|
||||
}
|
||||
if let homogeneous, updateProperties {
|
||||
gtk_flow_box_set_homogeneous(widget, homogeneous.cBool)
|
||||
}
|
||||
if let maxChildrenPerLine, updateProperties {
|
||||
gtk_flow_box_set_max_children_per_line(widget, maxChildrenPerLine.cInt)
|
||||
}
|
||||
if let minChildrenPerLine, updateProperties {
|
||||
gtk_flow_box_set_min_children_per_line(widget, minChildrenPerLine.cInt)
|
||||
}
|
||||
if let rowSpacing, updateProperties {
|
||||
gtk_flow_box_set_row_spacing(widget, rowSpacing.cInt)
|
||||
}
|
||||
|
||||
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
|
||||
let old = storage.fields["element"] as? [Element] ?? []
|
||||
old.identifiableTransform(
|
||||
to: elements,
|
||||
functions: .init { index, element in
|
||||
let child = content(element).widget(modifiers: modifiers).container(modifiers: modifiers)
|
||||
gtk_flow_box_remove(widget, gtk_flow_box_get_child_at_index(widget, index.cInt)?.cast())
|
||||
gtk_flow_box_insert(widget, child.pointer?.cast(), index.cInt)
|
||||
contentStorage.remove(at: index)
|
||||
contentStorage.insert(child, at: index)
|
||||
} delete: { index in
|
||||
gtk_flow_box_remove(widget, gtk_flow_box_get_child_at_index(widget, index.cInt)?.cast())
|
||||
contentStorage.remove(at: index)
|
||||
} insert: { index, element in
|
||||
let child = content(element).widget(modifiers: modifiers).container(modifiers: modifiers)
|
||||
gtk_flow_box_insert(widget, child.pointer?.cast(), index.cInt)
|
||||
contentStorage.insert(child, at: index)
|
||||
}
|
||||
)
|
||||
storage.fields["element"] = elements
|
||||
storage.content[.mainContent] = contentStorage
|
||||
for (index, element) in elements.enumerated() {
|
||||
content(element).widget(modifiers: modifiers).update(contentStorage[index], modifiers: modifiers, updateProperties: updateProperties)
|
||||
}
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage)
|
||||
}
|
||||
}
|
||||
|
||||
/// accept-unpaired-release
|
||||
public func acceptUnpairedRelease(_ acceptUnpairedRelease: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.acceptUnpairedRelease = acceptUnpairedRelease
|
||||
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Determines whether children can be activated with a single
|
||||
/// click, or require a double-click.
|
||||
public func activateOnSingleClick(_ activateOnSingleClick: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activateOnSingleClick = activateOnSingleClick
|
||||
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// The amount of horizontal space between two children.
|
||||
public func columnSpacing(_ columnSpacing: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.columnSpacing = columnSpacing
|
||||
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Determines whether all children should be allocated the
|
||||
/// same size.
|
||||
public func homogeneous(_ homogeneous: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.homogeneous = homogeneous
|
||||
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// The maximum amount of children to request space for consecutively
|
||||
/// in the given orientation.
|
||||
public func maxChildrenPerLine(_ maxChildrenPerLine: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.maxChildrenPerLine = maxChildrenPerLine
|
||||
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// The minimum number of children to allocate consecutively
|
||||
/// in the given orientation.
|
||||
///
|
||||
/// Setting the minimum children per line ensures
|
||||
/// that a reasonably small height will be requested
|
||||
/// for the overall minimum width of the box.
|
||||
public func minChildrenPerLine(_ minChildrenPerLine: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.minChildrenPerLine = minChildrenPerLine
|
||||
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// The amount of vertical space between two children.
|
||||
public func rowSpacing(_ rowSpacing: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.rowSpacing = rowSpacing
|
||||
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Emitted when the user activates the @box.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
public func activateCursorChild(_ activateCursorChild: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activateCursorChild = activateCursorChild
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Emitted when a child has been activated by the user.
|
||||
public func childActivated(_ childActivated: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.childActivated = childActivated
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Emitted when the user initiates a cursor movement.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
/// Applications should not connect to it, but may emit it with
|
||||
/// g_signal_emit_by_name() if they need to control the cursor
|
||||
/// programmatically.
|
||||
///
|
||||
/// The default bindings for this signal come in two variants,
|
||||
/// the variant with the Shift modifier extends the selection,
|
||||
/// the variant without the Shift modifier does not.
|
||||
/// There are too many key combinations to list them all here.
|
||||
///
|
||||
/// - <kbd>←</kbd>, <kbd>→</kbd>, <kbd>↑</kbd>, <kbd>↓</kbd>
|
||||
/// move by individual children
|
||||
/// - <kbd>Home</kbd>, <kbd>End</kbd> move to the ends of the box
|
||||
/// - <kbd>PgUp</kbd>, <kbd>PgDn</kbd> move vertically by pages
|
||||
public func moveCursor(_ moveCursor: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.moveCursor = moveCursor
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Emitted to select all children of the box,
|
||||
/// if the selection mode permits it.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
///
|
||||
/// The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>a</kbd>.
|
||||
public func selectAll(_ selectAll: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.selectAll = selectAll
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Emitted when the set of selected children changes.
|
||||
///
|
||||
/// Use [method@Gtk.FlowBox.selected_foreach] or
|
||||
/// [method@Gtk.FlowBox.get_selected_children] to obtain the
|
||||
/// selected children.
|
||||
public func selectedChildrenChanged(_ selectedChildrenChanged: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.selectedChildrenChanged = selectedChildrenChanged
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Emitted to toggle the selection of the child that has the focus.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
///
|
||||
/// The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>Space</kbd>.
|
||||
public func toggleCursorChild(_ toggleCursorChild: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.toggleCursorChild = toggleCursorChild
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Emitted to unselect all children of the box,
|
||||
/// if the selection mode permits it.
|
||||
///
|
||||
/// This is a [keybinding signal](class.SignalAction.html).
|
||||
///
|
||||
/// The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>Shift</kbd>-<kbd>a</kbd>.
|
||||
public func unselectAll(_ unselectAll: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.unselectAll = unselectAll
|
||||
return newSelf
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// HeaderBar.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Label.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// LevelBar.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// LinkButton.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ListBox.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Menu.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Overlay.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// OverlaySplitView.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// PasswordEntryRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Popover.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// PreferencesGroup.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// PreferencesPage.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// PreferencesRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ProgressBar.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ScrolledWindow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SpinRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// Spinner.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SplitButton.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// StatusPage.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SwitchRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ToastOverlay.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ToggleButton.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// ToolbarView.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// WindowTitle.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 10.02.24.
|
||||
// Created by auto-generation on 12.02.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
@ -220,7 +220,16 @@ struct GenerationConfiguration {
|
||||
]
|
||||
),
|
||||
.init(class: "Overlay", staticWidgets: [.init(name: "overlay", add: "gtk_overlay_add_overlay")]),
|
||||
.init(class: "Popover", excludeProperties: ["pointing-to", "position"], cast: true)
|
||||
.init(class: "Popover", excludeProperties: ["pointing-to", "position"], cast: true),
|
||||
.init(
|
||||
class: "FlowBox",
|
||||
dynamicWidget: .init(
|
||||
insert: "gtk_flow_box_insert",
|
||||
remove: "gtk_flow_box_remove",
|
||||
getElement: "gtk_flow_box_get_child_at_index(widget, index.cInt)?.cast()"
|
||||
),
|
||||
excludeProperties: ["selection-mode"]
|
||||
)
|
||||
]
|
||||
|
||||
/// The unshortening map.
|
||||
|
||||
49
Tests/FlowBoxDemo.swift
Normal file
49
Tests/FlowBoxDemo.swift
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// ListDemo.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by david-swift on 01.01.24.
|
||||
//
|
||||
|
||||
// swiftlint:disable missing_docs no_magic_numbers
|
||||
|
||||
import Adwaita
|
||||
import Foundation
|
||||
|
||||
struct FlowBoxDemo: View {
|
||||
|
||||
@State private var items: [ListDemo.Element] = []
|
||||
@State private var selectedItem = ""
|
||||
|
||||
var view: Body {
|
||||
HStack {
|
||||
Button("Add Element") {
|
||||
let element = ListDemo.Element(id: UUID().uuidString)
|
||||
items.append(element)
|
||||
selectedItem = element.id
|
||||
}
|
||||
Button("Delete Selected Element") {
|
||||
let index = items.firstIndex { $0.id == selectedItem }
|
||||
items = items.filter { $0.id != selectedItem }
|
||||
selectedItem = items[safe: index]?.id ?? items[safe: index ?? 0 - 1]?.id ?? items.first?.id ?? ""
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.style("linked")
|
||||
.halign(.center)
|
||||
if !items.isEmpty {
|
||||
FlowBox(items, selection: $selectedItem) { item in
|
||||
HStack {
|
||||
Text(.init("\(item.id)".prefix(5)))
|
||||
.hexpand()
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.valign(.center)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// swiftlint:enable missing_docs no_magic_numbers
|
||||
@ -24,6 +24,7 @@ enum Page: String, Identifiable, CaseIterable, Codable {
|
||||
case viewSwitcher
|
||||
case form
|
||||
case popover
|
||||
case flowBox
|
||||
|
||||
var id: Self {
|
||||
self
|
||||
@ -35,6 +36,8 @@ enum Page: String, Identifiable, CaseIterable, Codable {
|
||||
return "Overlay Window"
|
||||
case .viewSwitcher:
|
||||
return "View Switcher"
|
||||
case .flowBox:
|
||||
return "Flow Box"
|
||||
default:
|
||||
return rawValue.capitalized
|
||||
}
|
||||
@ -77,6 +80,8 @@ enum Page: String, Identifiable, CaseIterable, Codable {
|
||||
return "Group controls used for data entry."
|
||||
case .popover:
|
||||
return "Present content in a bubble-like context popup."
|
||||
case .flowBox:
|
||||
return "Display views in a reflowing grid."
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,6 +115,8 @@ enum Page: String, Identifiable, CaseIterable, Codable {
|
||||
FormDemo(app: app)
|
||||
case .popover:
|
||||
PopoverDemo()
|
||||
case .flowBox:
|
||||
FlowBoxDemo()
|
||||
}
|
||||
}
|
||||
// swiftlint:enable cyclomatic_complexity
|
||||
|
||||
@ -20,11 +20,11 @@ struct PopoverDemo: View {
|
||||
}
|
||||
.style("suggested-action")
|
||||
.frame(maxSize: 100)
|
||||
}
|
||||
.popover(visible: $visible) {
|
||||
CounterDemo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user