Add ForEach widget for dynamic GtkBox
This commit is contained in:
parent
8d05d22dc6
commit
81e489c62a
@ -34,6 +34,7 @@
|
||||
- [EntryRow](structs/EntryRow.md)
|
||||
- [ExpanderRow](structs/ExpanderRow.md)
|
||||
- [FileDialog](structs/FileDialog.md)
|
||||
- [ForEach](structs/ForEach.md)
|
||||
- [Form](structs/Form.md)
|
||||
- [HStack](structs/HStack.md)
|
||||
- [HeaderBar](structs/HeaderBar.md)
|
||||
|
||||
37
Documentation/Reference/structs/ForEach.md
Normal file
37
Documentation/Reference/structs/ForEach.md
Normal file
@ -0,0 +1,37 @@
|
||||
**STRUCT**
|
||||
|
||||
# `ForEach`
|
||||
|
||||
A dynamic list but without a list design in the user interface.
|
||||
|
||||
## Properties
|
||||
### `elements`
|
||||
|
||||
The dynamic widget elements.
|
||||
|
||||
### `content`
|
||||
|
||||
The dynamic widget content.
|
||||
|
||||
### `horizontal`
|
||||
|
||||
Whether the list is horizontal.
|
||||
|
||||
## Methods
|
||||
### `init(_:horizontal:content:)`
|
||||
|
||||
Initialize `ForEach`.
|
||||
|
||||
### `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.
|
||||
80
Sources/Adwaita/View/ForEach.swift
Normal file
80
Sources/Adwaita/View/ForEach.swift
Normal file
@ -0,0 +1,80 @@
|
||||
//
|
||||
// ForEach.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by david-swift on 30.01.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// A dynamic list but without a list design in the user interface.
|
||||
public struct ForEach<Element>: Widget where Element: Identifiable {
|
||||
|
||||
/// The dynamic widget elements.
|
||||
var elements: [Element]
|
||||
/// The dynamic widget content.
|
||||
var content: (Element) -> Body
|
||||
/// Whether the list is horizontal.
|
||||
var horizontal: Bool
|
||||
|
||||
/// Initialize `ForEach`.
|
||||
public init(_ elements: [Element], horizontal: Bool = false, @ViewBuilder content: @escaping (Element) -> Body) {
|
||||
self.elements = elements
|
||||
self.content = content
|
||||
self.horizontal = horizontal
|
||||
}
|
||||
|
||||
/// 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_box_new(horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, 0)?.opaque()
|
||||
)
|
||||
update(storage, modifiers: modifiers, updateProperties: true)
|
||||
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) {
|
||||
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
|
||||
let old = storage.fields["element"] as? [Element] ?? []
|
||||
let widget: UnsafeMutablePointer<GtkBox>? = storage.pointer?.cast()
|
||||
old.identifiableTransform(
|
||||
to: elements,
|
||||
functions: .init { index, element in
|
||||
let child = content(element).widget(modifiers: modifiers).container(modifiers: modifiers)
|
||||
gtk_box_remove(widget, contentStorage[safe: index]?.pointer?.cast())
|
||||
gtk_box_insert_child_after(widget, child.pointer?.cast(), contentStorage[safe: index]?.pointer?.cast())
|
||||
contentStorage.remove(at: index)
|
||||
contentStorage.insert(child, at: index)
|
||||
} delete: { index in
|
||||
gtk_box_remove(widget, contentStorage[safe: index]?.pointer?.cast())
|
||||
contentStorage.remove(at: index)
|
||||
} insert: { index, element in
|
||||
let child = content(element).widget(modifiers: modifiers).container(modifiers: modifiers)
|
||||
gtk_box_insert_child_after(widget, child.pointer?.cast(), contentStorage[safe: index]?.pointer?.cast())
|
||||
contentStorage.insert(child, at: index)
|
||||
}
|
||||
)
|
||||
if updateProperties {
|
||||
gtk_orientable_set_orientation(
|
||||
widget?.opaque(),
|
||||
horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL
|
||||
)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
# Widgets
|
||||
|
||||
This is an overview of the available widgets and other components in _Adwaita_ that are not auto-generated.
|
||||
This is an overview of the available widgets and other components in _Adwaita_ that are not auto-generated or that are wrappers for easily accessing auto-generated widgets.
|
||||
There are many more widgets available using auto-generation. Learn [how to use them.](AutoGeneratedWidgets.md)
|
||||
|
||||
| Name | Description | Widget |
|
||||
@ -10,6 +10,7 @@ There are many more widgets available using auto-generation. Learn [how to use t
|
||||
| HStack | A widget which arranges child widgets into a single row. | GtkBox |
|
||||
| Toggle | A button with two possible states, on and off. | GtkToggleButton |
|
||||
| List | A widget which arranges child widgets vertically into rows. | GtkListBox |
|
||||
| ForEach | Arrange dynamic widgets vertically or horizontally. | GtkBox |
|
||||
| NavigationSplitView | A widget presenting sidebar and content side by side. | AdwNavigationSplitView |
|
||||
| ScrollView | A container that makes its child scrollable. | GtkScrolledWindow |
|
||||
| ViewSwitcher | A control for switching between different views. | AdwViewSwitcher |
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user