Compare commits

...

13 Commits

Author SHA1 Message Date
2072c16040 Add support for keypaths where sensible #74 2026-02-04 16:36:51 +01:00
c08a9dc3bd Fix build failing on macOS #74 2026-02-03 20:35:35 +01:00
7e41c9b5df Add exposeGeneratedAppearUpdateFunctions trait #74 2026-02-03 00:29:14 +01:00
6acf83dce3 Fix not building on macOS #78 2026-02-03 00:17:07 +01:00
0fc91dc50e Use new update logic to construct dialog UIs 2026-02-03 00:15:37 +01:00
d0d7d2b6d3 Use the new wrapModifier for simple modifiers 2026-02-03 00:07:26 +01:00
8f6a83dfc3 Move update responsibility to constructor
When constructing views, the top-level constructor should now update
those views directly after the construction process. In adwaita-swift,
this applies only for EitherViews (as Meta will now automatically update
when constructing new scene elements).
2026-02-02 22:44:44 +01:00
c976c29cd0 Add round style class #74 2026-02-02 21:32:10 +01:00
6b76a4c8f4 Use new wrap modifier 2026-02-02 21:26:50 +01:00
19aa17c0ab Fix to work with latest SQLite.swift version 2026-02-02 21:21:43 +01:00
54619c69f4 Add support for specifying the CSS scheme to load 2026-02-02 19:42:31 +01:00
07d6a38edc Remove old style context providers in (css) #74 2026-01-30 14:49:10 +01:00
29194341e2 Fix CSS updating on each view update #74 2026-01-30 14:33:59 +01:00
82 changed files with 917 additions and 581 deletions

View File

@ -1,4 +1,4 @@
// swift-tools-version: 6.0
// swift-tools-version: 6.1
//
// Package.swift
// Adwaita
@ -8,10 +8,25 @@
import PackageDescription
/// The dependencies.
var dependencies: [Package.Dependency] = [
.package(url: "https://git.aparoksha.dev/aparoksha/meta", branch: "main"),
.package(url: "https://git.aparoksha.dev/aparoksha/meta-sqlite", branch: "main"),
.package(
url: "https://git.aparoksha.dev/aparoksha/levenshtein-transformations",
branch: "main"
),
.package(url: "https://github.com/CoreOffice/XMLCoder", from: "0.17.1")
]
#if os(Linux)
dependencies.append(.package(url: "https://github.com/stephencelis/CSQLite", from: "3.50.4"))
#endif
/// The Adwaita package.
let package = Package(
name: "Adwaita",
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
platforms: [.macOS(.v13), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
products: [
.library(
name: "Adwaita",
@ -22,15 +37,8 @@ let package = Package(
targets: ["CAdw"]
)
],
dependencies: [
.package(url: "https://git.aparoksha.dev/aparoksha/meta", branch: "main"),
.package(url: "https://git.aparoksha.dev/aparoksha/meta-sqlite", from: "0.1.0"),
.package(
url: "https://git.aparoksha.dev/aparoksha/levenshtein-transformations",
branch: "main"
),
.package(url: "https://github.com/CoreOffice/XMLCoder", from: "0.17.1")
],
traits: [.trait(name: "exposeGeneratedAppearUpdateFunctions")],
dependencies: dependencies,
targets: [
.systemLibrary(
name: "CAdw",

View File

@ -0,0 +1,23 @@
//
// ColorScheme.swift
// Adwaita
//
// Created by david-swift on 01.02.26.
//
import CAdw
/// The system color scheme.
public enum ColorScheme: UInt32 {
/// The dark color scheme.
case dark = 2
/// The light color scheme.
case light = 3
/// The ColorScheme value as GtkInterfaceColorScheme.
var gtkValue: GtkInterfaceColorScheme {
.init(rawValue)
}
}

View File

@ -108,6 +108,13 @@ extension AnyView {
style("circular", active: active)
}
/// Make a button or similar widget use round appearance.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func round(_ active: Bool = true) -> AnyView {
style("round", active: active)
}
/// Make a button or similar widget appear as a pill.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
@ -271,13 +278,6 @@ extension AnyView {
style("frame", active: active)
}
/// Run a function when the view gets an update.
/// - Parameter onUpdate: The function.
/// - Returns: A view.
public func onUpdate(_ onUpdate: @escaping () -> Void) -> AnyView {
inspect { _, _ in onUpdate() }
}
/// Bind to the view's focus.
/// - Parameter focus: Whether the view is focused.
/// - Returns: A view.
@ -336,15 +336,21 @@ extension AnyView {
}
/// Add CSS classes to the app as soon as the view appears.
/// - Parameter getString: Get the CSS.
/// - Parameters:
/// - scheme: The color scheme.
/// - getString: Get the CSS.
/// - Returns: A view.
public func css(_ getString: @escaping () -> String) -> AnyView {
inspect { storage, updateProperties in
public func css(scheme: ColorScheme? = nil, getString: @escaping () -> String) -> AnyView {
wrap { storage, updateProperties in
let cssID = "internal-css"
let providerID = "internal-css-provider"
let previous = storage.fields[cssID] as? String
let string = getString()
if updateProperties, string != previous {
let provider = gtk_css_provider_new()
if let scheme {
gtui_cssprovider_set_prefers_color_scheme(.init(Int(bitPattern: provider)), scheme.gtkValue)
}
gtk_css_provider_load_from_string(
provider,
string
@ -356,8 +362,32 @@ extension AnyView {
.init(GTK_STYLE_PROVIDER_PRIORITY_APPLICATION)
)
g_object_unref(provider)
storage.fields[cssID] = string
if let oldProvider = storage.fields[providerID] as? OpaquePointer {
gtk_style_context_remove_provider_for_display(
display,
oldProvider
)
}
storage.fields[providerID] = provider?.opaque()
}
}
}
/// Whether the view has a width higher or equal to its natural width.
/// - Parameters:
/// - matches: Whether the content view matches the breakpoint.
/// - padding: Increase the natural width by a certain padding.
public func naturalWidth(matches: Binding<Bool>, padding: Int = 0) -> AnyView {
BreakpointBin(condition: .naturalWidth(padding: padding), matches: matches) { self }
}
/// Whether the view has a height higher or equal to its natural height.
/// - Parameters:
/// - matches: Whether the content view matches the breakpoint.
/// - padding: Increase the natural height by a certain padding.
public func naturalHeight(matches: Binding<Bool>, padding: Int = 0) -> AnyView {
BreakpointBin(condition: .naturalHeight(padding: padding), matches: matches) { self }
}
}

View File

@ -5,6 +5,7 @@
// Created by david-swift on 16.10.24.
//
import CAdw
import Foundation
extension AnyView {
@ -243,90 +244,6 @@ extension AnyView {
.maximumSize(maxHeight ?? -1)
}
/// Add padding around a view.
/// - Parameters:
/// - padding: The size of the padding.
/// - edges: The edges which are affected by the padding.
/// - Returns: A view.
public func padding(_ padding: Int = 10, _ edges: Set<Edge> = .all) -> AnyView {
ModifierWrapper(content: self, padding: padding, edges: edges)
}
/// Add a padding of 10 around a view.
/// - Parameters:
/// - edges: The edges which are affected by the padding.
/// - Returns: A view.
public func padding(_ edges: Set<Edge> = .all) -> AnyView {
padding(10, edges)
}
/// Enable or disable the horizontal expansion.
/// - Parameter enabled: Whether it is enabled or disabled.
/// - Returns: A view.
public func hexpand(_ enabled: Bool = true) -> AnyView {
ModifierWrapper(content: self, hexpand: enabled)
}
/// Enable or disable the vertical expansion.
/// - Parameter enabled: Whether it is enabled or disabled.
/// - Returns: A view.
public func vexpand(_ enabled: Bool = true) -> AnyView {
ModifierWrapper(content: self, vexpand: enabled)
}
/// Set the horizontal alignment.
/// - Parameter align: The alignment.
/// - Returns: A view.
public func halign(_ align: Alignment) -> AnyView {
ModifierWrapper(content: self, halign: align)
}
/// Set the vertical alignment.
/// - Parameter align: The alignment.
/// - Returns: A view.
public func valign(_ align: Alignment) -> AnyView {
ModifierWrapper(content: self, valign: align)
}
/// Set the view's minimal width or height.
/// - Parameters:
/// - minWidth: The minimal width.
/// - minHeight: The minimal height.
/// - Returns: A view.
public func frame(minWidth: Int? = nil, minHeight: Int? = nil) -> AnyView {
ModifierWrapper(content: self, minWidth: minWidth, minHeight: minHeight)
}
/// Add a style class to the view.
/// - Parameters:
/// - style: The style class.
/// - active: Whether the style is currently applied.
/// - Returns: A view.
public func style(_ style: String, active: Bool = true) -> AnyView {
ModifierWrapper(content: self, style: style, styleActive: active)
}
/// Make the view insensitive (useful e.g. in overlays).
/// - Parameter insensitive: Whether the view is insensitive.
/// - Returns: A view.
public func insensitive(_ insensitive: Bool = true) -> AnyView {
ModifierWrapper(content: self, insensitive: insensitive)
}
/// Set the view's visibility.
/// - Parameter visible: Whether the view is visible.
/// - Returns: A view.
public func visible(_ visible: Bool = true) -> AnyView {
ModifierWrapper(content: self, visible: visible)
}
/// Add a tooltip to the widget.
/// - Parameter tooltip: The tooltip text.
/// - Returns: A view.
public func tooltip(_ tooltip: String) -> AnyView {
ModifierWrapper(content: self, tooltip: tooltip)
}
/// Present a toast when the signal gets activated.
/// - Parameters:
/// - title: The title of the toast.
@ -382,22 +299,6 @@ extension AnyView {
BreakpointBin(condition: .minHeight(minHeight), matches: matches) { self }
}
/// Whether the view has a width higher or equal to its natural width.
/// - Parameters:
/// - matches: Whether the content view matches the breakpoint.
/// - padding: Increase the natural width by a certain padding.
public func naturalWidth(matches: Binding<Bool>, padding: Int = 0) -> AnyView {
BreakpointBin(condition: .naturalWidth(padding: padding), matches: matches) { self }
}
/// Whether the view has a height higher or equal to its natural height.
/// - Parameters:
/// - matches: Whether the content view matches the breakpoint.
/// - padding: Increase the natural height by a certain padding.
public func naturalHeight(matches: Binding<Bool>, padding: Int = 0) -> AnyView {
BreakpointBin(condition: .naturalHeight(padding: padding), matches: matches) { self }
}
/// Build the UI from scratch once the identifier changes.
/// - Parameter id: The identifier.
public func id(_ id: CustomStringConvertible) -> AnyView {

View File

@ -0,0 +1,123 @@
//
// AnyView+wrapModifier.swift
// Adwaita
//
// Created by david-swift on 02.02.26.
//
import CAdw
extension AnyView {
/// Add padding around a view.
/// - Parameters:
/// - padding: The size of the padding.
/// - edges: The edges which are affected by the padding.
/// - Returns: A view.
public func padding(_ padding: Int = 10, _ edges: Set<Edge> = .all) -> AnyView {
wrapModifier(properties: [padding, edges]) { storage in
if edges.contains(.leading) { gtk_widget_set_margin_start(storage.opaquePointer?.cast(), padding.cInt) }
if edges.contains(.trailing) { gtk_widget_set_margin_end(storage.opaquePointer?.cast(), padding.cInt) }
if edges.contains(.top) { gtk_widget_set_margin_top(storage.opaquePointer?.cast(), padding.cInt) }
if edges.contains(.bottom) { gtk_widget_set_margin_bottom(storage.opaquePointer?.cast(), padding.cInt) }
}
}
/// Add a padding of 10 around a view.
/// - Parameters:
/// - edges: The edges which are affected by the padding.
/// - Returns: A view.
public func padding(_ edges: Set<Edge> = .all) -> AnyView {
padding(10, edges)
}
/// Enable or disable the horizontal expansion.
/// - Parameter enabled: Whether it is enabled or disabled.
/// - Returns: A view.
public func hexpand(_ enabled: Bool = true) -> AnyView {
wrapModifier(properties: [enabled]) { storage in
gtk_widget_set_hexpand(storage.opaquePointer?.cast(), enabled.cBool)
}
}
/// Enable or disable the vertical expansion.
/// - Parameter enabled: Whether it is enabled or disabled.
/// - Returns: A view.
public func vexpand(_ enabled: Bool = true) -> AnyView {
wrapModifier(properties: [enabled]) { storage in
gtk_widget_set_vexpand(storage.opaquePointer?.cast(), enabled.cBool)
}
}
/// Set the horizontal alignment.
/// - Parameter align: The alignment.
/// - Returns: A view.
public func halign(_ align: Alignment) -> AnyView {
wrapModifier(properties: [align]) { storage in
gtk_widget_set_halign(storage.opaquePointer?.cast(), align.cAlign)
}
}
/// Set the vertical alignment.
/// - Parameter align: The alignment.
/// - Returns: A view.
public func valign(_ align: Alignment) -> AnyView {
wrapModifier(properties: [align]) { storage in
gtk_widget_set_valign(storage.opaquePointer?.cast(), align.cAlign)
}
}
/// Set the view's minimal width or height.
/// - Parameters:
/// - minWidth: The minimal width.
/// - minHeight: The minimal height.
/// - Returns: A view.
public func frame(minWidth: Int? = nil, minHeight: Int? = nil) -> AnyView {
wrapModifier(properties: [minWidth, minHeight]) { storage in
gtk_widget_set_size_request(storage.opaquePointer?.cast(), minWidth?.cInt ?? 1, minHeight?.cInt ?? -1)
}
}
/// Add a style class to the view.
/// - Parameters:
/// - style: The style class.
/// - active: Whether the style is currently applied.
/// - Returns: A view.
public func style(_ style: String, active: Bool = true) -> AnyView {
wrapModifier(properties: [style, active]) { storage in
if active {
gtk_widget_add_css_class(storage.opaquePointer?.cast(), style)
} else {
gtk_widget_remove_css_class(storage.opaquePointer?.cast(), style)
}
}
}
/// Make the view insensitive (useful e.g. in overlays).
/// - Parameter insensitive: Whether the view is insensitive.
/// - Returns: A view.
public func insensitive(_ insensitive: Bool = true) -> AnyView {
wrapModifier(properties: [insensitive]) { storage in
gtk_widget_set_sensitive(storage.opaquePointer?.cast(), insensitive ? 0 : 1)
}
}
/// Set the view's visibility.
/// - Parameter visible: Whether the view is visible.
/// - Returns: A view.
public func visible(_ visible: Bool = true) -> AnyView {
wrapModifier(properties: [visible]) { storage in
gtk_widget_set_visible(storage.opaquePointer?.cast(), visible.cBool)
}
}
/// Add a tooltip to the widget.
/// - Parameter tooltip: The tooltip text.
/// - Returns: A view.
public func tooltip(_ tooltip: String) -> AnyView {
wrapModifier(properties: [tooltip]) { storage in
gtk_widget_set_tooltip_markup(storage.opaquePointer?.cast(), tooltip)
}
}
}

View File

@ -68,9 +68,7 @@ struct AboutDialog: AdwaitaWidget {
/// - type: The view render data type.
/// - Returns: The view storage.
func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let storage = child.storage(data: data, type: type)
update(storage, data: data, updateProperties: true, type: type)
return storage
child.storage(data: data, type: type)
}
/// Update the stored content.

View File

@ -106,9 +106,7 @@ public struct AlertDialog: AdwaitaWidget {
data: WidgetData,
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let storage = child.storage(data: data, type: type)
update(storage, data: data, updateProperties: true, type: type)
return storage
child.storage(data: data, type: type)
}
/// Update the stored content.
@ -217,6 +215,7 @@ public struct AlertDialog: AdwaitaWidget {
storage.content[Self.dialogID + id] = [dialog]
if let extraChild {
let child = extraChild.storage(data: data, type: AdwaitaMainView.self)
extraChild.updateStorage(child, data: data, updateProperties: true, type: AdwaitaMainView.self)
let childPointer = child.pointer as? OpaquePointer
storage.content["extra-child"] = [child]
adw_alert_dialog_set_extra_child(pointer?.cast(), childPointer?.cast())

View File

@ -64,9 +64,7 @@ struct Dialog: AdwaitaWidget {
/// - Returns: The view storage.
func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let child = child.storage(data: data, type: type)
let storage = ViewStorage(child.opaquePointer, content: [.mainContent: [child]])
update(storage, data: data, updateProperties: true, type: type)
return storage
return .init(child.opaquePointer, content: [.mainContent: [child]])
}
/// Update the stored content.
@ -132,6 +130,7 @@ struct Dialog: AdwaitaWidget {
let dialog = ViewStorage(pointer?.opaque())
storage.content[dialogID + id] = [dialog]
let contentStorage = content.storage(data: data, type: type)
content.updateStorage(contentStorage, data: data, updateProperties: true, type: type)
adw_dialog_set_child(pointer, contentStorage.opaquePointer?.cast())
storage.content[contentID + id] = [contentStorage]
dialog.connectSignal(name: "closed") {

View File

@ -105,9 +105,7 @@ struct FileDialog: AdwaitaWidget {
/// - Returns: The view storage.
func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let child = child.storage(data: data, type: type)
let storage = ViewStorage(child.opaquePointer, content: [.mainContent: [child]])
update(storage, data: data, updateProperties: true, type: type)
return storage
return .init(child.opaquePointer, content: [.mainContent: [child]])
}
/// Update the stored content.

View File

@ -153,9 +153,7 @@ public struct PreferencesDialog: AdwaitaWidget {
/// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let child = child.storage(data: data, type: type)
let storage = ViewStorage(child.opaquePointer, content: [.mainContent: [child]])
update(storage, data: data, updateProperties: true, type: type)
return storage
return .init(child.opaquePointer, content: [.mainContent: [child]])
}
/// Update the stored content.

View File

@ -109,9 +109,7 @@ public struct ShortcutsDialog: AdwaitaWidget {
/// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let child = child.storage(data: data, type: type)
let storage = ViewStorage(child.opaquePointer, content: [.mainContent: [child]])
update(storage, data: data, updateProperties: true, type: type)
return storage
return .init(child.opaquePointer, content: [.mainContent: [child]])
}
/// Update the stored content.

View File

@ -17,27 +17,40 @@ extension DropDown {
/// Initialize a combo row.
/// - Parameters:
/// - title: The row's title.
/// - selection: The selected value.
/// - values: The available values.
public init<Element>(
selection: Binding<Element.ID>,
values: [Element]
) where Element: Identifiable, Element: CustomStringConvertible {
self.init(selection: selection, values: values, id: \.id, description: \.description)
}
/// Initialize a combo row.
/// - Parameters:
/// - title: The row's title.
/// - selection: The selected value.
/// - values: The available values.
public init<Element, Identifier>(
selection: Binding<Identifier>,
values: [Element],
id: KeyPath<Element, Identifier>,
description: KeyPath<Element, String>
) where Identifier: Equatable {
self.init()
self = self.selected(.init {
.init(values.firstIndex { $0.id == selection.wrappedValue } ?? 0)
.init(values.firstIndex { $0[keyPath: id] == selection.wrappedValue } ?? 0)
} set: { index in
if let id = values[safe: .init(index)]?.id {
if let id = values[safe: .init(index)]?[keyPath: id] {
selection.wrappedValue = id
}
})
appearFunctions.append { storage, _ in
storage.fields[Self.stringList] = gtk_drop_down_get_model(storage.opaquePointer)
Self.updateContent(storage: storage, values: values, element: Element.self)
Self.updateContent(storage: storage, values: values, id: id, description: description)
}
updateFunctions.append { storage, _, _ in
Self.updateContent(storage: storage, values: values, element: Element.self)
Self.updateContent(storage: storage, values: values, id: id, description: description)
}
}
@ -45,20 +58,23 @@ extension DropDown {
/// - Parameters:
/// - storage: The view storage.
/// - values: The elements.
/// - element: The type of the elements.
static func updateContent<Element>(
/// - id: The keypath to the id.
/// - description: The keypath to the description.
static func updateContent<Element, Identifier>(
storage: ViewStorage,
values: [Element],
element: Element.Type
) where Element: Identifiable, Element: CustomStringConvertible {
id: KeyPath<Element, Identifier>,
description: KeyPath<Element, String>
) where Identifier: Equatable {
if let list = storage.fields[Self.stringList] as? OpaquePointer {
let old = storage.fields[Self.values] as? [Element] ?? []
old.identifiableTransform(
old.transform(
to: values,
id: id,
functions: .init { index in
gtk_string_list_remove(list, .init(index))
} insert: { _, element in
gtk_string_list_append(list, element.description)
gtk_string_list_append(list, element[keyPath: description])
}
)
storage.fields[Self.values] = values

View File

@ -17,19 +17,21 @@ extension FlowBox {
/// Initialize `FlowBox`.
/// - Parameters:
/// - elements: The elements.
/// - id: The element identifier keypath.
/// - 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>? = nil,
id: KeyPath<Element, Identifier>,
selection: Binding<Identifier>? = nil,
@ViewBuilder content: @escaping (Element) -> Body
) {
self.init(elements, content: content)
let id: (ViewStorage, [Element]) -> Element.ID? = { storage, elements in
self.init(elements, id: id, content: content)
let getID: (ViewStorage, [Element]) -> Identifier? = { storage, elements in
if let child = g_list_nth_data(gtk_flow_box_get_selected_children(storage.opaquePointer), 0) {
let element = gtk_flow_box_child_get_child(child.cast())
return elements[safe: storage.content[.mainContent]?
.firstIndex { $0.opaquePointer?.cast() == element }]?.id
.firstIndex { $0.opaquePointer?.cast() == element }]?[keyPath: id]
}
return nil
}
@ -37,12 +39,12 @@ extension FlowBox {
updateFunctions.append { storage, _, _ in
storage.connectSignal(name: "selected_children_changed", id: Self.selectionField) {
if let elements = storage.fields[Self.elementsField] as? [Element],
let id = id(storage, elements) {
let id = getID(storage, elements) {
selection.wrappedValue = id
}
}
if selection.wrappedValue != id(storage, elements),
let index = elements.firstIndex(where: { $0.id == selection.wrappedValue })?.cInt {
if selection.wrappedValue != getID(storage, elements),
let index = elements.firstIndex(where: { $0[keyPath: id] == selection.wrappedValue })?.cInt {
gtk_flow_box_select_child(
storage.opaquePointer,
gtk_flow_box_get_child_at_index(storage.opaquePointer, index)
@ -57,3 +59,20 @@ extension FlowBox {
}
}
extension FlowBox where Element: Identifiable, Identifier == Element.ID {
/// 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>? = nil,
@ViewBuilder content: @escaping (Element) -> Body
) {
self.init(elements, id: \.id, selection: selection, content: content)
}
}

View File

@ -9,7 +9,7 @@ import CAdw
import LevenshteinTransformations
/// A dynamic list but without a list design in the user interface.
public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
public struct ForEach<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
/// The dynamic widget elements.
var elements: [Element]
@ -19,12 +19,20 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
var horizontal: Bool
/// Whether the children should all be the same size.
var homogeneous: Bool?
/// The path to the identifier.
var id: KeyPath<Element, Identifier>
/// Initialize `ForEach`.
public init(_ elements: [Element], horizontal: Bool = false, @ViewBuilder content: @escaping (Element) -> Body) {
public init(
_ elements: [Element],
id: KeyPath<Element, Identifier>,
horizontal: Bool = false,
@ViewBuilder content: @escaping (Element) -> Body
) {
self.elements = elements
self.content = content
self.horizontal = horizontal
self.id = id
}
/// The view storage.
@ -36,11 +44,9 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
data: WidgetData,
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let storage = ViewStorage(
.init(
gtk_box_new(horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, 0)?.opaque()
)
update(storage, data: data, updateProperties: true, type: type)
return storage
}
/// Update the stored content.
@ -58,8 +64,9 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? []
let widget: UnsafeMutablePointer<GtkBox>? = storage.opaquePointer?.cast()
old.identifiableTransform(
old.transform(
to: elements,
id: id,
functions: .init { index in
let child = contentStorage[safe: index]?.opaquePointer
gtk_box_remove(widget, child?.cast())
@ -107,3 +114,15 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
}
}
extension ForEach where Element: Identifiable, Identifier == Element.ID {
/// Initialize `ForEach`.
public init(_ elements: [Element], horizontal: Bool = false, @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements
self.content = content
self.horizontal = horizontal
self.id = \.id
}
}

View File

@ -26,11 +26,26 @@ extension ComboRow {
selection: Binding<Element.ID>,
values: [Element]
) where Element: Identifiable, Element: CustomStringConvertible {
self.init(title, selection: selection, values: values, id: \.id, description: \.description)
}
/// Initialize a combo row.
/// - Parameters:
/// - title: The row's title.
/// - selection: The selected value.
/// - values: The available values.
public init<Element, Identifier>(
_ title: String,
selection: Binding<Identifier>,
values: [Element],
id: KeyPath<Element, Identifier>,
description: KeyPath<Element, String>
) where Identifier: Equatable {
self = self.title(title)
self = self.selected(.init {
.init(values.firstIndex { $0.id == selection.wrappedValue } ?? 0)
.init(values.firstIndex { $0[keyPath: id] == selection.wrappedValue } ?? 0)
} set: { index in
if let id = values[safe: .init(index)]?.id {
if let id = values[safe: .init(index)]?[keyPath: id] {
selection.wrappedValue = id
}
})
@ -39,34 +54,10 @@ extension ComboRow {
storage.fields[Self.stringList] = list
adw_combo_row_set_model(storage.opaquePointer?.cast(), list)
g_object_unref(list?.cast())
Self.updateContent(storage: storage, values: values, element: Element.self)
DropDown.updateContent(storage: storage, values: values, id: id, description: description)
}
updateFunctions.append { storage, _, _ in
Self.updateContent(storage: storage, values: values, element: Element.self)
}
}
/// Update the combo row's content.
/// - Parameters:
/// - storage: The view storage.
/// - values: The elements.
/// - element: The type of the elements.
static func updateContent<Element>(
storage: ViewStorage,
values: [Element],
element: Element.Type
) where Element: Identifiable, Element: CustomStringConvertible {
if let list = storage.fields[Self.stringList] as? OpaquePointer {
let old = storage.fields[Self.values] as? [Element] ?? []
old.identifiableTransform(
to: values,
functions: .init { index in
gtk_string_list_remove(list, .init(index))
} insert: { _, element in
gtk_string_list_append(list, element.description)
}
)
storage.fields[Self.values] = values
DropDown.updateContent(storage: storage, values: values, id: id, description: description)
}
}

View File

@ -15,11 +15,8 @@ public struct Form: SimpleView {
/// The view's body.
public var view: Body {
ModifierWrapper(
content: List([Int](content.indices), selection: nil) { index in content[index] },
style: "boxed-list",
styleActive: true
)
List([Int](content.indices), selection: nil) { index in content[index] }
.style("boxed-list")
}
/// Initialize a `Form`.

View File

@ -2,7 +2,7 @@
// ActionRow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -24,10 +24,17 @@ import LevenshteinTransformations
///
public struct ActionRow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The widget to activate when the row is activated.
///
@ -95,7 +102,6 @@ public struct ActionRow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let activatableWidgetStorage = activatableWidget?.storage(data: data, type: type) {
storage.content["activatableWidget"] = [activatableWidgetStorage]
adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// AspectFrame.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -16,10 +16,17 @@ import LevenshteinTransformations
///
public struct AspectFrame: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -54,7 +61,6 @@ public struct AspectFrame: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_aspect_frame_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// Avatar.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -28,10 +28,17 @@ import LevenshteinTransformations
///
public struct Avatar: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The name of an icon to use as a fallback.
///
@ -65,7 +72,6 @@ public struct Avatar: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// Banner.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -30,10 +30,17 @@ import LevenshteinTransformations
///
public struct Banner: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The label to show on the button.
///
@ -72,7 +79,6 @@ public struct Banner: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// Bin.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -19,10 +19,17 @@ import LevenshteinTransformations
/// for handling a single child widget.
public struct Bin: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The child widget of the `AdwBin`.
var child: Body?
@ -41,7 +48,6 @@ public struct Bin: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
adw_bin_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// Box.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -36,10 +36,17 @@ import LevenshteinTransformations
///
public struct Box: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -73,7 +80,6 @@ public struct Box: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
var appendStorage: [ViewStorage] = []
for view in append() {

View File

@ -2,7 +2,7 @@
// Button.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -19,10 +19,17 @@ import LevenshteinTransformations
///
public struct Button: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -74,7 +81,6 @@ public struct Button: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// ButtonContent.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -28,10 +28,17 @@ import LevenshteinTransformations
///
public struct ButtonContent: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether the button can be smaller than the natural size of its contents.
///
@ -66,7 +73,6 @@ public struct ButtonContent: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// Carousel.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -19,12 +19,19 @@ import LevenshteinTransformations
/// to provide page indicators for `AdwCarousel`.
///
///
public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
public struct Carousel<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether to allow swiping for more than one page at a time.
///
@ -63,11 +70,14 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
var elements: [Element]
/// The dynamic widget content.
var content: (Element) -> Body
/// The dynamic widget identifier key path.
var id: KeyPath<Element, Identifier>
/// Initialize `Carousel`.
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
public init(_ elements: [Element], id: KeyPath<Element, Identifier>, @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements
self.content = content
self.id = id
}
/// The view storage.
@ -80,7 +90,6 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}
@ -120,8 +129,9 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? []
old.identifiableTransform(
old.transform(
to: elements,
id: id,
functions: .init { index in
adw_carousel_remove(widget, adw_carousel_get_nth_page(widget, UInt(index).cInt))
contentStorage.remove(at: index)
@ -206,3 +216,14 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
}
}
extension Carousel where Element: Identifiable, Identifier == Element.ID {
/// Initialize `Carousel`.
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements
self.content = content
self.id = \.id
}
}

View File

@ -2,7 +2,7 @@
// CenterBox.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -23,10 +23,17 @@ import LevenshteinTransformations
///
public struct CenterBox: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -70,7 +77,6 @@ public struct CenterBox: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let centerWidgetStorage = centerWidget?.storage(data: data, type: type) {
storage.content["centerWidget"] = [centerWidgetStorage]
gtk_center_box_set_center_widget(storage.opaquePointer, centerWidgetStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// CheckButton.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -22,10 +22,17 @@ import LevenshteinTransformations
///
public struct CheckButton: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -79,7 +86,6 @@ public struct CheckButton: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_check_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// Clamp.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -28,10 +28,17 @@ import LevenshteinTransformations
///
public struct Clamp: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The child widget of the `AdwClamp`.
var child: Body?
@ -69,7 +76,6 @@ public struct Clamp: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
adw_clamp_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// ComboRow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -32,10 +32,17 @@ import LevenshteinTransformations
///
public struct ComboRow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The widget to activate when the row is activated.
///
@ -125,7 +132,6 @@ public struct ComboRow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let activatableWidgetStorage = activatableWidget?.storage(data: data, type: type) {
storage.content["activatableWidget"] = [activatableWidgetStorage]
adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// DropDown.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -48,10 +48,17 @@ import LevenshteinTransformations
///
public struct DropDown: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -89,7 +96,6 @@ public struct DropDown: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// Entry.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -48,10 +48,17 @@ import LevenshteinTransformations
///
public struct Entry: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -279,7 +286,6 @@ public struct Entry: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let extraMenu {
let childStorage = MenuCollection { extraMenu }.getMenu(data: data)
storage.content["extraMenu"] = [childStorage]

View File

@ -2,7 +2,7 @@
// EntryRow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -29,10 +29,17 @@ import LevenshteinTransformations
///
public struct EntryRow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether activating the embedded entry can activate the default widget.
var activatesDefault: Bool?
@ -96,7 +103,6 @@ public struct EntryRow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
var suffixStorage: [ViewStorage] = []
for view in suffix() {

View File

@ -2,7 +2,7 @@
// ExpanderRow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -19,10 +19,17 @@ import LevenshteinTransformations
///
public struct ExpanderRow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether expansion is enabled.
var enableExpansion: Binding<Bool>?
@ -82,7 +89,6 @@ public struct ExpanderRow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
var rowsStorage: [ViewStorage] = []
for view in rows() {

View File

@ -2,7 +2,7 @@
// Fixed.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -47,10 +47,17 @@ import LevenshteinTransformations
/// widget. But you should be aware of the tradeoffs.
public struct Fixed: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -71,7 +78,6 @@ public struct Fixed: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// FlowBox.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -37,12 +37,19 @@ import LevenshteinTransformations
/// Also see `Gtk.ListBox`.
///
///
public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
public struct FlowBox<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether to accept unpaired release events.
var acceptUnpairedRelease: Bool?
@ -123,11 +130,14 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
var elements: [Element]
/// The dynamic widget content.
var content: (Element) -> Body
/// The dynamic widget identifier key path.
var id: KeyPath<Element, Identifier>
/// Initialize `FlowBox`.
init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
init(_ elements: [Element], id: KeyPath<Element, Identifier>, @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements
self.content = content
self.id = id
}
/// The view storage.
@ -140,7 +150,6 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}
@ -210,8 +219,9 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? []
old.identifiableTransform(
old.transform(
to: elements,
id: id,
functions: .init { index in
gtk_flow_box_remove(widget, gtk_flow_box_get_child_at_index(widget, index.cInt)?.cast())
contentStorage.remove(at: index)
@ -371,3 +381,14 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
}
}
extension FlowBox where Element: Identifiable, Identifier == Element.ID {
/// Initialize `FlowBox`.
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements
self.content = content
self.id = \.id
}
}

View File

@ -2,7 +2,7 @@
// HeaderBar.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -19,10 +19,17 @@ import LevenshteinTransformations
///
public struct HeaderBar: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The decoration layout for buttons.
///
@ -92,7 +99,6 @@ public struct HeaderBar: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let titleWidgetStorage = titleWidget?.storage(data: data, type: type) {
storage.content["titleWidget"] = [titleWidgetStorage]
adw_header_bar_set_title_widget(storage.opaquePointer, titleWidgetStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// Image.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -41,10 +41,17 @@ import LevenshteinTransformations
///
public struct Image: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -85,7 +92,6 @@ public struct Image: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// Label.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -17,10 +17,17 @@ import LevenshteinTransformations
///
public struct Label: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -121,7 +128,6 @@ public struct Label: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let mnemonicWidgetStorage = mnemonicWidget?.storage(data: data, type: type) {
storage.content["mnemonicWidget"] = [mnemonicWidgetStorage]
gtk_label_set_mnemonic_widget(storage.opaquePointer, mnemonicWidgetStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// LevelBar.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -29,10 +29,17 @@ import LevenshteinTransformations
///
public struct LevelBar: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -73,7 +80,6 @@ public struct LevelBar: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// LinkButton.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -29,10 +29,17 @@ import LevenshteinTransformations
///
public struct LinkButton: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -91,7 +98,6 @@ public struct LinkButton: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// ListBox.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -34,12 +34,19 @@ import LevenshteinTransformations
/// as selected when the user tries to select it.
///
///
public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
public struct ListBox<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether to accept unpaired release events.
var acceptUnpairedRelease: Bool?
@ -100,11 +107,14 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
var elements: [Element]
/// The dynamic widget content.
var content: (Element) -> Body
/// The dynamic widget identifier key path.
var id: KeyPath<Element, Identifier>
/// Initialize `ListBox`.
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
public init(_ elements: [Element], id: KeyPath<Element, Identifier>, @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements
self.content = content
self.id = id
}
/// The view storage.
@ -117,7 +127,6 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}
@ -180,8 +189,9 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? []
old.identifiableTransform(
old.transform(
to: elements,
id: id,
functions: .init { index in
gtk_list_box_remove(widget, gtk_list_box_get_row_at_index(widget, index.cInt)?.cast())
contentStorage.remove(at: index)
@ -314,3 +324,14 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
}
}
extension ListBox where Element: Identifiable, Identifier == Element.ID {
/// Initialize `ListBox`.
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements
self.content = content
self.id = \.id
}
}

View File

@ -2,7 +2,7 @@
// Menu.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -44,10 +44,17 @@ import LevenshteinTransformations
///
public struct Menu: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -99,7 +106,6 @@ public struct Menu: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_menu_button_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// NavigationView.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -39,10 +39,17 @@ import LevenshteinTransformations
///
public struct NavigationView: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether to animate page transitions.
///
@ -114,7 +121,6 @@ public struct NavigationView: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// Overlay.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -31,10 +31,17 @@ import LevenshteinTransformations
///
public struct Overlay: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -74,7 +81,6 @@ public struct Overlay: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_overlay_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// OverlaySplitView.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -50,10 +50,17 @@ import LevenshteinTransformations
///
public struct OverlaySplitView: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether the split view is collapsed.
///
@ -120,7 +127,6 @@ public struct OverlaySplitView: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let contentStorage = content?.storage(data: data, type: type) {
storage.content["content"] = [contentStorage]
adw_overlay_split_view_set_content(storage.opaquePointer, contentStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// PasswordEntryRow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -23,10 +23,17 @@ import LevenshteinTransformations
///
public struct PasswordEntryRow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether activating the embedded entry can activate the default widget.
var activatesDefault: Bool?
@ -90,7 +97,6 @@ public struct PasswordEntryRow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
var suffixStorage: [ViewStorage] = []
for view in suffix() {

View File

@ -2,7 +2,7 @@
// Picture.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -38,10 +38,17 @@ import LevenshteinTransformations
///
public struct Picture: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -68,7 +75,6 @@ public struct Picture: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// Popover.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -35,10 +35,17 @@ import LevenshteinTransformations
///
public struct Popover: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -81,7 +88,6 @@ public struct Popover: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_popover_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// PreferencesGroup.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -24,10 +24,17 @@ import LevenshteinTransformations
/// [`.boxed-list-separate`](style-classes.html
public struct PreferencesGroup: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The description for this group of preferences.
var description: String?
@ -62,7 +69,6 @@ public struct PreferencesGroup: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let headerSuffixStorage = headerSuffix?.storage(data: data, type: type) {
storage.content["headerSuffix"] = [headerSuffixStorage]
adw_preferences_group_set_header_suffix(storage.opaquePointer?.cast(), headerSuffixStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// PreferencesPage.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -18,10 +18,17 @@ import LevenshteinTransformations
///
public struct PreferencesPage: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The description to be displayed at the top of the page.
var description: String?
@ -52,7 +59,6 @@ public struct PreferencesPage: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
var childStorage: [ViewStorage] = []
for view in child() {

View File

@ -2,7 +2,7 @@
// PreferencesRow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -19,10 +19,17 @@ import LevenshteinTransformations
/// compose the inputs of the preference around it.
public struct PreferencesRow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The title of the preference represented by this row.
///
@ -56,7 +63,6 @@ public struct PreferencesRow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// ProgressBar.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -36,10 +36,17 @@ import LevenshteinTransformations
///
public struct ProgressBar: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -79,7 +86,6 @@ public struct ProgressBar: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// ScrolledWindow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -42,10 +42,17 @@ import LevenshteinTransformations
///
public struct ScrolledWindow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -153,7 +160,6 @@ public struct ScrolledWindow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_scrolled_window_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// SearchBar.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -30,10 +30,17 @@ import LevenshteinTransformations
///
public struct SearchBar: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -62,7 +69,6 @@ public struct SearchBar: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_search_bar_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// SearchEntry.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -41,10 +41,17 @@ import LevenshteinTransformations
///
public struct SearchEntry: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -157,7 +164,6 @@ public struct SearchEntry: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// Separator.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -19,10 +19,17 @@ import LevenshteinTransformations
///
public struct Separator: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -43,7 +50,6 @@ public struct Separator: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// SpinRow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -23,10 +23,17 @@ import LevenshteinTransformations
///
public struct SpinRow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The widget to activate when the row is activated.
///
@ -125,7 +132,6 @@ public struct SpinRow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let activatableWidgetStorage = activatableWidget?.storage(data: data, type: type) {
storage.content["activatableWidget"] = [activatableWidgetStorage]
adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// Spinner.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -31,10 +31,17 @@ import LevenshteinTransformations
///
public struct Spinner: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Initialize `Spinner`.
@ -51,7 +58,6 @@ public struct Spinner: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// SplitButton.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -21,10 +21,17 @@ import LevenshteinTransformations
///
public struct SplitButton: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether the button can be smaller than the natural size of its contents.
///
@ -89,7 +96,6 @@ public struct SplitButton: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
adw_split_button_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// StatusPage.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -18,10 +18,17 @@ import LevenshteinTransformations
///
public struct StatusPage: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The child widget.
var child: Body?
@ -50,7 +57,6 @@ public struct StatusPage: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
adw_status_page_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// SwitchRow.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -32,10 +32,17 @@ import LevenshteinTransformations
///
public struct SwitchRow: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The widget to activate when the row is activated.
///
@ -105,7 +112,6 @@ public struct SwitchRow: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let activatableWidgetStorage = activatableWidget?.storage(data: data, type: type) {
storage.content["activatableWidget"] = [activatableWidgetStorage]
adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// ToastOverlay.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -24,10 +24,17 @@ import LevenshteinTransformations
///
public struct ToastOverlay: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The child widget.
var child: Body?
@ -46,7 +53,6 @@ public struct ToastOverlay: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
adw_toast_overlay_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// ToggleButton.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -26,10 +26,17 @@ import LevenshteinTransformations
///
public struct ToggleButton: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation.
///
@ -85,7 +92,6 @@ public struct ToggleButton: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let childStorage = child?.storage(data: data, type: type) {
storage.content["child"] = [childStorage]
gtk_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// ToggleGroup.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -46,10 +46,17 @@ import LevenshteinTransformations
///
public struct ToggleGroup: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The index of the active toggle.
///
@ -91,7 +98,6 @@ public struct ToggleGroup: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -2,7 +2,7 @@
// ToolbarView.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -33,10 +33,17 @@ import LevenshteinTransformations
/// [`.toolbar`](style-classes.html
public struct ToolbarView: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The current bottom bar height.
///
@ -120,7 +127,6 @@ public struct ToolbarView: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
if let contentStorage = content?.storage(data: data, type: type) {
storage.content["content"] = [contentStorage]
adw_toolbar_view_set_content(storage.opaquePointer, contentStorage.opaquePointer?.cast())

View File

@ -2,7 +2,7 @@
// WindowTitle.swift
// Adwaita
//
// Created by auto-generation on 30.12.25.
// Created by auto-generation on 04.02.26.
//
import CAdw
@ -18,10 +18,17 @@ import LevenshteinTransformations
///
public struct WindowTitle: AdwaitaWidget {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The subtitle to display.
///
@ -49,7 +56,6 @@ public struct WindowTitle: AdwaitaWidget {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
return storage
}

View File

@ -17,11 +17,7 @@ public struct HStack: SimpleView {
/// The view's body.
public var view: Body {
ModifierWrapper(
content: VStack(horizontal: true, spacing: spacing, content: content),
style: "linked",
styleActive: linked
)
VStack(horizontal: true, spacing: spacing, content: content)
}
/// Initialize a `HStack`.

View File

@ -1,24 +0,0 @@
//
// List+.swift
// Adwaita
//
// Created by david-swift on 16.10.24.
//
extension List {
/// Add the "navigation-sidebar" style class.
/// - Parameter active: Whether the style is applied.
/// - Returns: A view.
public func sidebarStyle(_ active: Bool = true) -> AnyView {
style("navigation-sidebar", active: active)
}
/// Apply the boxed list style class.
/// - Parameter active: Whether the style is applied.
/// - Returns: A view.
public func boxedList(_ active: Bool = true) -> AnyView {
style("boxed-list", active: active)
}
}

View File

@ -21,17 +21,19 @@ extension List {
/// Initialize `List`.
/// - Parameters:
/// - elements: The elements.
/// - id: The key path to the elements' identifiers.
/// - 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>?,
id: KeyPath<Element, Identifier>,
selection: Binding<Identifier>?,
@ViewBuilder content: @escaping (Element) -> Body
) {
self.init(elements, content: content)
let id: (ViewStorage, [Element]) -> Element.ID? = { storage, elements in
self.init(elements, id: id, content: content)
let getID: (ViewStorage, [Element]) -> Identifier? = { storage, elements in
if let row = gtk_list_box_get_selected_row(storage.opaquePointer) {
return elements[safe: .init(gtk_list_box_row_get_index(row))]?.id
return elements[safe: .init(gtk_list_box_row_get_index(row))]?[keyPath: id]
}
return nil
}
@ -39,13 +41,13 @@ extension List {
updateFunctions.append { storage, _, _ in
storage.connectSignal(name: "selected_rows_changed", id: Self.selectionField) {
if let elements = storage.fields[Self.elementsField] as? [Element],
let id = id(storage, elements),
let id = getID(storage, elements),
selection.wrappedValue != id {
selection.wrappedValue = id
}
}
if selection.wrappedValue != id(storage, elements),
let index = elements.firstIndex(where: { $0.id == selection.wrappedValue })?.cInt {
if selection.wrappedValue != getID(storage, elements),
let index = elements.firstIndex(where: { $0[keyPath: id] == selection.wrappedValue })?.cInt {
gtk_list_box_select_row(
storage.opaquePointer,
gtk_list_box_get_row_at_index(storage.opaquePointer, index)
@ -59,4 +61,35 @@ extension List {
}
}
/// Add the "navigation-sidebar" style class.
/// - Parameter active: Whether the style is applied.
/// - Returns: A view.
public func sidebarStyle(_ active: Bool = true) -> AnyView {
style("navigation-sidebar", active: active)
}
/// Apply the boxed list style class.
/// - Parameter active: Whether the style is applied.
/// - Returns: A view.
public func boxedList(_ active: Bool = true) -> AnyView {
style("boxed-list", active: active)
}
}
extension List where Element: Identifiable, Element.ID == Identifier {
/// Initialize `List`.
/// - 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, id: \.id, selection: selection, content: content)
}
}

View File

@ -1,192 +0,0 @@
//
// ModifierWrapper.swift
// Adwaita
//
// Created by david-swift on 04.09.24.
//
import CAdw
/// A wrapper for view modifiers for any view.
struct ModifierWrapper: AdwaitaWidget {
/// The view.
var content: AnyView
/// The padding.
var padding: Int?
/// The padding edges.
var edges: Set<Edge>?
/// Whether to expand horizontally.
var hexpand: Bool?
/// Whether to expand vertically.
var vexpand: Bool?
/// The horizontal alignment.
var halign: Alignment?
/// The vertical alignment.
var valign: Alignment?
/// The minimum width.
var minWidth: Int?
/// The minimum height.
var minHeight: Int?
/// The style class.
var style: String?
/// Whether the style is active.
var styleActive: Bool?
/// Whether the view is insensitive.
var insensitive: Bool?
/// Whether the view is visible.
var visible: Bool?
/// The tooltip.
var tooltip: String?
/// Initialize a modifier wrapper.
/// - Parameters:
/// - content: The view.
/// - padding: The padding.
/// - edges: The padding edges.
/// - hexpand: Whether to expand horizontally.
/// - vexpand: Whether to expand vertically.
/// - halign: The horizontal alignment.
/// - valign: The vertical alignment.
/// - minWidth: The minimum width.
/// - minHeight: The minimum height.
/// - style: The style class.
/// - styleActive: Whether the style is active.
/// - insensitive: Whether the view is insensitive.
/// - visible: Whether the view is visible.
/// - tooltip: The tooltip.
init(
content: AnyView,
padding: Int? = nil,
edges: Set<Edge>? = nil,
hexpand: Bool? = nil,
vexpand: Bool? = nil,
halign: Alignment? = nil,
valign: Alignment? = nil,
minWidth: Int? = nil,
minHeight: Int? = nil,
style: String? = nil,
styleActive: Bool? = nil,
insensitive: Bool? = nil,
visible: Bool? = nil,
tooltip: String? = nil
) {
self.content = content
self.padding = padding
self.edges = edges
self.hexpand = hexpand
self.vexpand = vexpand
self.halign = halign
self.valign = valign
self.minWidth = minWidth
self.minHeight = minHeight
self.style = style
self.styleActive = styleActive
self.insensitive = insensitive
self.visible = visible
self.tooltip = tooltip
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The view render data type.
/// - Returns: The view storage.
func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let content = content.storage(data: data, type: type)
let storage = ViewStorage(content.pointer, content: [.mainContent: [content]])
update(storage, data: data, updateProperties: true, type: type)
return storage
}
/// Update the stored content.
/// - Parameters:
/// - storage: The storage to update.
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The view render data type.
func update<Data>(
_ storage: ViewStorage,
data: WidgetData,
updateProperties: Bool,
type: Data.Type
) where Data: ViewRenderData {
if let storage = storage.content[.mainContent]?.first {
content.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
}
guard updateProperties else {
return
}
update1(storage, data: data, updateProperties: updateProperties, type: type)
update2(storage, data: data, updateProperties: updateProperties, type: type)
storage.previousState = self
}
/// Update part 1 of the properties.
/// - Parameters:
/// - storage: The storage to update.
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The view render data type.
func update1<Data>(
_ storage: ViewStorage,
data: WidgetData,
updateProperties: Bool,
type: Data.Type
) where Data: ViewRenderData {
let previousState = storage.previousState as? Self
if let padding, let edges, previousState?.padding != padding || previousState?.edges != edges {
if edges.contains(.leading) { gtk_widget_set_margin_start(storage.opaquePointer?.cast(), padding.cInt) }
if edges.contains(.trailing) { gtk_widget_set_margin_end(storage.opaquePointer?.cast(), padding.cInt) }
if edges.contains(.top) { gtk_widget_set_margin_top(storage.opaquePointer?.cast(), padding.cInt) }
if edges.contains(.bottom) { gtk_widget_set_margin_bottom(storage.opaquePointer?.cast(), padding.cInt) }
}
if let hexpand, previousState?.hexpand != hexpand {
gtk_widget_set_hexpand(storage.opaquePointer?.cast(), hexpand.cBool)
}
if let vexpand, previousState?.vexpand != vexpand {
gtk_widget_set_vexpand(storage.opaquePointer?.cast(), vexpand.cBool)
}
if let halign, previousState?.halign != halign {
gtk_widget_set_halign(storage.opaquePointer?.cast(), halign.cAlign)
}
if let valign, previousState?.valign != valign {
gtk_widget_set_valign(storage.opaquePointer?.cast(), valign.cAlign)
}
}
/// Update part 2 of the properties.
/// - Parameters:
/// - storage: The storage to update.
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The view render data type.
func update2<Data>(
_ storage: ViewStorage,
data: WidgetData,
updateProperties: Bool,
type: Data.Type
) where Data: ViewRenderData {
let previousState = storage.previousState as? Self
if minWidth != previousState?.minWidth || minHeight != previousState?.minHeight {
gtk_widget_set_size_request(storage.opaquePointer?.cast(), minWidth?.cInt ?? 1, minHeight?.cInt ?? -1)
}
if let style, let styleActive, previousState?.styleActive != styleActive {
if styleActive {
gtk_widget_add_css_class(storage.opaquePointer?.cast(), style)
} else {
gtk_widget_remove_css_class(storage.opaquePointer?.cast(), style)
}
}
if let insensitive, previousState?.insensitive != insensitive {
gtk_widget_set_sensitive(storage.opaquePointer?.cast(), insensitive ? 0 : 1)
}
if let visible, previousState?.visible != visible {
gtk_widget_set_visible(storage.opaquePointer?.cast(), visible.cBool)
}
if let tooltip, previousState?.tooltip != tooltip {
gtk_widget_set_tooltip_markup(storage.opaquePointer?.cast(), tooltip)
}
}
}

View File

@ -58,7 +58,6 @@ public struct NavigationSplitView: AdwaitaWidget {
content[contentID] = [mainContent]
let storage = ViewStorage(splitView?.opaque(), content: content)
update(storage, data: data, updateProperties: true, type: type)
storage.fields["sidebar-page"] = sidebarPage?.opaque()
storage.fields["main-page"] = mainPage?.opaque()

View File

@ -111,6 +111,8 @@ extension NavigationView {
} else { print("Warning: removing the initial view is not allowed.") }
case let .push(component):
let contentStorage = views.0(component).storage(data: data, type: AdwaitaMainView.self)
views.0(component)
.updateStorage(contentStorage, data: data, updateProperties: true, type: AdwaitaMainView.self)
contentStorage.fields[Self.componentID] = component
storages.append(contentStorage)
adw_navigation_view_push(

View File

@ -104,7 +104,6 @@ public struct TextView: AdwaitaWidget {
content: ["buffer": [buffer]]
)
initProperties(editor, data: data, type: type)
update(editor, data: data, updateProperties: true, type: type)
return editor
}

View File

@ -23,72 +23,103 @@ extension ToggleGroup {
selection: Binding<Element.ID>,
values: [Element]
) where Element: ToggleGroupItem {
self.init(
selection: selection,
values: values,
id: \.id,
label: \.id.description,
icon: \.icon,
showLabel: \.showLabel
)
}
/// Initialize a toggle group.
/// - Parameters:
/// - selection: The selected value.
/// - values: The available values.
/// - id: The path to the identifier.
/// - label: The path to the label.
/// - icon: The path to the icon.
/// - showLabel: The path to the boolean that defines whether to show an element's label.
public init<Element, Identifier>(
selection: Binding<Identifier>,
values: [Element],
id: KeyPath<Element, Identifier>,
label: KeyPath<Element, String>,
icon: KeyPath<Element, Icon?>? = nil,
showLabel: KeyPath<Element, Bool>? = nil
) where Identifier: Equatable {
self.init()
appearFunctions.append { storage, _ in
storage.notify(name: "active-name", id: "init") {
if let name = adw_toggle_group_get_active_name(storage.opaquePointer),
let values = storage.fields[Self.values] as? [Element],
let value = values.first(where: { $0.id.description == String(cString: name) }) {
selection.wrappedValue = value.id
let identifier = values
.map({ $0[keyPath: label] }).first(where: { $0.description == String(cString: name) }),
let value = values.first(where: { $0[keyPath: label] == identifier }) {
selection.wrappedValue = value[keyPath: id]
}
}
Self.updateContent(
storage: storage,
selection: selection.wrappedValue,
values: values,
updateProperties: true
)
}
updateFunctions.append { storage, _, updateProperties in
Self.updateContent(
storage: storage,
selection: selection.wrappedValue,
values: values,
id: id,
label: label,
icon: icon,
showLabel: showLabel,
updateProperties: updateProperties
)
}
}
// swiftlint:disable function_parameter_count
/// Update the combo row's content.
/// - Parameters:
/// - storage: The view storage.
/// - values: The elements.
/// - updateProperties: Whether to update the properties.
static func updateContent<Element>(
static func updateContent<Element, Identifier>(
storage: ViewStorage,
selection: Element.ID,
selection: Identifier,
values: [Element],
id: KeyPath<Element, Identifier>,
label: KeyPath<Element, String>,
icon: KeyPath<Element, Icon?>?,
showLabel: KeyPath<Element, Bool>?,
updateProperties: Bool
) where Element: ToggleGroupItem {
) where Identifier: Equatable {
guard updateProperties else {
return
}
let old = storage.fields[Self.values] as? [Element] ?? []
old.identifiableTransform(
old.transform(
to: values,
id: id,
functions: .init { index in
if let id = old[safe: index]?.id.description,
if let id = old[safe: index]?[keyPath: label],
let toggle = storage.fields[Self.toggle + id] as? OpaquePointer {
adw_toggle_group_remove(storage.opaquePointer, toggle)
}
} insert: { _, element in
let toggle = adw_toggle_new()
adw_toggle_set_name(toggle, element.id.description)
if element.showLabel {
adw_toggle_set_label(toggle, element.id.description)
adw_toggle_set_name(toggle, element[keyPath: label])
if let showLabel, !element[keyPath: showLabel] {
adw_toggle_set_tooltip(toggle, element[keyPath: label])
} else {
adw_toggle_set_tooltip(toggle, element.id.description)
adw_toggle_set_label(toggle, element[keyPath: label])
}
if let icon = element.icon {
if let icon, let icon = element[keyPath: icon] {
adw_toggle_set_icon_name(toggle, icon.string)
}
storage.fields[Self.toggle + element.id.description] = toggle
storage.fields[Self.toggle + element[keyPath: label]] = toggle
adw_toggle_group_add(storage.opaquePointer, toggle)
}
)
storage.fields[Self.values] = values
adw_toggle_group_set_active_name(storage.opaquePointer, selection.description)
if let selection = values.first(where: { $0[keyPath: id] == selection }) {
adw_toggle_group_set_active_name(storage.opaquePointer, selection[keyPath: label])
}
}
// swiftlint:enable function_parameter_count
}

View File

@ -53,9 +53,7 @@ public struct ViewStack: AdwaitaWidget {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let stack = gtk_stack_new()
let storage = ViewStorage(stack?.opaque())
update(storage, data: data, updateProperties: true, type: type)
return storage
return .init(stack?.opaque())
}
/// Update the stored content.
@ -74,6 +72,7 @@ public struct ViewStack: AdwaitaWidget {
content.updateStorage(view, data: data, updateProperties: updateProperties, type: type)
} else {
let view = content.storage(data: data, type: type)
content.updateStorage(view, data: data, updateProperties: true, type: type)
gtk_stack_add_named(storage.opaquePointer, view.opaquePointer?.cast(), id.description)
storage.content[id.description] = [view]
}

View File

@ -39,7 +39,6 @@ public struct ViewSwitcher<Element>: AdwaitaWidget where Element: ViewSwitcherOp
let switcher = ViewStorage(adw_view_switcher_new()?.opaque())
let stack = ViewStorage(adw_view_stack_new()?.opaque())
adw_view_switcher_set_stack(switcher.opaquePointer, stack.opaquePointer)
updateSwitcher(switcher: switcher)
switcher.fields["stack"] = stack
return switcher
}

View File

@ -85,3 +85,13 @@ gtui_initialize_boolean (gboolean boolean)
g_value_set_boolean(&val, boolean);
return val;
}
static void
gtui_cssprovider_set_prefers_color_scheme (uint64_t provider, GtkInterfaceColorScheme scheme)
{
GValue val = G_VALUE_INIT;
g_value_init(&val, G_TYPE_ENUM);
g_value_set_enum(&val, scheme);
g_object_set_property(provider, "prefers-color-scheme", &val);
g_value_unset(&val);
}

View File

@ -28,7 +28,7 @@ struct FlowBoxDemo: View {
selectedItem = items[safe: index]?.id ?? items[safe: index ?? 0 - 1]?.id ?? items.first?.id ?? ""
}
}
.linked()
.modifyContent(VStack.self) { $0.linked() }
.padding()
.halign(.center)
if !items.isEmpty {

View File

@ -28,7 +28,7 @@ struct ListDemo: View {
selectedItem = items[safe: index]?.id ?? items[safe: index ?? 0 - 1]?.id ?? items.first?.id ?? ""
}
}
.linked()
.modifyContent(VStack.self) { $0.linked() }
.padding()
.halign(.center)
if !items.isEmpty {

View File

@ -15,8 +15,13 @@ struct ToggleGroupDemo: View {
@State private var selection: Subview = .view1
var view: Body {
ToggleGroup(selection: $selection, values: Subview.allCases)
.padding()
ToggleGroup(
selection: $selection,
values: Subview.allCases,
id: \.self,
label: \.rawValue
)
.padding()
VStack {
Text(selection.rawValue)
.padding()
@ -26,19 +31,11 @@ struct ToggleGroupDemo: View {
.padding()
}
enum Subview: String, ToggleGroupItem, CaseIterable, CustomStringConvertible {
enum Subview: String, CaseIterable, Equatable {
case view1 = "View 1"
case view2 = "View 2"
var id: Self { self }
var description: String { rawValue }
var icon: Icon? { nil }
var showLabel: Bool { true }
}
}

View File

@ -24,7 +24,7 @@ extension Class {
.filter { config.requiredProperties.contains($0.name) }
var initializer = "\(config.internalInitializer ? "" : "public ")init("
if config.dynamicWidget != nil {
initializer.append("_ elements: [Element], ")
initializer.append("_ elements: [Element], id: KeyPath<Element, Identifier>, ")
}
for property in requiredProperties {
initializer.append("\(property.parameter(config: config, genConfig: genConfig)), ")
@ -46,6 +46,7 @@ extension Class {
self.elements = elements
self.content = content
self.id = id
"""
)
}
@ -167,6 +168,8 @@ extension Class {
var elements: [Element]
/// The dynamic widget content.
var content: (Element) -> Body
/// The dynamic widget identifier key path.
var id: KeyPath<Element, Identifier>
"""
}
content += staticWidgetProperties(namespace: namespace, configs: configs)
@ -226,8 +229,9 @@ extension Class {
return """
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? []
old.identifiableTransform(
old.transform(
to: elements,
id: id,
functions: .init { index in
\(dynamicWidget.remove)(\(widget), \(dynamicWidget.getElement))
contentStorage.remove(at: index)

View File

@ -64,10 +64,25 @@ struct Class: ClassLike, Decodable {
dateFormatter.dateFormat = "dd.MM.yy"
let widgetName = config.name ?? config.class
let definition: String
var extensions = ""
if config.dynamicWidget == nil {
definition = "\(widgetName): AdwaitaWidget"
} else {
definition = "\(widgetName)<Element>: AdwaitaWidget where Element: Identifiable"
definition = "\(widgetName)<Element, Identifier>: AdwaitaWidget where Identifier: Equatable"
extensions += """
extension \(widgetName) where Element: Identifiable, Identifier == Element.ID {
/// Initialize `\(widgetName)`.
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements
self.content = content
self.id = \\.id
}
}
"""
}
return """
//
@ -83,10 +98,17 @@ struct Class: ClassLike, Decodable {
\(doc.docComment(configuration: genConfig))
public struct \(definition) {
#if exposeGeneratedAppearUpdateFunctions
/// Additional update functions for type extensions.
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#else
/// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
\(generateProperties(config: config, genConfig: genConfig, namespace: namespace, configs: configs))
/// Initialize `\(widgetName)`.
@ -102,7 +124,6 @@ struct Class: ClassLike, Decodable {
for function in appearFunctions {
function(storage, data)
}
update(storage, data: data, updateProperties: true, type: type)
\(generateWidgetAssignments(config: config, genConfig: genConfig, namespace: namespace, configs: configs))
return storage
}
@ -129,7 +150,7 @@ struct Class: ClassLike, Decodable {
}
\(generateModifiers(config: config, genConfig: genConfig, namespace: namespace, configs: configs))
}
\(extensions)
"""
}
// swiftlint:enable function_body_length line_length