Compare commits

...

81 Commits
0.1.0 ... main

Author SHA1 Message Date
d928b464f1 Fix broken preferences page tabs #74
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2026-02-17 16:29:12 +01:00
2072c16040 Add support for keypaths where sensible #74
All checks were successful
SwiftLint / SwiftLint (push) Successful in 7s
Deploy Docs / publish (push) Successful in 1h49m51s
2026-02-04 16:36:51 +01:00
c08a9dc3bd Fix build failing on macOS #74
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-03 20:35:35 +01:00
7e41c9b5df Add exposeGeneratedAppearUpdateFunctions trait #74
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-03 00:29:14 +01:00
6acf83dce3 Fix not building on macOS #78
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-03 00:17:07 +01:00
0fc91dc50e Use new update logic to construct dialog UIs
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-03 00:15:37 +01:00
d0d7d2b6d3 Use the new wrapModifier for simple modifiers
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-03 00:07:26 +01:00
8f6a83dfc3 Move update responsibility to constructor
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
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
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-02 21:32:10 +01:00
6b76a4c8f4 Use new wrap modifier
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-02 21:26:50 +01:00
19aa17c0ab Fix to work with latest SQLite.swift version
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-02 21:21:43 +01:00
54619c69f4 Add support for specifying the CSS scheme to load
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2026-02-02 19:42:31 +01:00
07d6a38edc Remove old style context providers in (css) #74
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2026-01-30 14:49:10 +01:00
29194341e2 Fix CSS updating on each view update #74
Some checks are pending
Deploy Docs / publish (push) Waiting to run
2026-01-30 14:33:59 +01:00
cf60b8103f Add homogeneous option to ForEach #74
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-12-30 16:32:24 +01:00
b364557f2f FlowBox: Selection disabled by default #74
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-12-30 16:24:47 +01:00
adae811e41 Add alternative padding method #74
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-12-30 16:04:25 +01:00
c29c6e22cb Add id modifier #74
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-12-30 15:14:51 +01:00
92fe4fb256 Name sqlite file after application id
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
For non-Flatpak apps
2025-11-06 13:02:58 +01:00
4de2d312ab Fix style
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-11-05 13:04:53 +01:00
a524cde9b0 Add support for AdwShortcutsDialog
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-11-05 13:01:27 +01:00
7eb2bf7bb2 Add internal initializer to autogeneration
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-11-04 13:09:17 +01:00
90e8c78163 Add support for toggle groups
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-11-03 22:28:28 +01:00
1418d1333c Generation: store views as Body
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-10-31 23:43:47 +01:00
557ec14232 Fix style
All checks were successful
Deploy Docs / publish (push) Successful in 1h52m14s
SwiftLint / SwiftLint (push) Successful in 39s
2025-10-30 22:01:48 +01:00
edb6a81812 Remove explicit passing of window to shortcuts
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-10-30 21:55:38 +01:00
04c77831b5 Remove Core library
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-10-30 21:36:13 +01:00
fd29eccd68 Improve autogenerated docs
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-10-30 20:48:37 +01:00
david-swift
f86e968028 Merge pull request 'Add Symbol view' (#73) from marquiskurt/adwaita-swift:main into main
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
Reviewed-on: #73
Reviewed-by: david-swift <david-swift@noreply.aproksha.uber.space>
2025-10-25 15:37:35 +02:00
ac2dbadedb
Add Symbol view
Some checks failed
SwiftLint / SwiftLint (pull_request) Has been cancelled
A symbol view is used to display an symbolic icon at an arbitrary
size. It is a typealias to the Image class from GTK.
2025-10-23 22:54:27 -04:00
5b9047ea85 Rename "keep" close confirmation to "cancel"
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-10-20 13:03:30 +02:00
571ed60954 Add default values to onClose (in file dialogs)
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-10-17 13:07:16 +02:00
c8ce2cc2fe Add support for folder importers
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-10-17 12:47:39 +02:00
037a697c74 Make onClose easier to understand
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-10-12 21:53:46 +02:00
e430031bbc Add onClose to windows
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-10-03 23:07:41 +02:00
1bc36e0759 Remove invisible unicode characters
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-09-18 21:40:57 +02:00
d17306f195 Add HSplitView and VSplitView
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
Co-authored-by: desbeers nick@desbeers.nl
2025-09-18 21:22:20 +02:00
david-swift
fea203fabd Merge pull request 'Add implementation for WrapMode initializer.' (#71) from mlm/adwaita-swift:AddInitializerImplementation into main
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
Reviewed-on: #71
Reviewed-by: david-swift <david-swift@noreply.aproksha.uber.space>
2025-09-07 10:04:46 +02:00
ml
6e6265aa76 Add implementation for WrapMode initializer.
Some checks failed
SwiftLint / SwiftLint (pull_request) Has been cancelled
2025-09-05 14:05:07 +02:00
0d4db96f60 Fix crashing when removing items from ForEach
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-09-03 13:35:29 +02:00
david-swift
ebb2455fe1 Merge pull request 'Add WrapMode to TextView/TextEditor' (#68) from mlm/adwaita-swift:AddWrapMode into main
Some checks failed
SwiftLint / SwiftLint (push) Failing after 21m8s
Deploy Docs / publish (push) Has been cancelled
Reviewed-on: #68
2025-08-27 13:36:21 +02:00
4eb58b154c Use more declarative approach for text editor
Some checks failed
SwiftLint / SwiftLint (pull_request) Has been cancelled
2025-08-27 13:27:36 +02:00
87b970d844 Fix code style
All checks were successful
SwiftLint / SwiftLint (pull_request) Successful in 6s
2025-08-26 13:33:43 +02:00
ml
0af3864058 Add WrapMode to TextView/TextEditor
Some checks failed
SwiftLint / SwiftLint (pull_request) Has been cancelled
2025-08-25 10:12:02 +02:00
david-swift
daa922d33b Merge pull request 'Update README.me' (#66) from Sylphrena/adwaita-swift:template-repo into main
Some checks failed
Deploy Docs / publish (push) Has been cancelled
Reviewed-on: #66
Reviewed-by: david-swift <david-swift@noreply.aproksha.uber.space>
2025-08-15 17:40:44 +02:00
4e95e4e655 Implement proper self destruction of signals
Some checks failed
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Has been cancelled
2025-08-14 23:24:30 +02:00
Sylphrena
d53ba5f4e7 Update README.me
Replace old github link to the template repo with the new one.
2025-08-12 15:46:59 +02:00
049b5b54f8 Add support for text editors
Some checks failed
SwiftLint / SwiftLint (push) Successful in 6s
Deploy Docs / publish (push) Has been cancelled
2025-08-09 10:48:04 +02:00
a04bd9025d Add support for dynamic CSS #61
Some checks failed
Deploy Docs / publish (push) Has been cancelled
SwiftLint / SwiftLint (push) Has been cancelled
2025-05-05 13:11:35 +02:00
7eeec9e0fd Add support for GtkEntry
All checks were successful
Deploy Docs / publish (push) Successful in 1h45m1s
SwiftLint / SwiftLint (push) Successful in 5s
2025-04-19 19:03:26 +02:00
a996be3f16 Add support for setting a window's minimum size
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
2025-04-19 18:37:23 +02:00
f209c8387c Add support for AdwToolbarStyle
Some checks failed
Deploy Docs / publish (push) Failing after 1s
SwiftLint / SwiftLint (push) Failing after 1s
2025-04-15 16:44:20 +02:00
513a5d36a3 Add SwiftLint to Flatpak manifest
Some checks failed
Deploy Docs / publish (push) Has been cancelled
2025-04-11 10:31:41 +02:00
befa7d52ea Add spacing to VStack/HStack initializers
Some checks failed
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Has been cancelled
2025-04-11 10:31:11 +02:00
4290dd4137 Use latest version of SFTP upload action
All checks were successful
Deploy Docs / publish (push) Successful in 1h43m10s
2025-04-09 16:52:30 +02:00
281bf7cf40 Fix code style
Some checks failed
SwiftLint / SwiftLint (push) Successful in 3s
Deploy Docs / publish (push) Has been cancelled
2025-04-09 16:51:33 +02:00
a898efcdf8 Add support for GtkDropDown 2025-04-09 16:06:57 +02:00
62b3aa93b2 Add Flatpak manifest for generation
Some checks failed
Deploy Docs / publish (push) Failing after 8m47s
SwiftLint / SwiftLint (push) Failing after 38s
2025-04-09 11:13:27 +02:00
9ae203fd7b Update GNOME runtime
Some checks are pending
Deploy Docs / publish (push) Waiting to run
2025-04-08 17:12:30 +02:00
90349fd435 Fix file dialog children updates not working
This was reported in https://forums.aparoksha.dev/d/5-at-state-and-fileexporter-dont-like-each-other
2025-03-23 11:06:32 +01:00
f89b44cee6 Only update alert dialog's extra child if visible
Some checks failed
Deploy Docs / publish (push) Failing after 25s
SwiftLint / SwiftLint (push) Successful in 5s
2025-01-24 18:11:37 +01:00
5613ce13cd Fix memory leaks
Some checks failed
SwiftLint / SwiftLint (push) Successful in 6s
Deploy Docs / publish (push) Failing after 25s
2025-01-23 13:02:11 +01:00
a0c0136298 Add storage fields to AdwaitaWindow
All checks were successful
SwiftLint / SwiftLint (push) Successful in 5s
Deploy Docs / publish (push) Successful in 22m31s
2024-12-01 13:58:19 +01:00
90beecaeb9 Add custom content to alert dialog
All checks were successful
Deploy Docs / publish (push) Successful in 22m31s
SwiftLint / SwiftLint (push) Successful in 5s
2024-11-27 09:15:35 +01:00
776b63f46a Polish demo
All checks were successful
Deploy Docs / publish (push) Successful in 20m37s
SwiftLint / SwiftLint (push) Successful in 5s
2024-11-23 11:35:50 +01:00
6a9f05bc18 Remove system-specific default icons
All checks were successful
Deploy Docs / publish (push) Successful in 20m59s
2024-11-23 10:57:59 +01:00
4b23fe16d1 Fix crash when closing dialog
All checks were successful
Deploy Docs / publish (push) Successful in 20m30s
SwiftLint / SwiftLint (push) Successful in 6s
2024-11-11 21:52:26 +01:00
188007ceb3 Add support for preferences dialogs
All checks were successful
Deploy Docs / publish (push) Successful in 20m26s
SwiftLint / SwiftLint (push) Successful in 5s
2024-11-05 13:18:37 +01:00
6229b85f46 Fix memory leaks
All checks were successful
Deploy Docs / publish (push) Successful in 21m49s
SwiftLint / SwiftLint (push) Successful in 5s
2024-10-31 23:00:50 +01:00
6bf6df0c6f Fix about dialog setting previous state
All checks were successful
Deploy Docs / publish (push) Successful in 21m20s
SwiftLint / SwiftLint (push) Successful in 5s
2024-10-30 09:20:09 +01:00
d93bc321a2 Make breakpoints check condition when initializing
All checks were successful
Deploy Docs / publish (push) Successful in 21m20s
SwiftLint / SwiftLint (push) Successful in 5s
2024-10-28 21:59:59 +01:00
e2da50703c Add padding option to natural width and height
All checks were successful
Deploy Docs / publish (push) Successful in 22m10s
SwiftLint / SwiftLint (push) Successful in 4s
2024-10-26 21:08:50 +02:00
2d12c57236 Set a scroll view's scroll bar policies
All checks were successful
Deploy Docs / publish (push) Successful in 20m49s
SwiftLint / SwiftLint (push) Successful in 4s
2024-10-26 18:44:31 +02:00
356eec00a9 Replace GtkSpinner with AdwSpinner
All checks were successful
Deploy Docs / publish (push) Successful in 21m36s
SwiftLint / SwiftLint (push) Successful in 5s
2024-10-26 17:32:45 +02:00
ced07e4293 Add support for natural sizes for breakpoints
All checks were successful
Deploy Docs / publish (push) Successful in 21m0s
SwiftLint / SwiftLint (push) Successful in 5s
2024-10-25 14:02:45 +02:00
e7c81dba1d Do not compare bindings before updating
All checks were successful
Deploy Docs / publish (push) Successful in 21m8s
SwiftLint / SwiftLint (push) Successful in 4s
2024-10-22 13:11:48 +02:00
963a02b1e1 Add support for AdwBreakpointBin
All checks were successful
Deploy Docs / publish (push) Successful in 21m42s
SwiftLint / SwiftLint (push) Successful in 3s
2024-10-21 18:30:10 +02:00
016425e329 Make view switcher dynamic
Some checks failed
Deploy Docs / publish (push) Successful in 19m25s
SwiftLint / SwiftLint (push) Failing after 1s
2024-10-19 22:50:41 +02:00
8c50494c74 Fix view switcher not updating selection
Some checks failed
Deploy Docs / publish (push) Successful in 19m56s
SwiftLint / SwiftLint (push) Failing after 1s
2024-10-19 21:54:38 +02:00
4913c0a382 Update view switcher option protocol
Some checks failed
Deploy Docs / publish (push) Successful in 20m36s
SwiftLint / SwiftLint (push) Failing after 1s
2024-10-19 20:36:19 +02:00
c893a8f0c6 Add option to pass custom array to view switcher
Some checks failed
SwiftLint / SwiftLint (push) Waiting to run
Deploy Docs / publish (push) Has been cancelled
2024-10-19 20:28:08 +02:00
169 changed files with 6275 additions and 4310 deletions

View File

@ -31,7 +31,7 @@ jobs:
echo "<script>window.location.href += \"/documentation/adwaita\"</script><p>Please enable JavaScript to view the documentation <a href='/documentation/adwaita'>here</a>.</p>" > docs/index.html; echo "<script>window.location.href += \"/documentation/adwaita\"</script><p>Please enable JavaScript to view the documentation <a href='/documentation/adwaita'>here</a>.</p>" > docs/index.html;
sed -i '' 's/,2px/,10px/g' docs/css/index.*.css sed -i '' 's/,2px/,10px/g' docs/css/index.*.css
- name: Upload - name: Upload
uses: wangyucode/sftp-upload-action@v2.0.2 uses: wangyucode/sftp-upload-action@v2.0.4
with: with:
host: 'volans.uberspace.de' host: 'volans.uberspace.de'
username: 'akforum' username: 'akforum'

View File

@ -154,5 +154,5 @@ type_contents_order:
- other_method - other_method
excluded: excluded:
- Sources/Core/View/Generated/ - Sources/Adwaita/View/Generated/
- .build/ - .build/

View File

@ -1,4 +1,4 @@
// swift-tools-version: 6.0 // swift-tools-version: 6.1
// //
// Package.swift // Package.swift
// Adwaita // Adwaita
@ -8,40 +8,44 @@
import PackageDescription 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. /// The Adwaita package.
let package = Package( let package = Package(
name: "Adwaita", 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: [ products: [
.library( .library(
name: "Adwaita", name: "Adwaita",
targets: ["Adwaita"] targets: ["Adwaita"]
), ),
.library(
name: "Core",
targets: ["Core"]
),
.library( .library(
name: "CAdw", name: "CAdw",
targets: ["CAdw"] targets: ["CAdw"]
) )
], ],
dependencies: [ traits: [.trait(name: "exposeGeneratedAppearUpdateFunctions")],
.package(url: "https://git.aparoksha.dev/aparoksha/meta", from: "0.1.0"), dependencies: dependencies,
.package(url: "https://git.aparoksha.dev/aparoksha/meta-sqlite", from: "0.1.0"),
.package(
url: "https://git.aparoksha.dev/aparoksha/levenshtein-transformations",
from: "0.1.0"
),
.package(url: "https://github.com/CoreOffice/XMLCoder", from: "0.17.1")
],
targets: [ targets: [
.systemLibrary( .systemLibrary(
name: "CAdw", name: "CAdw",
pkgConfig: "libadwaita-1" pkgConfig: "libadwaita-1"
), ),
.target( .target(
name: "Core", name: "Adwaita",
dependencies: [ dependencies: [
"CAdw", "CAdw",
.product(name: "LevenshteinTransformations", package: "levenshtein-transformations"), .product(name: "LevenshteinTransformations", package: "levenshtein-transformations"),
@ -49,10 +53,6 @@ let package = Package(
.product(name: "MetaSQLite", package: "meta-sqlite") .product(name: "MetaSQLite", package: "meta-sqlite")
] ]
), ),
.target(
name: "Adwaita",
dependencies: ["Core"]
),
.executableTarget( .executableTarget(
name: "Generation", name: "Generation",
dependencies: [ dependencies: [

View File

@ -66,7 +66,7 @@ Find more information about the project's motivation in [this blog post](https:/
It is recommended to develop apps inside of a Flatpak. It is recommended to develop apps inside of a Flatpak.
That way, you don't have to install Swift or any of the dependencies on your system, and you always have access to the latest versions. That way, you don't have to install Swift or any of the dependencies on your system, and you always have access to the latest versions.
Take a look at the [template repository](https://github.com/AparokshaUI/AdwaitaTemplate). Take a look at the [template repository](https://git.aparoksha.dev/aparoksha/adwaita-template).
This works on Linux only. This works on Linux only.
#### Directly on System #### Directly on System
@ -92,7 +92,7 @@ brew install libadwaita
## Usage ## Usage
I recommend using the [template repository](https://github.com/AparokshaUI/AdwaitaTemplate) as a starting point. I recommend using the [template repository](https://git.aparoksha.dev/aparoksha/adwaita-template) as a starting point.
Follow the [interactive tutorial](https://adwaita-swift.aparoksha.dev//tutorials/table-of-contents) or [read the docs](https://adwaita-swift.aparoksha.dev/) in order to get to know _Adwaita for Swift_. Follow the [interactive tutorial](https://adwaita-swift.aparoksha.dev//tutorials/table-of-contents) or [read the docs](https://adwaita-swift.aparoksha.dev/) in order to get to know _Adwaita for Swift_.

View File

@ -1,17 +0,0 @@
//
// ActionRow+.swift
// Adwaita
//
// Created by david-swift on 16.10.24.
//
extension ActionRow {
/// Deemphasize the row title and emphasize the subtitle.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func property(_ active: Bool = true) -> AnyView {
style("property", active: active)
}
}

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

@ -33,7 +33,7 @@ public class AdwaitaApp: AppStorage {
/// - Parameter id: The identifier. /// - Parameter id: The identifier.
public required init(id: String) { public required init(id: String) {
pointer = adw_application_new(id, G_APPLICATION_DEFAULT_FLAGS)?.cast() pointer = adw_application_new(id, G_APPLICATION_DEFAULT_FLAGS)?.cast()
DatabaseInformation.setPath(Self.userDataDir().appendingPathComponent("data.sqlite").path) DatabaseInformation.setPath(Self.userDataDir().appendingPathComponent("\(id).sqlite").path)
} }
/// Copy a string to the clipboard. /// Copy a string to the clipboard.
@ -100,7 +100,9 @@ public class AdwaitaApp: AppStorage {
g_action_map_add_action(.init(pointer), action) g_action_map_add_action(.init(pointer), action)
signals[id] = data signals[id] = data
} }
gtk_application_set_accels_for_action(pointer, (window == nil ? "app." : "win.") + id, [shortcut].cArray) let array = [shortcut].cArray
gtk_application_set_accels_for_action(pointer, (window == nil ? "app." : "win.") + id, array)
array?.deallocate()
} }
/// Remove a keyboard shortcut from the application. /// Remove a keyboard shortcut from the application.

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

@ -29,7 +29,7 @@ public enum Icon {
} }
/// A preinstalled icon. /// A preinstalled icon.
public enum DefaultIcon: String { public enum DefaultIcon: String, CaseIterable {
// swiftlint:disable missing_docs identifier_name // swiftlint:disable missing_docs identifier_name
case acAdapter case acAdapter
case accessoriesCalculator case accessoriesCalculator
@ -40,7 +40,6 @@ public enum Icon {
case addressBookNew case addressBookNew
case airplaneMode case airplaneMode
case alarm case alarm
case appRemove
case appletsScreenshooter case appletsScreenshooter
case applicationCertificate case applicationCertificate
case applicationExitRtl case applicationExitRtl
@ -288,7 +287,6 @@ public enum Icon {
case functionLinear case functionLinear
case gestureSwipeLeft case gestureSwipeLeft
case gestureSwipeRight case gestureSwipeRight
case gnomeDisksStateStandby
case gnomePowerManager case gnomePowerManager
case goBottom case goBottom
case goDown case goDown
@ -301,12 +299,6 @@ public enum Icon {
case goPrevious case goPrevious
case goTop case goTop
case goUp case goUp
case goaAccountExchange
case goaAccountGoogle
case goaAccountLastfm
case goaAccountMsn
case goaAccountOwncloud
case goaAccount
case goaPanel case goaPanel
case gtk3Demo case gtk3Demo
case gtk3WidgetFactory case gtk3WidgetFactory
@ -317,7 +309,6 @@ public enum Icon {
case imageLoading case imageLoading
case imageMissing case imageMissing
case imageXGeneric case imageXGeneric
case info
case inodeDirectory case inodeDirectory
case inputDialpad case inputDialpad
case inputGaming case inputGaming
@ -343,13 +334,6 @@ public enum Icon {
case langTypedef case langTypedef
case langUnion case langUnion
case langVariable case langVariable
case libreofficeBase
case libreofficeCalc
case libreofficeDraw
case libreofficeImpress
case libreofficeMain
case libreofficeMath
case libreofficeWriter
case listAdd case listAdd
case listDragHandle case listDragHandle
case listRemoveAll case listRemoveAll
@ -469,9 +453,6 @@ public enum Icon {
case networkWorkgroup case networkWorkgroup
case nightLightDisabled case nightLightDisabled
case nightLight case nightLight
case nmDeviceWiredSecure
case nmDeviceWired
case nmDeviceWwan
case nonStarred case nonStarred
case notificationsDisabled case notificationsDisabled
case objectFlipHorizontal case objectFlipHorizontal
@ -480,70 +461,6 @@ public enum Icon {
case objectRotateRight case objectRotateRight
case objectSelect case objectSelect
case openMenu case openMenu
case orca
case fedoraprojectAnacondaInstaller = "org.fedoraproject.AnacondaInstaller"
case freedesktopMalcontentControl = "org.freedesktop.MalcontentControl"
case gnomeAdwaita1Demo = "org.gnome.Adwaita1.Demo"
case gnomeBoxes = "org.gnome.Boxes"
case gnomeBuilder = "org.gnome.Builder"
case gnomeCalculator = "org.gnome.Calculator"
case gnomeCharacters = "org.gnome.Characters"
case gnomeCheese = "org.gnome.Cheese"
case gnomeConsole = "org.gnome.Console"
case gnomeDiskUtility = "org.gnome.DiskUtility"
case gnomeEpiphany = "org.gnome.Epiphany"
case gnomeEvince = "org.gnome.Evince"
case gnomeLogs = "org.gnome.Logs"
case gnomeMaps = "org.gnome.Maps"
case gnomeNautilus = "org.gnome.Nautilus"
case gnomePhotos = "org.gnome.Photos"
case gnomeRhythmbox3 = "org.gnome.Rhythmbox3"
case gnomeSettingsAbout = "org.gnome.Settings-about"
case gnomeSettingsAccessibility = "org.gnome.Settings-accessibility"
case gnomeSettingsAppearance = "org.gnome.Settings-appearance"
case gnomeSettingsApplications = "org.gnome.Settings-applications"
case gnomeSettingsBluetooth = "org.gnome.Settings-bluetooth"
case gnomeSettingsCamera = "org.gnome.Settings-camera"
case gnomeSettingsColor = "org.gnome.Settings-color"
case gnomeSettingsDefaultApps = "org.gnome.Settings-default-apps"
case gnomeSettingsDiagnostics = "org.gnome.Settings-diagnostics"
case gnomeSettingsDisplay = "org.gnome.Settings-display"
case gnomeSettingsFileHistory = "org.gnome.Settings-file-history"
case gnomeSettingsKeyboard = "org.gnome.Settings-keyboard"
case gnomeSettingsLocation = "org.gnome.Settings-location"
case gnomeSettingsMicrophone = "org.gnome.Settings-microphone"
case gnomeSettingsMobileNetwork = "org.gnome.Settings-mobile-network"
case gnomeSettingsMouse = "org.gnome.Settings-mouse"
case gnomeSettingsMultitasking = "org.gnome.Settings-multitasking"
case gnomeSettingsNetwork = "org.gnome.Settings-network"
case gnomeSettingsNotifications = "org.gnome.Settings-notifications"
case gnomeSettingsOnlineAccounts = "org.gnome.Settings-online-accounts"
case gnomeSettingsPower = "org.gnome.Settings-power"
case gnomeSettingsPinters = "org.gnome.Setting-printers"
case gnomeSettingsRegion = "org.gnome.Settings-region"
case gnomeSettingsRemovableMedia = "org.gnome.Settings-removable-media"
case gnomeSettingsSearch = "org.gnome.Settings-search"
case gnomeSettingsSharing = "org.gnome.Settings-sharing"
case gnomeSettingsSound = "org.gnome.Settings-sound"
case gnomeSettings = "org.gnome.Settings"
case gnomeSettingsSystemLockScreen = "org.gnome.Settings-system-lock-screen"
case gnomeSettingsThunderbolt = "org.gnome.Settings-thunderbolt"
case gnomeSettingsTime = "org.gnome.Settings-time"
case gnomeSettingsUsers = "org.gnome.Settings-users"
case gnomeSettingsWacom = "org.gnome.Settings-wacom"
case gnomeShellExtensions = "org.gnome.Shell.Extensions"
case gnomeSoftware = "org.gnome.Software"
case gnomeSystemMonitor = "org.gnome.SystemMonitor"
case gnomeTextEditor = "org.gnome.TextEditor"
case gnomeTotem = "org.gnome.Totem"
case gnomeWeather = "org.gnome.Weather"
case gnomeYelp = "org.gnome.Yelp"
case gnomeBaobab = "org.gnome.baobab"
case gnomeClocks = "org.gnome.clocks"
case gnomeDesignIconLibrary = "org.gnome.design.IconLibrary"
case gnomeEog = "org.gnome.eog"
case gnomeFontViewer = "org.gnome.font-viewer"
case gnomeTweaks = "org.gnome.tweaks"
case gtkDemo4 = "org.gtk.Demo4" case gtkDemo4 = "org.gtk.Demo4"
case gtkIconBrowser4 = "org.gtk.IconBrowser4" case gtkIconBrowser4 = "org.gtk.IconBrowser4"
case gtkPrintEditor4 = "org.gtk.PrintEditor4" case gtkPrintEditor4 = "org.gtk.PrintEditor4"
@ -554,18 +471,12 @@ public enum Icon {
case orientationPortraitInverse case orientationPortraitInverse
case orientationPortraitLeft case orientationPortraitLeft
case orientationPortraitRight case orientationPortraitRight
case orientationProtrait case orientationPortrait
case packageXGeneric case packageXGeneric
case panDown case panDown
case panEnd case panEnd
case panStart case panStart
case panUp case panUp
case panelBottom
case panelCenter
case panelLeft
case panelModified
case panelRight
case panelTop
case pda case pda
case phoneAppleIphone case phoneAppleIphone
case phoneOld case phoneOld
@ -629,7 +540,6 @@ public enum Icon {
case sidebarShow case sidebarShow
case softwareUpdateAvailable case softwareUpdateAvailable
case softwareUpdateUrgent case softwareUpdateUrgent
case speedometer
case starNew case starNew
case starred case starred
case startHere case startHere
@ -652,13 +562,11 @@ public enum Icon {
case tablet case tablet
case taskDue case taskDue
case taskPastDue case taskPastDue
case temperature
case textEditor case textEditor
case textXGeneric case textXGeneric
case thunderboltAcquiring case thunderboltAcquiring
case thunderbolt case thunderbolt
case toolsCheckSpelling case toolsCheckSpelling
case totemTv
case touchDisabled case touchDisabled
case touchpadDisabled case touchpadDisabled
case tv case tv
@ -681,7 +589,7 @@ public enum Icon {
case valueDecrease case valueDecrease
case valueIncrease case valueIncrease
case videoDisplay case videoDisplay
case videoJoineDisplays case videoJoinedDisplays
case videoSingleDisplay case videoSingleDisplay
case videoXGeneric case videoXGeneric
case viewAppGrid case viewAppGrid
@ -716,7 +624,6 @@ public enum Icon {
case weatherFewCloudsNight case weatherFewCloudsNight
case weatherFewClouds case weatherFewClouds
case weatherFog case weatherFog
case weatherHourly
case weatherOvercast case weatherOvercast
case weatherSevereAlert case weatherSevereAlert
case weatherShowersScattered case weatherShowersScattered

View File

@ -0,0 +1,27 @@
//
// ContentFit.swift
// Adwaita
//
// Created by david-swift on 19.07.24.
//
import CAdw
/// The visibility of a scroll bar.
public enum ScrollbarVisibility: UInt32 {
/// The scrollbar is always visible. The view size is independent of the content.
case alwaysVisible
/// The scrollbar will appear and disappear as necessary.
case automatic
/// The scrollbar should never appear. In this mode the content determines the size.
case never
/// Dont show a scrollbar, but dont force the size to follow the content.
case external
/// The ScrollbarVisibility value as a GtkPolicyType value.
var gtkValue: GtkPolicyType {
.init(rawValue)
}
}

View File

@ -0,0 +1,25 @@
//
// ToolbarStyle.swift
// Adwaita
//
// Created by david-swift on 15.04.25.
//
import CAdw
/// The top and bottom bar styles.
public enum ToolbarStyle: UInt32 {
/// No background, shadow only for scrolled content.
case flat
/// Opaque background with a persistent shadow.
case raised
/// Opaque background with a persistent border.
case raisedBorder
/// The ToolbarStyle value as an AdwToolbarStyle value.
var gtkValue: AdwToolbarStyle {
.init(rawValue)
}
}

View File

@ -0,0 +1,54 @@
//
// WrapMode.swift
// Adwaita
//
// Created by mlm on 24.08.25.
//
import CAdw
/// Wrap modes for `TextView`/`TextEditor`
public enum WrapMode: GtkWrapMode, RawRepresentable {
// swiftlint:disable discouraged_none_name
/// GTK_WRAP_NONE
case none
// swiftlint:enable discouraged_none_name
/// GTK_WRAP_CHAR
case char
/// GTK_WRAP_WORD
case word
/// GTK_WRAP_WORD_CHAR
case wordChar
/// Get the GtkWrapMode.
public var rawValue: GtkWrapMode {
switch self {
case .none:
GTK_WRAP_NONE
case .char:
GTK_WRAP_CHAR
case .word:
GTK_WRAP_WORD
case .wordChar:
GTK_WRAP_WORD_CHAR
}
}
/// Initialize from the GtkWrapMode.
/// - Parameter rawValue: The GtkWrapMode.
public init?(rawValue: GtkWrapMode) {
switch rawValue {
case GTK_WRAP_NONE:
self = .none
case GTK_WRAP_CHAR:
self = .char
case GTK_WRAP_WORD:
self = .word
case GTK_WRAP_WORD_CHAR:
self = .wordChar
default:
return nil
}
}
}

View File

@ -5,6 +5,8 @@
// Created by david-swift on 15.01.24. // Created by david-swift on 15.01.24.
// //
import CAdw
extension Bool { extension Bool {
/// Get the gboolean for C. /// Get the gboolean for C.

View File

@ -0,0 +1,19 @@
//
// GtkWrapMode.swift
// Adwaita
//
// Created by mlm on 24.08.25.
//
import CAdw
/// Add ExpressibleByIntegerLiteral conformance to make GtkWrapMode usable as
/// a RawValue in an enum.
extension GtkWrapMode: @retroactive ExpressibleByIntegerLiteral {
/// Initialize from an integer literal.
public init(integerLiteral value: Int) {
self.init(UInt32(value))
}
}

View File

@ -78,6 +78,20 @@ public struct Idle {
/// An idle handler. /// An idle handler.
class IdleHandler { class IdleHandler {
/// Execute the function.
/// - Parameter pointer: The closure wrapper's pointer.
static func run(pointer: gpointer?) -> Int32 {
if let pointer {
let container = Unmanaged<ClosureContainer>.fromOpaque(pointer).takeUnretainedValue()
let result = container.closure()
if !result {
Unmanaged<ClosureContainer>.fromOpaque(pointer).release()
}
return result.cBool
}
return G_SOURCE_REMOVE
}
/// Add a function to be called whenever there are no higher priority events pending to the default main loop. /// Add a function to be called whenever there are no higher priority events pending to the default main loop.
/// - Parameter closure: The function. /// - Parameter closure: The function.
func add(_ closure: @escaping () -> Bool, priority: Int32, delay: Int64? = nil) { func add(_ closure: @escaping () -> Bool, priority: Int32, delay: Int64? = nil) {
@ -93,20 +107,6 @@ public struct Idle {
} }
} }
/// Execute the function.
/// - Parameter pointer: The closure wrapper's pointer.
static func run(pointer: gpointer?) -> Int32 {
if let pointer {
let container = Unmanaged<ClosureContainer>.fromOpaque(pointer).takeUnretainedValue()
let result = container.closure()
if !result {
Unmanaged<ClosureContainer>.fromOpaque(pointer).release()
}
return result.cBool
}
return G_SOURCE_REMOVE
}
} }
/// A reference type holding a closure. /// A reference type holding a closure.

View File

@ -11,13 +11,15 @@ import CAdw
public class SignalData { public class SignalData {
/// The closure. /// The closure.
public var closure: ([Any?]) -> Void public var closure: ([Any?]) -> Any?
/// Destroy the class.
public var selfDestruction: (() -> Void)?
/// The closure as a C handler. /// The closure as a C handler.
var handler: @convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Void { var handler: @convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Void {
{ _, data in { _, data in
let data = unsafeBitCast(data, to: SignalData.self) let data = unsafeBitCast(data, to: SignalData.self)
data.closure([]) _ = data.closure([])
} }
} }
@ -29,7 +31,7 @@ public class SignalData {
) -> Void { ) -> Void {
{ _, arg1, data in { _, arg1, data in
let data = unsafeBitCast(data, to: SignalData.self) let data = unsafeBitCast(data, to: SignalData.self)
data.closure([arg1]) _ = data.closure([arg1])
} }
} }
@ -42,7 +44,7 @@ public class SignalData {
) -> Void { ) -> Void {
{ _, arg1, arg2, data in { _, arg1, arg2, data in
let data = unsafeBitCast(data, to: SignalData.self) let data = unsafeBitCast(data, to: SignalData.self)
data.closure([arg1, arg2]) _ = data.closure([arg1, arg2])
} }
} }
@ -56,20 +58,49 @@ public class SignalData {
) -> Void { ) -> Void {
{ _, arg1, arg2, arg3, data in { _, arg1, arg2, arg3, data in
let data = unsafeBitCast(data, to: SignalData.self) let data = unsafeBitCast(data, to: SignalData.self)
data.closure([arg1, arg2, arg3]) _ = data.closure([arg1, arg2, arg3])
}
}
/// The closure as a C handler with a return value.
var boolHandler: @convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Bool {
{ _, data in
let data = unsafeBitCast(data, to: SignalData.self)
return data.closure([]) as? Bool ?? false
} }
} }
/// Initialize the signal data. /// Initialize the signal data.
/// - Parameter closure: The signal's closure. /// - Parameters:
public convenience init(closure: @escaping () -> Void) { /// - closure: The signal's closure.
self.init { _ in closure() } /// - destroy: The self destruction.
public convenience init(closure: @escaping () -> Any?, destroy: (() -> Void)? = nil) {
self.init(closure: { _ in closure() }, destroy: destroy)
} }
/// Initialize the signal data. /// Initialize the signal data.
/// - Parameter closure: The signal's closure. /// - Parameters:
public init(closure: @escaping ([Any]) -> Void) { /// - closure: The signal's closure.
/// - destroy: The self destruction.
public convenience init(closure: @escaping () -> Void, destroy: (() -> Void)? = nil) {
self.init(closure: { _ in closure(); return nil }, destroy: destroy)
}
/// Initialize the signal data.
/// - Parameters:
/// - closure: The signal's closure.
/// - destroy: The self destruction.
public init(closure: @escaping ([Any]) -> Any?, destroy: (() -> Void)? = nil) {
self.closure = closure self.closure = closure
self.selfDestruction = destroy
}
/// The return type.
public enum ReturnType {
/// Returns a boolean.
case bool
} }
/// Connect the signal data to a signal. /// Connect the signal data to a signal.
@ -77,9 +108,20 @@ public class SignalData {
/// - pointer: The pointer to the object which holds the signal. /// - pointer: The pointer to the object which holds the signal.
/// - signal: The signal's name. /// - signal: The signal's name.
/// - argCount: The number of arguments. /// - argCount: The number of arguments.
public func connect(pointer: UnsafeMutableRawPointer?, signal: String, argCount: Int = 0) { /// - return: The return type.
public func connect(
pointer: UnsafeMutableRawPointer?,
signal: String,
argCount: Int = 0,
return: ReturnType? = nil
) {
let callback: GCallback let callback: GCallback
if argCount >= 3 { if let `return` {
switch `return` {
case .bool:
callback = unsafeBitCast(boolHandler, to: GCallback.self)
}
} else if argCount >= 3 {
callback = unsafeBitCast(fiveParamsHandler, to: GCallback.self) callback = unsafeBitCast(fiveParamsHandler, to: GCallback.self)
} else if argCount == 2 { } else if argCount == 2 {
callback = unsafeBitCast(fourParamsHandler, to: GCallback.self) callback = unsafeBitCast(fourParamsHandler, to: GCallback.self)
@ -88,12 +130,19 @@ public class SignalData {
} else { } else {
callback = unsafeBitCast(handler, to: GCallback.self) callback = unsafeBitCast(handler, to: GCallback.self)
} }
let destroy: GClosureNotify = { data, _ in
guard let data else {
return
}
let signalData: SignalData = Unmanaged.fromOpaque(data).takeUnretainedValue()
signalData.selfDestruction?()
}
g_signal_connect_data( g_signal_connect_data(
pointer, pointer,
signal, signal,
callback, callback,
Unmanaged.passUnretained(self).toOpaque().cast(), Unmanaged.passUnretained(self).toOpaque().cast(),
nil, destroy,
G_CONNECT_AFTER G_CONNECT_AFTER
) )
} }

View File

@ -48,7 +48,30 @@ extension Storage {
pointer: OpaquePointer? = nil, pointer: OpaquePointer? = nil,
handler: @escaping () -> Void handler: @escaping () -> Void
) { ) {
connectSignal(name: name, id: id, argCount: argCount, pointer: pointer) { _ in connectSignal(name: name, id: id, argCount: argCount, pointer: pointer) {
handler()
return nil
}
}
/// Connect a handler to a signal.
/// - Parameters:
/// - name: The signal's name.
/// - id: The handlers id to separate form others connecting to the signal.
/// - connectFlags: The GConnectFlags.
/// - argCount: The number of additional arguments (without the first and the last one).
/// - return: The return type.
/// - pointer: A custom pointer instead of the stored one.
/// - handler: The signal's handler.
public func connectSignal(
name: String,
id: String = "",
argCount: Int = 0,
return: SignalData.ReturnType? = nil,
pointer: OpaquePointer? = nil,
handler: @escaping () -> Any?
) {
connectSignal(name: name, id: id, argCount: argCount, return: `return`, pointer: pointer) { _ in
handler() handler()
} }
} }
@ -66,13 +89,42 @@ extension Storage {
argCount: Int = 0, argCount: Int = 0,
pointer: OpaquePointer? = nil, pointer: OpaquePointer? = nil,
handler: @escaping ([Any]) -> Void handler: @escaping ([Any]) -> Void
) {
connectSignal(name: name, id: id, argCount: argCount, pointer: pointer) { args in
handler(args)
return nil
}
}
/// Connect a handler to a signal.
/// - Parameters:
/// - name: The signal's name.
/// - id: The handlers id to separate form others connecting to the signal.
/// - argCount: The number of additional arguments (without the first and the last one).
/// - return: The return type.
/// - pointer: A custom pointer instead of the stored one.
/// - handler: The signal's handler.
public func connectSignal(
name: String,
id: String = "",
argCount: Int = 0,
return: SignalData.ReturnType? = nil,
pointer: OpaquePointer? = nil,
handler: @escaping ([Any]) -> Any?
) { ) {
if let data = fields[name + id] as? SignalData { if let data = fields[name + id] as? SignalData {
data.closure = handler data.closure = handler
} else { } else {
let data = SignalData(closure: handler) let data = SignalData(closure: handler) { [self] in fields[name + id] = nil }
fields[name + id] = data fields[name + id] = data
data.connect(pointer: (pointer ?? opaquePointer)?.cast(), signal: name, argCount: argCount) data.connect(
pointer: (
pointer ?? opaquePointer ?? ((self as? SceneStorage)?.pointer as? AdwaitaWindow)?.pointer?.opaque()
)?.cast(),
signal: name,
argCount: argCount,
return: `return`
)
} }
} }

View File

@ -1,17 +0,0 @@
//
// StatusPage+.swift
// Adwaita
//
// Created by david-swift on 16.10.24.
//
extension StatusPage {
/// Make the status page more compact.
/// - Parameter active: Whether the style is applied.
/// - Returns: A view.
public func compact(_ active: Bool = true) -> AnyView {
style("compact", active: active)
}
}

View File

@ -108,6 +108,13 @@ extension AnyView {
style("circular", active: active) 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. /// Make a button or similar widget appear as a pill.
/// - Parameter active: Whether the style is currently applied. /// - Parameter active: Whether the style is currently applied.
/// - Returns: A view. /// - Returns: A view.
@ -271,13 +278,6 @@ extension AnyView {
style("frame", active: active) 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. /// Bind to the view's focus.
/// - Parameter focus: Whether the view is focused. /// - Parameter focus: Whether the view is focused.
/// - Returns: A view. /// - Returns: A view.
@ -336,22 +336,58 @@ extension AnyView {
} }
/// Add CSS classes to the app as soon as the view appears. /// 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. /// - Returns: A view.
public func css(_ getString: @escaping () -> String) -> AnyView { public func css(scheme: ColorScheme? = nil, getString: @escaping () -> String) -> AnyView {
inspectOnAppear { _ in wrap { storage, updateProperties in
let provider = gtk_css_provider_new() let cssID = "internal-css"
gtk_css_provider_load_from_string( let providerID = "internal-css-provider"
provider, let previous = storage.fields[cssID] as? String
getString() let string = getString()
) if updateProperties, string != previous {
let display = gdk_display_get_default() let provider = gtk_css_provider_new()
gtk_style_context_add_provider_for_display( if let scheme {
display, gtui_cssprovider_set_prefers_color_scheme(.init(Int(bitPattern: provider)), scheme.gtkValue)
provider?.opaque(), }
.init(GTK_STYLE_PROVIDER_PRIORITY_APPLICATION) gtk_css_provider_load_from_string(
) provider,
string
)
let display = gdk_display_get_default()
gtk_style_context_add_provider_for_display(
display,
provider?.opaque(),
.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,7 +5,7 @@
// Created by david-swift on 16.10.24. // Created by david-swift on 16.10.24.
// //
@_exported import Core import CAdw
import Foundation import Foundation
extension AnyView { extension AnyView {
@ -45,6 +45,8 @@ extension AnyView {
/// - visible: Whether the dialog is presented. /// - visible: Whether the dialog is presented.
/// - heading: The heading. /// - heading: The heading.
/// - body: The body text. /// - body: The body text.
/// - id: An optional identifier.
/// - extraChild: A view with custom content.
public func alertDialog( public func alertDialog(
visible: Binding<Bool>, visible: Binding<Bool>,
heading: String, heading: String,
@ -60,6 +62,30 @@ extension AnyView {
) )
} }
/// Add an alert dialog to the parent window.
/// - Parameters:
/// - visible: Whether the dialog is presented.
/// - heading: The heading.
/// - body: The body text.
/// - id: An optional identifier.
/// - extraChild: A view with custom content.
public func alertDialog(
visible: Binding<Bool>,
heading: String,
body: String = "",
id: String? = nil,
@ViewBuilder extraChild: () -> Body
) -> AlertDialog {
.init(
visible: visible,
child: self,
id: id ?? "no-id",
heading: heading,
body: body,
extraChild: extraChild()
)
}
/// Add a dialog to the parent window. /// Add a dialog to the parent window.
/// - Parameters: /// - Parameters:
/// - visible: Whether the dialog is presented. /// - visible: Whether the dialog is presented.
@ -86,12 +112,43 @@ extension AnyView {
) )
} }
/// Add a preferences dialog to the parent window.
/// - Parameters:
/// - visible: Whether the dialog is presented.
/// - id: The dialog's id.
/// - Returns: The view.
public func preferencesDialog(
visible: Binding<Bool>,
id: String? = nil
) -> PreferencesDialog {
.init(
visible: visible,
child: self,
id: id ?? ""
)
}
/// Add a shortcuts dialog to the parent window.
/// - Parameters:
/// - visible: Whether the dialog is presented.
/// - id: The dialog's id.
/// - Returns: The view.
public func shortcutsDialog(
visible: Binding<Bool>,
id: String? = nil
) -> ShortcutsDialog {
.init(
visible: visible,
child: self,
id: id ?? ""
)
}
/// Create an importer file dialog. /// Create an importer file dialog.
/// - Parameters: /// - Parameters:
/// - open: The signal to open the dialog. /// - open: The signal to open the dialog.
/// - initialFolder: The URL to the folder open when being opened. /// - initialFolder: The URL to the folder open when being opened.
/// - extensions: The accepted file extensions. /// - extensions: The accepted file extensions.
/// - folders: Whether folders are accepted.
/// - onOpen: Run this when a file for importing has been chosen. /// - onOpen: Run this when a file for importing has been chosen.
/// - onClose: Run this when the user cancelled the action. /// - onClose: Run this when the user cancelled the action.
public func fileImporter( public func fileImporter(
@ -99,17 +156,37 @@ extension AnyView {
initialFolder: URL? = nil, initialFolder: URL? = nil,
extensions: [String]? = nil, extensions: [String]? = nil,
onOpen: @escaping (URL) -> Void, onOpen: @escaping (URL) -> Void,
onClose: @escaping () -> Void onClose: @escaping () -> Void = { }
) -> AnyView { ) -> AnyView {
FileDialog( FileDialog(
importer: true, type: .importer(folder: false, extensions: extensions),
open: open, open: open,
child: self, child: self,
result: onOpen, result: onOpen,
cancel: onClose, cancel: onClose,
initialFolder: initialFolder, initialFolder: initialFolder
initialName: nil, )
extensions: extensions }
/// Create an importer file dialog for folders.
/// - Parameters:
/// - open: The signal to open the dialog.
/// - initialFolder: The URL to the folder open when being opened.
/// - onOpen: Run this when a file for importing has been chosen.
/// - onClose: Run this when the user cancelled the action.
public func folderImporter(
open: Signal,
initialFolder: URL? = nil,
onOpen: @escaping (URL) -> Void,
onClose: @escaping () -> Void = { }
) -> AnyView {
FileDialog(
type: .importer(folder: true, extensions: nil),
open: open,
child: self,
result: onOpen,
cancel: onClose,
initialFolder: initialFolder
) )
} }
@ -125,16 +202,15 @@ extension AnyView {
initialFolder: URL? = nil, initialFolder: URL? = nil,
initialName: String? = nil, initialName: String? = nil,
onSave: @escaping (URL) -> Void, onSave: @escaping (URL) -> Void,
onClose: @escaping () -> Void onClose: @escaping () -> Void = { }
) -> AnyView { ) -> AnyView {
FileDialog( FileDialog(
importer: false, type: .exporter(initialName: initialName),
open: open, open: open,
child: self, child: self,
result: onSave, result: onSave,
cancel: onClose, cancel: onClose,
initialFolder: initialFolder, initialFolder: initialFolder
initialName: initialName
) )
} }
@ -168,82 +244,6 @@ extension AnyView {
.maximumSize(maxHeight ?? -1) .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)
}
/// 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. /// Present a toast when the signal gets activated.
/// - Parameters: /// - Parameters:
/// - title: The title of the toast. /// - title: The title of the toast.
@ -267,4 +267,43 @@ extension AnyView {
.action(button: button, handler: handler) .action(button: button, handler: handler)
} }
/// Add a breakpoint.
/// - Parameters:
/// - maxWidth: The maximum width.
/// - matches: Whether the content view matches the breakpoint.
public func breakpoint(maxWidth: Int, matches: Binding<Bool>) -> AnyView {
BreakpointBin(condition: .maxWidth(maxWidth), matches: matches) { self }
}
/// Add a breakpoint.
/// - Parameters:
/// - minWidth: The minimum width.
/// - matches: Whether the content view matches the breakpoint.
public func breakpoint(minWidth: Int, matches: Binding<Bool>) -> AnyView {
BreakpointBin(condition: .minWidth(minWidth), matches: matches) { self }
}
/// Add a breakpoint.
/// - Parameters:
/// - maxHeight: The maximum height.
/// - matches: Whether the content view matches the breakpoint.
public func breakpoint(maxHeight: Int, matches: Binding<Bool>) -> AnyView {
BreakpointBin(condition: .maxHeight(maxHeight), matches: matches) { self }
}
/// Add a breakpoint.
/// - Parameters:
/// - minHeight: The minimum height.
/// - matches: Whether the content view matches the breakpoint.
public func breakpoint(minHeight: Int, matches: Binding<Bool>) -> AnyView {
BreakpointBin(condition: .minHeight(minHeight), matches: matches) { self }
}
/// Build the UI from scratch once the identifier changes.
/// - Parameter id: The identifier.
public func id(_ id: CustomStringConvertible) -> AnyView {
ViewStack(id: id) { _ in self }
.limitChildren()
}
} }

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

@ -0,0 +1,154 @@
//
// BreakpointBin.swift
// Adwaita
//
// Created by david-swift on 21.10.24.
//
import CAdw
import Meta
/// Bind a dimension's to observe whether the child view matches a condition.
public struct BreakpointBin: AdwaitaWidget {
/// The child view.
@ViewProperty(
set: { bin, view in
var width: Int32 = 0
var height: Int32 = 0
gtk_widget_measure(view.cast(), GTK_ORIENTATION_VERTICAL, -1, &height, nil, nil, nil)
gtk_widget_measure(view.cast(), GTK_ORIENTATION_HORIZONTAL, -1, &width, nil, nil, nil)
gtk_widget_set_size_request(bin.cast(), width, height)
adw_breakpoint_bin_set_child(bin.cast(), view.cast())
},
pointer: OpaquePointer.self,
subview: OpaquePointer.self,
context: AdwaitaMainView.self
)
var content
/// The condition.
@Property(
set: { bin, condition, storage in
var condition = condition
switch condition {
case let .naturalWidth(padding):
let child = adw_breakpoint_bin_get_child(bin.cast())
var size: Int32 = 0
gtk_widget_measure(child, GTK_ORIENTATION_HORIZONTAL, -1, nil, &size, nil, nil)
condition = .minWidth(.init(size) + padding)
case let .naturalHeight(padding):
let child = adw_breakpoint_bin_get_child(bin.cast())
var size: Int32 = 0
gtk_widget_measure(child, GTK_ORIENTATION_VERTICAL, -1, nil, &size, nil, nil)
condition = .minHeight(.init(size) + padding)
default:
break
}
storage.fields["condition"] = condition
let string = adw_breakpoint_condition_parse(condition.condition)
if let breakpoint = storage.fields["breakpoint"] as? OpaquePointer {
g_object_unref(adw_breakpoint_get_condition(breakpoint)?.cast())
adw_breakpoint_set_condition(breakpoint, string)
} else {
let breakpoint = adw_breakpoint_new(string)
adw_breakpoint_bin_add_breakpoint(bin.cast(), breakpoint)
storage.fields["breakpoint"] = breakpoint
if let matches = storage.fields["binding"] as? Binding<Bool> {
Idle {
condition.initialize(child: adw_breakpoint_bin_get_child(bin.cast()), matches: matches)
}
}
}
},
pointer: OpaquePointer.self
)
var condition: BreakpointCondition = .maxWidth(0)
/// Whether the child view does not match the condition.
@BindingProperty(
observe: { bin, matches, storage in
storage.notify(name: "current-breakpoint") {
matches.wrappedValue = adw_breakpoint_bin_get_current_breakpoint(bin.cast()) != nil
}
storage.fields["binding"] = matches
},
set: { _, _, _ in },
pointer: OpaquePointer.self
)
var matches: Binding<Bool> = .constant(false)
/// Initialize a breakpoint bin.
/// - Parameters:
/// - condition: The condition.
/// - matches: Whether the content matches the condition.
/// - content: The content.
public init(
condition: BreakpointCondition,
matches: Binding<Bool>,
@ViewBuilder content: () -> Body
) {
self.condition = condition
self.matches = matches
self.content = content()
}
/// Initialize the widget.
public func initializeWidget() -> Any {
adw_breakpoint_bin_new()?.opaque() as Any
}
}
/// A breakpoint condition.
public enum BreakpointCondition: Equatable {
/// Define a maximum width.
case maxWidth(_ width: Int)
/// Define a maximum height.
case maxHeight(_ height: Int)
/// Define a minimum width.
case minWidth(_ width: Int)
/// Define a minimum height.
case minHeight(_ height: Int)
/// The minimum width is the content's natural width.
case naturalWidth(padding: Int = 0)
/// The minimum height is the content's natural height.
case naturalHeight(padding: Int = 0)
/// The condition to parse.
var condition: String? {
switch self {
case let .maxWidth(width):
"max-width: \(width)sp"
case let .maxHeight(height):
"max-height: \(height)sp"
case let .minWidth(width):
"min-width: \(width)sp"
case let .minHeight(height):
"min-height: \(height)sp"
default:
nil
}
}
/// Initialize the breakpoint when initializing the view.
/// - Parameters:
/// - child: The widget.
/// - matches: The matches binding.
func initialize(child: UnsafeMutablePointer<GtkWidget>?, matches: Binding<Bool>) {
switch self {
case let .maxWidth(width):
matches.wrappedValue = gtk_widget_get_width(child) <= width
case let .minWidth(width):
matches.wrappedValue = gtk_widget_get_width(child) >= width
case let .maxHeight(height):
matches.wrappedValue = gtk_widget_get_height(child) <= height
case let .minHeight(height):
matches.wrappedValue = gtk_widget_get_height(child) >= height
default:
break
}
}
}

View File

@ -45,8 +45,11 @@ extension Button {
/// - window: The application window. /// - window: The application window.
/// - active: Whether the keyboard shortcut is active. /// - active: Whether the keyboard shortcut is active.
/// - Returns: The button. /// - Returns: The button.
public func keyboardShortcut(_ shortcut: String, window: AdwaitaWindow, active: Bool = true) -> AnyView { public func keyboardShortcut(_ shortcut: String, active: Bool = true) -> AnyView {
onUpdate { inspect { _, data, _ in
guard let window = data.sceneStorage.pointer as? AdwaitaWindow else {
return
}
if active { if active {
window.app.addKeyboardShortcut(shortcut, id: shortcut, window: window) { self.clicked?() } window.app.addKeyboardShortcut(shortcut, id: shortcut, window: window) { self.clicked?() }
} else { } else {
@ -63,12 +66,15 @@ extension Button {
/// - window: The application. /// - window: The application.
/// - active: Whether the keyboard shortcut is active. /// - active: Whether the keyboard shortcut is active.
/// - Returns: The button. /// - Returns: The button.
public func keyboardShortcut(_ shortcut: String, app: AdwaitaApp, active: Bool = true) -> AnyView { public func appKeyboardShortcut(_ shortcut: String, active: Bool = true) -> AnyView {
onUpdate { inspect { _, data, _ in
guard let window = data.sceneStorage.pointer as? AdwaitaWindow else {
return
}
if active { if active {
app.addKeyboardShortcut(shortcut, id: shortcut) { self.clicked?() } window.app.addKeyboardShortcut(shortcut, id: shortcut) { self.clicked?() }
} else { } else {
app.removeKeyboardShortcut(id: shortcut) window.app.removeKeyboardShortcut(id: shortcut)
} }
} }
} }

View File

@ -9,7 +9,7 @@ import CAdw
import Foundation import Foundation
/// The about dialog widget. /// The about dialog widget.
public struct AboutDialog: AdwaitaWidget { struct AboutDialog: AdwaitaWidget {
/// Whether the dialog is visible. /// Whether the dialog is visible.
@Binding var visible: Bool @Binding var visible: Bool
@ -42,7 +42,7 @@ public struct AboutDialog: AdwaitaWidget {
/// - icon: The icon. /// - icon: The icon.
/// - website: The website's URL. /// - website: The website's URL.
/// - issues: The link for opening issues. /// - issues: The link for opening issues.
public init( init(
visible: Binding<Bool>, visible: Binding<Bool>,
child: AnyView, child: AnyView,
appName: String? = nil, appName: String? = nil,
@ -67,10 +67,8 @@ public struct AboutDialog: AdwaitaWidget {
/// - modifiers: Modify views before being updated. /// - modifiers: Modify views before being updated.
/// - type: The view render data type. /// - type: The view render data type.
/// - Returns: The view storage. /// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData { func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let storage = child.storage(data: data, type: type) child.storage(data: data, type: type)
update(storage, data: data, updateProperties: true, type: type)
return storage
} }
/// Update the stored content. /// Update the stored content.
@ -79,14 +77,14 @@ public struct AboutDialog: AdwaitaWidget {
/// - modifiers: Modify views before being updated /// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The view render data type. /// - type: The view render data type.
public func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
data: WidgetData, data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type) child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
guard updateProperties, (storage.previousState as? Self)?.visible != visible else { guard updateProperties else {
return return
} }
if visible { if visible {
@ -119,10 +117,11 @@ public struct AboutDialog: AdwaitaWidget {
adw_dialog_set_content_height(dialog?.cast(), -1) adw_dialog_set_content_height(dialog?.cast(), -1)
} else { } else {
if storage.content[dialogID]?.first != nil { if storage.content[dialogID]?.first != nil {
adw_dialog_close(storage.content[dialogID]?.first?.opaquePointer?.cast()) let dialog = storage.content[dialogID]?.first?.opaquePointer
adw_dialog_close(dialog?.cast())
storage.content[dialogID] = []
} }
} }
storage.previousState = self
} }
/// Create a new instance of the dialog. /// Create a new instance of the dialog.

View File

@ -28,6 +28,8 @@ public struct AlertDialog: AdwaitaWidget {
var heading: String var heading: String
/// The body text. /// The body text.
var body: String var body: String
/// The body view.
var extraChild: Body?
/// The available responses. /// The available responses.
var responses: [Response] = [] var responses: [Response] = []
/// The child view. /// The child view.
@ -40,18 +42,21 @@ public struct AlertDialog: AdwaitaWidget {
/// - id: A unique identifier for dialogs on the view. /// - id: A unique identifier for dialogs on the view.
/// - heading: The heading. /// - heading: The heading.
/// - body: The body text. /// - body: The body text.
public init( /// - extraChild: The body view.
init(
visible: Binding<Bool>, visible: Binding<Bool>,
child: AnyView, child: AnyView,
id: String, id: String,
heading: String, heading: String,
body: String body: String,
extraChild: Body? = nil
) { ) {
self._visible = visible self._visible = visible
self.child = child self.child = child
self.id = id self.id = id
self.heading = heading self.heading = heading
self.body = body self.body = body
self.extraChild = extraChild
} }
/// Information about a response. /// Information about a response.
@ -101,9 +106,7 @@ public struct AlertDialog: AdwaitaWidget {
data: WidgetData, data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
let storage = child.storage(data: data, type: type) child.storage(data: data, type: type)
update(storage, data: data, updateProperties: true, type: type)
return storage
} }
/// Update the stored content. /// Update the stored content.
@ -120,13 +123,18 @@ public struct AlertDialog: AdwaitaWidget {
) where Data: ViewRenderData { ) where Data: ViewRenderData {
storage.fields[Self.visibleID + id] = _visible storage.fields[Self.visibleID + id] = _visible
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type) child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
defer {
if let storage = storage.content["extra-child"]?.first, visible {
extraChild?.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
}
}
guard updateProperties else { guard updateProperties else {
return return
} }
if visible { if visible {
var present = false var present = false
if storage.content[Self.dialogID + id]?.first == nil { if storage.content[Self.dialogID + id]?.first == nil {
createDialog(storage: storage) createDialog(storage: storage, data: data)
present = true present = true
} }
let pointer = storage.content[Self.dialogID + id]?.first?.opaquePointer let pointer = storage.content[Self.dialogID + id]?.first?.opaquePointer
@ -135,10 +143,7 @@ public struct AlertDialog: AdwaitaWidget {
let old = storage.fields[Self.responsesID + id] as? [Response] ?? [] let old = storage.fields[Self.responsesID + id] as? [Response] ?? []
old.identifiableTransform( old.identifiableTransform(
to: responses, to: responses,
functions: .init { index, element in functions: .init { index in
adw_alert_dialog_remove_response(pointer?.cast(), responseID(old[safe: index]?.id))
adw_alert_dialog_add_response(pointer?.cast(), responseID(element.id), element.title)
} delete: { index in
adw_alert_dialog_remove_response(pointer?.cast(), responseID(old[safe: index]?.id)) adw_alert_dialog_remove_response(pointer?.cast(), responseID(old[safe: index]?.id))
} insert: { _, element in } insert: { _, element in
adw_alert_dialog_add_response(pointer?.cast(), responseID(element.id), element.title) adw_alert_dialog_add_response(pointer?.cast(), responseID(element.id), element.title)
@ -160,7 +165,9 @@ public struct AlertDialog: AdwaitaWidget {
} }
} else { } else {
if storage.content[Self.dialogID + id]?.first != nil { if storage.content[Self.dialogID + id]?.first != nil {
adw_dialog_close(storage.content[Self.dialogID + id]?.first?.opaquePointer?.cast()) let dialog = storage.content[Self.dialogID + id]?.first?.opaquePointer
adw_dialog_close(dialog?.cast())
storage.content[Self.dialogID] = []
} }
} }
} }
@ -199,11 +206,20 @@ public struct AlertDialog: AdwaitaWidget {
} }
/// Create a new instance of the dialog. /// Create a new instance of the dialog.
/// - Parameter storage: The wrapped view's storage. /// - Parameters:
func createDialog(storage: ViewStorage) { /// - storage: The wrapped view's storage.
/// - data: The widget data.
func createDialog(storage: ViewStorage, data: WidgetData) {
let pointer = adw_alert_dialog_new(nil, nil) let pointer = adw_alert_dialog_new(nil, nil)
let dialog = ViewStorage(pointer?.opaque()) let dialog = ViewStorage(pointer?.opaque())
storage.content[Self.dialogID + id] = [dialog] 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())
}
} }
/// Get the identifier of a response which is combined with the dialog's id. /// Get the identifier of a response which is combined with the dialog's id.

View File

@ -8,7 +8,7 @@
import CAdw import CAdw
/// The dialog widget. /// The dialog widget.
public struct Dialog: AdwaitaWidget { struct Dialog: AdwaitaWidget {
/// Whether the dialog is visible. /// Whether the dialog is visible.
@Binding var visible: Bool @Binding var visible: Bool
@ -39,7 +39,7 @@ public struct Dialog: AdwaitaWidget {
/// - title: The title. /// - title: The title.
/// - width: The width. /// - width: The width.
/// - height: The height. /// - height: The height.
public init( init(
visible: Binding<Bool>, visible: Binding<Bool>,
child: AnyView, child: AnyView,
id: String, id: String,
@ -62,11 +62,9 @@ public struct Dialog: AdwaitaWidget {
/// - modifiers: Modify views before being updated. /// - modifiers: Modify views before being updated.
/// - type: The view render data type. /// - type: The view render data type.
/// - Returns: The view storage. /// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData { func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let child = child.storage(data: data, type: type) let child = child.storage(data: data, type: type)
let storage = ViewStorage(child.opaquePointer, content: [.mainContent: [child]]) return .init(child.opaquePointer, content: [.mainContent: [child]])
update(storage, data: data, updateProperties: true, type: type)
return storage
} }
/// Update the stored content. /// Update the stored content.
@ -75,7 +73,7 @@ public struct Dialog: AdwaitaWidget {
/// - modifiers: Modify views before being updated /// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The view render data type. /// - type: The view render data type.
public func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
data: WidgetData, data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
@ -111,7 +109,9 @@ public struct Dialog: AdwaitaWidget {
} }
} else { } else {
if storage.content[dialogID + id]?.first != nil { if storage.content[dialogID + id]?.first != nil {
adw_dialog_close(storage.content[dialogID + id]?.first?.opaquePointer?.cast()) let dialog = storage.content[dialogID + id]?.first?.opaquePointer
adw_dialog_close(dialog?.cast())
storage.content[dialogID + id] = []
} }
} }
} }
@ -130,6 +130,7 @@ public struct Dialog: AdwaitaWidget {
let dialog = ViewStorage(pointer?.opaque()) let dialog = ViewStorage(pointer?.opaque())
storage.content[dialogID + id] = [dialog] storage.content[dialogID + id] = [dialog]
let contentStorage = content.storage(data: data, type: type) 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()) adw_dialog_set_child(pointer, contentStorage.opaquePointer?.cast())
storage.content[contentID + id] = [contentStorage] storage.content[contentID + id] = [contentStorage]
dialog.connectSignal(name: "closed") { dialog.connectSignal(name: "closed") {

View File

@ -9,67 +9,103 @@ import CAdw
import Foundation import Foundation
/// A structure representing a file dialog window. /// A structure representing a file dialog window.
public struct FileDialog: AdwaitaWidget { struct FileDialog: AdwaitaWidget {
/// Whether the dialog is an importer. /// The dialog type.
var importer: Bool var type: DialogType
/// Whether the dialog should open. /// Whether the dialog should open.
var open: Signal var open: Signal
/// The dialog's child. /// The dialog's child.
var child: AnyView var child: AnyView
/// The initial folder. /// The initial folder.
var initialFolder: URL? var initialFolder: URL?
/// The initial file name for the file exporter.
var initialName: String?
/// The accepted extensions for the file importer.
var extensions: [String]?
/// The closure to run when the import or export is successful. /// The closure to run when the import or export is successful.
var result: (URL) -> Void var result: (URL) -> Void
/// The closure to run when the import or export is not successful. /// The closure to run when the import or export is not successful.
var cancel: () -> Void var cancel: () -> Void
// swiftlint:disable function_default_parameter_at_end
/// Initialize the file dialog wrapper. /// Initialize the file dialog wrapper.
/// - Parameters: /// - Parameters:
/// - importer: Whether it is an importer. /// - type: The dialog type.
/// - open: The signal. /// - open: The signal.
/// - child: The wrapped view. /// - child: The wrapped view.
/// - initialFolder: The initial URL.
/// - initialName: The initial name.
/// - extensions: The file extensions.
/// - result: Run when the import or export succeeds. /// - result: Run when the import or export succeeds.
/// - cancel: Run when the import or export is not successful. /// - cancel: Run when the import or export is not successful.
public init( /// - initialFolder: The initial folder.
importer: Bool = true, init(
type: DialogType,
`open`: Signal, `open`: Signal,
child: AnyView, child: AnyView,
result: @escaping (URL) -> Void, result: @escaping (URL) -> Void,
cancel: @escaping () -> Void, cancel: @escaping () -> Void,
initialFolder: URL? = nil, initialFolder: URL? = nil,
initialName: String? = nil,
extensions: [String]? = nil
) { ) {
self.importer = importer self.type = type
self.open = open self.open = open
self.child = child self.child = child
self.result = result self.result = result
self.cancel = cancel self.cancel = cancel
self.initialFolder = initialFolder self.initialFolder = initialFolder
self.initialName = initialName
self.extensions = extensions
} }
// swiftlint:enable function_default_parameter_at_end
/// The different types of dialogs and their properties.
enum DialogType {
/// An importer dialog.
case importer(folder: Bool, extensions: [String]?)
/// An exporter dialog.
case exporter(initialName: String?)
/// Whether the dialog is an importer.
var isImporter: Bool {
switch self {
case .importer:
true
default:
false
}
}
/// The supported extensions.
var extensions: [String]? {
switch self {
case let .importer(folder: _, extensions: extensions):
extensions
default:
nil
}
}
/// Whether to import folders.
var folder: Bool {
switch self {
case let .importer(folder: folder, extensions: _):
folder
default:
false
}
}
/// The initial name.
var initialName: String? {
switch self {
case let .exporter(initialName: initialName):
initialName
default:
nil
}
}
}
/// The view storage. /// The view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - modifiers: Modify views before being updated.
/// - type: The view render data type. /// - type: The view render data type.
/// - Returns: The view storage. /// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData { func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let child = child.storage(data: data, type: type) let child = child.storage(data: data, type: type)
let storage = ViewStorage(child.opaquePointer, content: [.mainContent: [child]]) return .init(child.opaquePointer, content: [.mainContent: [child]])
update(storage, data: data, updateProperties: true, type: type)
return storage
} }
/// Update the stored content. /// Update the stored content.
@ -78,7 +114,7 @@ public struct FileDialog: AdwaitaWidget {
/// - modifiers: Modify views before being updated /// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The view render data type. /// - type: The view render data type.
public func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
data: WidgetData, data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
@ -89,32 +125,45 @@ public struct FileDialog: AdwaitaWidget {
guard let mainStorage = storage.content[.mainContent]?.first else { guard let mainStorage = storage.content[.mainContent]?.first else {
return return
} }
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type) child.updateStorage(mainStorage, data: data, updateProperties: updateProperties, type: type)
if open.update, storage.fields["callbacks"] == nil { if open.update, storage.fields["callbacks"] == nil {
var unref: [OpaquePointer?] = []
let pointer = gtk_file_dialog_new() let pointer = gtk_file_dialog_new()
if let initialName { unref.append(pointer)
if let initialName = self.type.initialName {
gtk_file_dialog_set_initial_name(pointer, initialName) gtk_file_dialog_set_initial_name(pointer, initialName)
} }
if let extensions { if let extensions = self.type.extensions {
let filter = gtk_file_filter_new() let filter = gtk_file_filter_new()
for name in extensions { for name in extensions {
gtk_file_filter_add_suffix(filter, name) gtk_file_filter_add_suffix(filter, name)
} }
gtk_file_dialog_set_default_filter(pointer, filter) gtk_file_dialog_set_default_filter(pointer, filter)
unref.append(filter)
} else { } else {
gtk_file_dialog_set_default_filter(pointer, nil) gtk_file_dialog_set_default_filter(pointer, nil)
} }
if let initialFolder { if let initialFolder {
gtk_file_dialog_set_initial_folder(pointer, g_file_new_for_path(initialFolder.absoluteString)) let file = g_file_new_for_path(initialFolder.absoluteString)
gtk_file_dialog_set_initial_folder(pointer, file)
unref.append(file)
} }
let callbacks = AdwaitaFileDialog() let callbacks = AdwaitaFileDialog()
callbacks.onResult = { (storage.fields["result"] as? (URL) -> Void)?($0) } let unrefClosure = {
callbacks.onCancel = { (storage.fields["cancel"] as? () -> Void)?() } for ref in unref {
g_object_unref(ref?.cast())
}
storage.fields["callbacks"] = nil
}
callbacks.onResult = { (storage.fields["result"] as? (URL) -> Void)?($0); unrefClosure() }
callbacks.onCancel = { (storage.fields["cancel"] as? () -> Void)?(); unrefClosure() }
callbacks.reset = { storage.fields["callbacks"] = nil } callbacks.reset = { storage.fields["callbacks"] = nil }
storage.fields["callbacks"] = callbacks storage.fields["callbacks"] = callbacks
let ptr = UInt64(Int(bitPattern: pointer)) let ptr = UInt64(Int(bitPattern: pointer))
let window = UInt64(Int(bitPattern: gtk_widget_get_root(mainStorage.opaquePointer?.cast()))) let window = UInt64(Int(bitPattern: gtk_widget_get_root(mainStorage.opaquePointer?.cast())))
if importer { if self.type.isImporter && self.type.folder {
gtui_filedialog_open_folder(ptr, unsafeBitCast(callbacks, to: UInt64.self), window)
} else if self.type.isImporter {
gtui_filedialog_open(ptr, unsafeBitCast(callbacks, to: UInt64.self), window) gtui_filedialog_open(ptr, unsafeBitCast(callbacks, to: UInt64.self), window)
} else { } else {
gtui_filedialog_save(ptr, unsafeBitCast(callbacks, to: UInt64.self), window) gtui_filedialog_save(ptr, unsafeBitCast(callbacks, to: UInt64.self), window)
@ -135,8 +184,9 @@ class AdwaitaFileDialog {
var reset: () -> Void = { } var reset: () -> Void = { }
/// Initialize the window callback. /// Initialize the window callback.
init() { init() { }
}
deinit { print("DEINIT fd") }
/// Run this when a file gets opened. /// Run this when a file gets opened.
/// - Parameter path: The file path. /// - Parameter path: The file path.

View File

@ -0,0 +1,252 @@
//
// PreferencesDialog.swift
// Adwaita
//
// Created by david-swift on 04.11.24.
//
import CAdw
/// The preferences dialog widget.
public struct PreferencesDialog: AdwaitaWidget {
/// Whether the dialog is visible.
@Binding var visible: Bool
/// An identifier used if multiple dialogs are on one view.
var id: String
/// The settings dialog pages.
var pages: [PreferencesPage] = []
/// The content.
var child: AnyView
/// The ID for the dialog's storage.
let dialogID = "dialog"
/// The ID for the content's storage.
let contentID = "content"
/// Initialize a dialog wrapper.
/// - Parameters:
/// - visible: Whether the dialog is visible.
/// - child: The wrapped view.
/// - id: An unique identifier for dialogs on the view.
init(
visible: Binding<Bool>,
child: AnyView,
id: String
) {
self._visible = visible
self.child = child
self.id = id
}
/// A preferences page.
public struct PreferencesPage {
/// The page's title.
var title: String
/// The page's icon.
var icon: Icon
/// The page content.
var content: [PreferencesGroup] = []
/// Initialize the preferences page.
/// - Parameters:
/// - title: The page title.
/// - icon: The page's icon.
init(_ title: String, icon: Icon) {
self.title = title
self.icon = icon
}
/// Get the GTK preferences page as well as the group's view storages.
/// - Parameter data: The widget data.
/// - Returns: The preferences page pointer and the groups view storages.
func gtkPreferencesPage(data: WidgetData) -> (OpaquePointer?, [ViewStorage]) {
let page = Adwaita.PreferencesPage()
.title(title)
.iconName(icon.string)
let pageStorage = page.storage(data: data.noModifiers, type: AdwaitaMainView.self)
page.update(pageStorage, data: data, updateProperties: true, type: AdwaitaMainView.self)
let groups = content.map { item in
let storage = item.gtkPreferencesGroup(data: data)
item.update(group: storage, data: data, updateProperties: true)
adw_preferences_page_add(pageStorage.opaquePointer?.cast(), storage.opaquePointer?.cast())
return storage
}
return (pageStorage.opaquePointer, groups)
}
/// Update the page.
/// - Parameters:
/// - groups: The groups' view storages.
/// - data: The widget data.
/// - updateProperties: Whether to update the properties.
func update(groups: [ViewStorage], data: WidgetData, updateProperties: Bool) {
for (index, storage) in groups.enumerated() {
content[safe: index]?.update(group: storage, data: data, updateProperties: updateProperties)
}
}
/// Add a preferences group.
/// - Parameters:
/// - title: The group's title.
/// - description: The group's description.
/// - child: The view child.
public func group(
_ title: String,
description: String = "",
@ViewBuilder child: () -> Body
) -> Self {
var newSelf = self
newSelf.content.append(
.init(
title: title,
description: description,
child: child()
)
)
return newSelf
}
}
/// The preferences group.
struct PreferencesGroup {
/// The group's title.
var title: String
/// The group's description.
var description: String
/// The group's child view.
var child: Body
/// Get the GTk preferences group.
/// - Parameter data: The widget data.
/// - Returns: The preferences group.
func group(data: WidgetData) -> Adwaita.PreferencesGroup {
.init()
.title(title)
.description(description)
.child { child }
}
/// Get the GTK preferences group's storage.
/// - Parameter data: The widget data.
/// - Returns: The view storage.
func gtkPreferencesGroup(data: WidgetData) -> ViewStorage {
group(data: data).container(data: data.noModifiers, type: AdwaitaMainView.self)
}
/// Update the preferences group.
/// - Parameters:
/// - group: The view storage.
/// - data: The widget data.
/// - updateProperties: Whether to update the properties.
func update(group: ViewStorage, data: WidgetData, updateProperties: Bool) {
self.group(data: data)
.update(group, data: data, updateProperties: updateProperties, type: AdwaitaMainView.self)
}
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The view render data type.
/// - 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)
return .init(child.opaquePointer, content: [.mainContent: [child]])
}
/// 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.
public func update<Data>(
_ storage: ViewStorage,
data: WidgetData,
updateProperties: Bool,
type: Data.Type
) where Data: ViewRenderData {
if let storage = storage.content[.mainContent]?.first {
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
}
defer {
if visible {
for (index, page) in pages.enumerated() {
if let preferences = storage.content["preferences-\(index)"] {
page.update(groups: preferences, data: data, updateProperties: updateProperties)
}
}
}
}
guard updateProperties else {
return
}
if visible {
if storage.content[dialogID + id]?.first == nil {
createDialog(storage: storage, data: data, type: type)
adw_dialog_present(
storage.content[dialogID + id]?.first?.opaquePointer?.cast(),
storage.opaquePointer?.cast()
)
}
} else {
if storage.content[dialogID + id]?.first != nil {
let dialog = storage.content[dialogID + id]?.first?.opaquePointer
adw_dialog_close(dialog?.cast())
g_object_unref(dialog?.cast())
for index in pages.indices {
let container = storage.content["preferences-\(index)"]?.map { $0.opaquePointer }
container?.forEach { g_object_unref($0?.cast()) }
g_object_unref((storage.fields["preferences-\(index)"] as? OpaquePointer)?.cast())
}
}
}
}
/// Create a new instance of the dialog.
/// - Parameters:
/// - storage: The wrapped view's storage.
/// - modifiers: The view modifiers.
/// - type: The view render data type.
func createDialog<Data>(
storage: ViewStorage,
data: WidgetData,
type: Data.Type
) where Data: ViewRenderData {
let pointer = adw_preferences_dialog_new()
adw_preferences_dialog_set_search_enabled(pointer?.cast(), 1)
let dialog = ViewStorage(pointer?.opaque())
storage.content[dialogID + id] = [dialog]
dialog.connectSignal(name: "closed") {
storage.content[dialogID + id] = []
storage.content[contentID + id] = []
if visible {
visible = false
}
}
for (index, page) in pages.map({ $0.gtkPreferencesPage(data: data) }).enumerated() {
storage.content["preferences-\(index)"] = page.1
storage.fields["preferences-\(index)"] = page.0
adw_preferences_dialog_add(pointer?.cast(), page.0?.cast())
}
}
/// Add a preferences page.
/// - Parameters:
/// - title: The page title.
/// - icon: The page icon.
/// - content: Modify the preferences pages.
public func preferencesPage(
_ title: String,
icon: Icon,
content: (PreferencesPage) -> PreferencesPage
) -> Self {
modify { $0.pages.append(content(.init(title, icon: icon))) }
}
}

View File

@ -0,0 +1,192 @@
//
// ShortcutsDialog.swift
// Adwaita
//
// Created by david-swift on 04.11.25.
//
import CAdw
/// The shortcuts dialog widget.
public struct ShortcutsDialog: AdwaitaWidget {
/// Whether the dialog is visible.
@Binding var visible: Bool
/// An identifier used if multiple dialogs are on one view.
var id: String
/// The shortcuts dialog sections.
var sections: [ShortcutsSection] = []
/// The content.
var child: AnyView
/// The ID for the dialog's storage.
let dialogID = "dialog"
/// The ID for the content's storage.
let contentID = "content"
/// Initialize a dialog wrapper.
/// - Parameters:
/// - visible: Whether the dialog is visible.
/// - child: The wrapped view.
/// - id: A unique identifier for dialogs on the view.
init(
visible: Binding<Bool>,
child: AnyView,
id: String
) {
self._visible = visible
self.child = child
self.id = id
}
/// A shortcuts section.
public struct ShortcutsSection {
/// The section's title.
var title: String?
/// The section's content.
var content: [ShortcutsItem] = []
/// Initialize the shortcuts section.
/// - Parameter title: The section's title.
init(_ title: String?) {
self.title = title
}
/// Get the GTK shortcuts section as well as the section's view storages.
/// - Parameter data: The widget data.
/// - Returns: The shortcuts section pointer and the section's view storages.
func gtkShortcutsSection(data: WidgetData) -> (OpaquePointer?, [ViewStorage]) {
let section = adw_shortcuts_section_new(title)
let items = content.map { $0.gtkShortcutsItem(data: data) }
for item in items {
adw_shortcuts_section_add(section, item.opaquePointer)
}
return (section, items)
}
/// Add a shortcuts item.
/// - Parameters:
/// - title: The item's title.
/// - accelerator: The shortcut acccelerator.
public func shortcutsItem(
_ title: String,
accelerator: String
) -> Self {
var newSelf = self
newSelf.content.append(
.init(
title: title,
accelerator: accelerator
)
)
return newSelf
}
}
/// The shortcuts item.
struct ShortcutsItem {
/// The item's title.
var title: String
/// The item's description.
var accelerator: String
/// Get the GTK preferences group's storage.
/// - Parameter data: The widget data.
/// - Returns: The view storage.
func gtkShortcutsItem(data: WidgetData) -> ViewStorage {
.init(adw_shortcuts_item_new(title, accelerator))
}
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The view render data type.
/// - 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)
return .init(child.opaquePointer, content: [.mainContent: [child]])
}
/// 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.
public func update<Data>(
_ storage: ViewStorage,
data: WidgetData,
updateProperties: Bool,
type: Data.Type
) where Data: ViewRenderData {
if let storage = storage.content[.mainContent]?.first {
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
}
guard updateProperties else {
return
}
if visible {
if storage.content[dialogID + id]?.first == nil {
createDialog(storage: storage, data: data, type: type)
adw_dialog_present(
storage.content[dialogID + id]?.first?.opaquePointer?.cast(),
storage.opaquePointer?.cast()
)
}
} else {
if storage.content[dialogID + id]?.first != nil {
let dialog = storage.content[dialogID + id]?.first?.opaquePointer
adw_dialog_close(dialog?.cast())
g_object_unref(dialog?.cast())
for index in sections.indices {
let container = storage.content["shortcuts-\(index)"]?.map { $0.opaquePointer }
container?.forEach { g_object_unref($0?.cast()) }
g_object_unref((storage.fields["shortcuts-\(index)"] as? OpaquePointer)?.cast())
}
}
}
}
/// Create a new instance of the dialog.
/// - Parameters:
/// - storage: The wrapped view's storage.
/// - modifiers: The view modifiers.
/// - type: The view render data type.
func createDialog<Data>(
storage: ViewStorage,
data: WidgetData,
type: Data.Type
) where Data: ViewRenderData {
let pointer = adw_shortcuts_dialog_new()
let dialog = ViewStorage(pointer?.opaque())
storage.content[dialogID + id] = [dialog]
dialog.connectSignal(name: "closed") {
storage.content[dialogID + id] = []
storage.content[contentID + id] = []
if visible {
visible = false
}
}
for (index, section) in sections.map({ $0.gtkShortcutsSection(data: data) }).enumerated() {
storage.content["shortcuts-\(index)"] = section.1
storage.fields["shortcuts-\(index)"] = section.0
adw_shortcuts_dialog_add(pointer?.opaque(), section.0)
}
}
/// Add a shortcuts section.
/// - Parameters:
/// - title: The section's title or `nil`.
/// - content: Modify the shortcuts items.
public func shortcutsSection(
_ title: String? = nil,
content: (ShortcutsSection) -> ShortcutsSection
) -> Self {
modify { $0.sections.append(content(.init(title))) }
}
}

View File

@ -1,15 +1,14 @@
// //
// ComboRow+.swift // DropDown+.swift
// Adwaita // Adwaita
// //
// Created by david-swift on 20.01.24. // Created by david-swift on 09.04.25.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A row for selecting an element out of a list of elements. extension DropDown {
extension ComboRow {
/// The identifier for the values. /// The identifier for the values.
static var values: String { "values" } static var values: String { "values" }
@ -18,30 +17,40 @@ extension ComboRow {
/// Initialize a combo row. /// Initialize a combo row.
/// - Parameters: /// - Parameters:
/// - title: The row's title.
/// - selection: The selected value. /// - selection: The selected value.
/// - values: The available values. /// - values: The available values.
public init<Element>( public init<Element>(
_ title: String,
selection: Binding<Element.ID>, selection: Binding<Element.ID>,
values: [Element] values: [Element]
) where Element: Identifiable, Element: CustomStringConvertible { ) where Element: Identifiable, Element: CustomStringConvertible {
self = self.title(title) 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 { self = self.selected(.init {
.init(values.firstIndex { $0.id == selection.wrappedValue } ?? 0) .init(values.firstIndex { $0[keyPath: id] == selection.wrappedValue } ?? 0)
} set: { index in } set: { index in
if let id = values[safe: .init(index)]?.id { if let id = values[safe: .init(index)]?[keyPath: id] {
selection.wrappedValue = id selection.wrappedValue = id
} }
}) })
appearFunctions.append { storage, _ in appearFunctions.append { storage, _ in
let list = gtk_string_list_new(nil) storage.fields[Self.stringList] = gtk_drop_down_get_model(storage.opaquePointer)
storage.fields[Self.stringList] = list Self.updateContent(storage: storage, values: values, id: id, description: description)
adw_combo_row_set_model(storage.opaquePointer?.cast(), list)
Self.updateContent(storage: storage, values: values, element: Element.self)
} }
updateFunctions.append { storage, _, _ in updateFunctions.append { storage, _, _ in
Self.updateContent(storage: storage, values: values, element: Element.self) Self.updateContent(storage: storage, values: values, id: id, description: description)
} }
} }
@ -49,23 +58,23 @@ extension ComboRow {
/// - Parameters: /// - Parameters:
/// - storage: The view storage. /// - storage: The view storage.
/// - values: The elements. /// - values: The elements.
/// - element: The type of the elements. /// - id: The keypath to the id.
static func updateContent<Element>( /// - description: The keypath to the description.
static func updateContent<Element, Identifier>(
storage: ViewStorage, storage: ViewStorage,
values: [Element], values: [Element],
element: Element.Type id: KeyPath<Element, Identifier>,
) where Element: Identifiable, Element: CustomStringConvertible { description: KeyPath<Element, String>
) where Identifier: Equatable {
if let list = storage.fields[Self.stringList] as? OpaquePointer { if let list = storage.fields[Self.stringList] as? OpaquePointer {
let old = storage.fields[Self.values] as? [Element] ?? [] let old = storage.fields[Self.values] as? [Element] ?? []
old.identifiableTransform( old.transform(
to: values, to: values,
functions: .init { index, element in id: id,
gtk_string_list_remove(list, .init(index)) functions: .init { index in
gtk_string_list_append(list, element.description)
} delete: { index in
gtk_string_list_remove(list, .init(index)) gtk_string_list_remove(list, .init(index))
} insert: { _, element in } insert: { _, element in
gtk_string_list_append(list, element.description) gtk_string_list_append(list, element[keyPath: description])
} }
) )
storage.fields[Self.values] = values storage.fields[Self.values] = values

View File

@ -0,0 +1,21 @@
//
// Entry+.swift
// Adwaita
//
// Created by david-swift on 19.04.25.
//
extension Entry {
/// Initialize an entry.
/// - Parameters:
/// - placeholder: The placeholder text.
/// - text: The value.
public init(_ placeholder: String, text: Binding<String>) {
self.init()
self = self
.text(text)
.placeholderText(placeholder)
}
}

View File

@ -17,19 +17,21 @@ extension FlowBox {
/// Initialize `FlowBox`. /// Initialize `FlowBox`.
/// - Parameters: /// - Parameters:
/// - elements: The elements. /// - elements: The elements.
/// - id: The element identifier keypath.
/// - selection: The identifier of the selected element. Selection disabled if `nil`. /// - selection: The identifier of the selected element. Selection disabled if `nil`.
/// - content: The view for an element. /// - content: The view for an element.
public init( public init(
_ elements: [Element], _ elements: [Element],
selection: Binding<Element.ID>?, id: KeyPath<Element, Identifier>,
selection: Binding<Identifier>? = nil,
@ViewBuilder content: @escaping (Element) -> Body @ViewBuilder content: @escaping (Element) -> Body
) { ) {
self.init(elements, content: content) self.init(elements, id: id, content: content)
let id: (ViewStorage, [Element]) -> Element.ID? = { storage, elements in let getID: (ViewStorage, [Element]) -> Identifier? = { storage, elements in
if let child = g_list_nth_data(gtk_flow_box_get_selected_children(storage.opaquePointer), 0) { 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()) let element = gtk_flow_box_child_get_child(child.cast())
return elements[safe: storage.content[.mainContent]? return elements[safe: storage.content[.mainContent]?
.firstIndex { $0.opaquePointer?.cast() == element }]?.id .firstIndex { $0.opaquePointer?.cast() == element }]?[keyPath: id]
} }
return nil return nil
} }
@ -37,12 +39,12 @@ extension FlowBox {
updateFunctions.append { storage, _, _ in updateFunctions.append { storage, _, _ in
storage.connectSignal(name: "selected_children_changed", id: Self.selectionField) { storage.connectSignal(name: "selected_children_changed", id: Self.selectionField) {
if let elements = storage.fields[Self.elementsField] as? [Element], 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), if selection.wrappedValue != getID(storage, elements),
let index = elements.firstIndex(where: { $0.id == selection.wrappedValue })?.cInt { let index = elements.firstIndex(where: { $0[keyPath: id] == selection.wrappedValue })?.cInt {
gtk_flow_box_select_child( gtk_flow_box_select_child(
storage.opaquePointer, storage.opaquePointer,
gtk_flow_box_get_child_at_index(storage.opaquePointer, index) 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 import LevenshteinTransformations
/// A dynamic list but without a list design in the user interface. /// 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. /// The dynamic widget elements.
var elements: [Element] var elements: [Element]
@ -17,12 +17,22 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
var content: (Element) -> Body var content: (Element) -> Body
/// Whether the list is horizontal. /// Whether the list is horizontal.
var horizontal: Bool 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`. /// 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.elements = elements
self.content = content self.content = content
self.horizontal = horizontal self.horizontal = horizontal
self.id = id
} }
/// The view storage. /// The view storage.
@ -34,11 +44,9 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
data: WidgetData, data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
let storage = ViewStorage( .init(
gtk_box_new(horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, 0)?.opaque() 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. /// Update the stored content.
@ -56,20 +64,12 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? [] var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? [] let old = storage.fields["element"] as? [Element] ?? []
let widget: UnsafeMutablePointer<GtkBox>? = storage.opaquePointer?.cast() let widget: UnsafeMutablePointer<GtkBox>? = storage.opaquePointer?.cast()
old.identifiableTransform( old.transform(
to: elements, to: elements,
functions: .init { index, element in id: id,
let child = content(element).storage(data: data, type: type) functions: .init { index in
gtk_box_remove(widget, contentStorage[safe: index]?.opaquePointer?.cast()) let child = contentStorage[safe: index]?.opaquePointer
gtk_box_insert_child_after( gtk_box_remove(widget, child?.cast())
widget,
child.opaquePointer?.cast(),
contentStorage[safe: index - 1]?.opaquePointer?.cast()
)
contentStorage.remove(at: index)
contentStorage.insert(child, at: index)
} delete: { index in
gtk_box_remove(widget, contentStorage[safe: index]?.opaquePointer?.cast())
contentStorage.remove(at: index) contentStorage.remove(at: index)
} insert: { index, element in } insert: { index, element in
let child = content(element).storage(data: data, type: type) let child = content(element).storage(data: data, type: type)
@ -82,10 +82,16 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
} }
) )
if updateProperties { if updateProperties {
gtk_orientable_set_orientation( if (storage.previousState as? Self)?.horizontal != horizontal {
widget?.opaque(), gtk_orientable_set_orientation(
horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL widget?.opaque(),
) horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL
)
}
if let homogeneous, (storage.previousState as? Self)?.homogeneous != homogeneous {
gtk_box_set_homogeneous(widget?.cast(), homogeneous.cBool)
}
storage.previousState = self
} }
storage.fields["element"] = elements storage.fields["element"] = elements
storage.content[.mainContent] = contentStorage storage.content[.mainContent] = contentStorage
@ -100,4 +106,23 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
} }
} }
/// Whether the children should all be the same size.
/// - Parameter homogeneous: Whether the children should all be the same size.
/// - Returns: The for each view.
public func homogeneous(_ homogeneous: Bool? = true) -> Self {
modify { $0.homogeneous = homogeneous }
}
}
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

@ -14,4 +14,11 @@ extension ActionRow {
self = self.title(title) self = self.title(title)
} }
/// Deemphasize the row title and emphasize the subtitle.
/// - Parameter active: Whether the style is currently applied.
/// - Returns: A view.
public func property(_ active: Bool = true) -> AnyView {
style("property", active: active)
}
} }

View File

@ -0,0 +1,64 @@
//
// ComboRow+.swift
// Adwaita
//
// Created by david-swift on 20.01.24.
//
import CAdw
import LevenshteinTransformations
/// A row for selecting an element out of a list of elements.
extension ComboRow {
/// The identifier for the values.
static var values: String { "values" }
/// The identifier for the string list.
static var stringList: String { "string-list" }
/// Initialize a combo row.
/// - Parameters:
/// - title: The row's title.
/// - selection: The selected value.
/// - values: The available values.
public init<Element>(
_ title: String,
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[keyPath: id] == selection.wrappedValue } ?? 0)
} set: { index in
if let id = values[safe: .init(index)]?[keyPath: id] {
selection.wrappedValue = id
}
})
appearFunctions.append { storage, _ in
let list = gtk_string_list_new(nil)
storage.fields[Self.stringList] = list
adw_combo_row_set_model(storage.opaquePointer?.cast(), list)
g_object_unref(list?.cast())
DropDown.updateContent(storage: storage, values: values, id: id, description: description)
}
updateFunctions.append { storage, _, _ in
DropDown.updateContent(storage: storage, values: values, id: id, description: description)
}
}
}

View File

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

View File

@ -2,15 +2,15 @@
// ActionRow.swift // ActionRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A [class@Gtk.ListBoxRow] used to present actions. /// A `Gtk.ListBoxRow` used to present actions.
///
/// ///
/// <picture><source srcset="action-row-dark.png" media="(prefers-color-scheme: dark)"><img src="action-row.png" alt="action-row"></picture>
/// ///
/// The `AdwActionRow` widget can have a title, a subtitle and an icon. The row /// The `AdwActionRow` widget can have a title, a subtitle and an icon. The row
/// can receive additional widgets at its end, or prefix widgets at its start. /// can receive additional widgets at its end, or prefix widgets at its start.
@ -21,50 +21,35 @@ import LevenshteinTransformations
/// will automatically make it activatable, but unsetting it won't change the /// will automatically make it activatable, but unsetting it won't change the
/// row's activatability. /// row's activatability.
/// ///
/// ## AdwActionRow as GtkBuildable
/// ///
/// The `AdwActionRow` implementation of the [iface@Gtk.Buildable] interface
/// supports adding a child at its end by specifying suffix or omitting the
/// type attribute of a <child> element.
///
/// It also supports adding a child as a prefix widget by specifying prefix as
/// the type attribute of a <child> element.
///
/// ## CSS nodes
///
/// `AdwActionRow` has a main CSS node with name `row`.
///
/// It contains the subnode `box.header` for its main horizontal box, and
/// `box.title` for the vertical box containing the title and subtitle labels.
///
/// It contains subnodes `label.title` and `label.subtitle` representing
/// respectively the title label and subtitle label.
///
/// `AdwActionRow` can use the
/// [`.property`](style-classes.html#property-rows) style class to emphasize
/// the row subtitle instead of the row title, which is useful for
/// displaying read-only properties.
public struct ActionRow: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The widget to activate when the row is activated. /// The widget to activate when the row is activated.
/// ///
/// The row can be activated either by clicking on it, calling /// The row can be activated either by clicking on it, calling
/// [method@ActionRow.activate], or via mnemonics in the title. /// `ActionRow.activate`, or via mnemonics in the title.
/// See the [property@PreferencesRow:use-underline] property to enable /// See the ``useUnderline(_:)`` property to enable
/// mnemonics. /// mnemonics.
/// ///
/// The target widget will be activated by emitting the /// The target widget will be activated by emitting the
/// [signal@Gtk.Widget::mnemonic-activate] signal on it. /// `Gtk.Widget::mnemonic-activate` signal on it.
var activatableWidget: (() -> Body)? var activatableWidget: Body?
/// The subtitle for this row. /// The subtitle for this row.
/// ///
/// The subtitle is interpreted as Pango markup unless /// The subtitle is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
var subtitle: String? var subtitle: String?
/// The number of lines at the end of which the subtitle label will be /// The number of lines at the end of which the subtitle label will be
/// ellipsized. /// ellipsized.
@ -73,12 +58,12 @@ public struct ActionRow: AdwaitaWidget {
var subtitleLines: Int? var subtitleLines: Int?
/// Whether the user can copy the subtitle from the label. /// Whether the user can copy the subtitle from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
var subtitleSelectable: Bool? var subtitleSelectable: Bool?
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
var title: String? var title: String?
/// The number of lines at the end of which the title label will be ellipsized. /// The number of lines at the end of which the title label will be ellipsized.
/// ///
@ -86,13 +71,13 @@ public struct ActionRow: AdwaitaWidget {
var titleLines: Int? var titleLines: Int?
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
var titleSelectable: Bool? var titleSelectable: Bool?
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
var useMarkup: Bool? var useMarkup: Bool?
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
var useUnderline: Bool? var useUnderline: Bool?
@ -117,8 +102,7 @@ public struct ActionRow: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let activatableWidgetStorage = activatableWidget?.storage(data: data, type: type) {
if let activatableWidgetStorage = activatableWidget?().storage(data: data, type: type) {
storage.content["activatableWidget"] = [activatableWidgetStorage] storage.content["activatableWidget"] = [activatableWidgetStorage]
adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast()) adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast())
} }
@ -153,7 +137,7 @@ public struct ActionRow: AdwaitaWidget {
storage.modify { widget in storage.modify { widget in
if let widget = storage.content["activatableWidget"]?.first { if let widget = storage.content["activatableWidget"]?.first {
activatableWidget?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) activatableWidget?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let subtitleLines, updateProperties, (storage.previousState as? Self)?.subtitleLines != subtitleLines { if let subtitleLines, updateProperties, (storage.previousState as? Self)?.subtitleLines != subtitleLines {
adw_action_row_set_subtitle_lines(widget?.cast(), subtitleLines.cInt) adw_action_row_set_subtitle_lines(widget?.cast(), subtitleLines.cInt)
@ -205,6 +189,7 @@ public struct ActionRow: AdwaitaWidget {
} }
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -217,28 +202,22 @@ public struct ActionRow: AdwaitaWidget {
/// The widget to activate when the row is activated. /// The widget to activate when the row is activated.
/// ///
/// The row can be activated either by clicking on it, calling /// The row can be activated either by clicking on it, calling
/// [method@ActionRow.activate], or via mnemonics in the title. /// `ActionRow.activate`, or via mnemonics in the title.
/// See the [property@PreferencesRow:use-underline] property to enable /// See the ``useUnderline(_:)`` property to enable
/// mnemonics. /// mnemonics.
/// ///
/// The target widget will be activated by emitting the /// The target widget will be activated by emitting the
/// [signal@Gtk.Widget::mnemonic-activate] signal on it. /// `Gtk.Widget::mnemonic-activate` signal on it.
public func activatableWidget(@ViewBuilder _ activatableWidget: @escaping (() -> Body)) -> Self { public func activatableWidget(@ViewBuilder _ activatableWidget: () -> Body) -> Self {
var newSelf = self modify { $0.activatableWidget = activatableWidget() }
newSelf.activatableWidget = activatableWidget
return newSelf
} }
/// The subtitle for this row. /// The subtitle for this row.
/// ///
/// The subtitle is interpreted as Pango markup unless /// The subtitle is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
public func subtitle(_ subtitle: String?) -> Self { public func subtitle(_ subtitle: String?) -> Self {
var newSelf = self modify { $0.subtitle = subtitle }
newSelf.subtitle = subtitle
return newSelf
} }
/// The number of lines at the end of which the subtitle label will be /// The number of lines at the end of which the subtitle label will be
@ -246,71 +225,50 @@ public struct ActionRow: AdwaitaWidget {
/// ///
/// If the value is 0, the number of lines won't be limited. /// If the value is 0, the number of lines won't be limited.
public func subtitleLines(_ subtitleLines: Int?) -> Self { public func subtitleLines(_ subtitleLines: Int?) -> Self {
var newSelf = self modify { $0.subtitleLines = subtitleLines }
newSelf.subtitleLines = subtitleLines
return newSelf
} }
/// Whether the user can copy the subtitle from the label. /// Whether the user can copy the subtitle from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
public func subtitleSelectable(_ subtitleSelectable: Bool? = true) -> Self { public func subtitleSelectable(_ subtitleSelectable: Bool? = true) -> Self {
var newSelf = self modify { $0.subtitleSelectable = subtitleSelectable }
newSelf.subtitleSelectable = subtitleSelectable
return newSelf
} }
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
public func title(_ title: String?) -> Self { public func title(_ title: String?) -> Self {
var newSelf = self modify { $0.title = title }
newSelf.title = title
return newSelf
} }
/// The number of lines at the end of which the title label will be ellipsized. /// The number of lines at the end of which the title label will be ellipsized.
/// ///
/// If the value is 0, the number of lines won't be limited. /// If the value is 0, the number of lines won't be limited.
public func titleLines(_ titleLines: Int?) -> Self { public func titleLines(_ titleLines: Int?) -> Self {
var newSelf = self modify { $0.titleLines = titleLines }
newSelf.titleLines = titleLines
return newSelf
} }
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
public func titleSelectable(_ titleSelectable: Bool? = true) -> Self { public func titleSelectable(_ titleSelectable: Bool? = true) -> Self {
var newSelf = self modify { $0.titleSelectable = titleSelectable }
newSelf.titleSelectable = titleSelectable
return newSelf
} }
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
public func useMarkup(_ useMarkup: Bool? = true) -> Self { public func useMarkup(_ useMarkup: Bool? = true) -> Self {
var newSelf = self modify { $0.useMarkup = useMarkup }
newSelf.useMarkup = useMarkup
return newSelf
} }
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// This signal is emitted after the row has been activated. /// This signal is emitted after the row has been activated.

View File

@ -2,45 +2,44 @@
// AspectFrame.swift // AspectFrame.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// `GtkAspectFrame` preserves the aspect ratio of its child. /// Preserves the aspect ratio of its child.
/// ///
/// The frame can respect the aspect ratio of the child widget, /// The frame can respect the aspect ratio of the child widget,
/// or use its own aspect ratio. /// or use its own aspect ratio.
/// ///
/// # CSS nodes
/// ///
/// `GtkAspectFrame` uses a CSS node with name `frame`.
///
/// # Accessibility
///
/// Until GTK 4.10, `GtkAspectFrame` used the `GTK_ACCESSIBLE_ROLE_GROUP` role.
///
/// Starting from GTK 4.12, `GtkAspectFrame` uses the `GTK_ACCESSIBLE_ROLE_GENERIC` role.
public struct AspectFrame: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
var accessibleRole: String? var accessibleRole: String?
/// The child widget. /// The child widget.
var child: (() -> Body)? var child: Body?
/// Whether the `GtkAspectFrame` should use the aspect ratio of its child. /// Whether the `GtkAspectFrame` should use the aspect ratio of its child.
var obeyChild: Bool? var obeyChild: Bool?
/// The aspect ratio to be used by the `GtkAspectFrame`. /// The aspect ratio to be used by the `GtkAspectFrame`.
/// ///
/// This property is only used if /// This property is only used if
/// [property@Gtk.AspectFrame:obey-child] is set to %FALSE. /// ``obeyChild(_:)`` is set to `false`.
var ratio: Float var ratio: Float
/// The horizontal alignment of the child. /// The horizontal alignment of the child.
var xalign: Float? var xalign: Float?
@ -62,8 +61,7 @@ public struct AspectFrame: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let childStorage = child?.storage(data: data, type: type) {
if let childStorage = child?().storage(data: data, type: type) {
storage.content["child"] = [childStorage] storage.content["child"] = [childStorage]
gtk_aspect_frame_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast()) gtk_aspect_frame_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())
} }
@ -81,7 +79,7 @@ public struct AspectFrame: AdwaitaWidget {
storage.modify { widget in storage.modify { widget in
if let widget = storage.content["child"]?.first { if let widget = storage.content["child"]?.first {
child?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) child?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let obeyChild, updateProperties, (storage.previousState as? Self)?.obeyChild != obeyChild { if let obeyChild, updateProperties, (storage.previousState as? Self)?.obeyChild != obeyChild {
gtk_aspect_frame_set_obey_child(widget, obeyChild.cBool) gtk_aspect_frame_set_obey_child(widget, obeyChild.cBool)
@ -97,6 +95,7 @@ public struct AspectFrame: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -110,53 +109,35 @@ public struct AspectFrame: AdwaitaWidget {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// The child widget. /// The child widget.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self { public func child(@ViewBuilder _ child: () -> Body) -> Self {
var newSelf = self modify { $0.child = child() }
newSelf.child = child
return newSelf
} }
/// Whether the `GtkAspectFrame` should use the aspect ratio of its child. /// Whether the `GtkAspectFrame` should use the aspect ratio of its child.
public func obeyChild(_ obeyChild: Bool? = true) -> Self { public func obeyChild(_ obeyChild: Bool? = true) -> Self {
var newSelf = self modify { $0.obeyChild = obeyChild }
newSelf.obeyChild = obeyChild
return newSelf
} }
/// The aspect ratio to be used by the `GtkAspectFrame`. /// The aspect ratio to be used by the `GtkAspectFrame`.
/// ///
/// This property is only used if /// This property is only used if
/// [property@Gtk.AspectFrame:obey-child] is set to %FALSE. /// ``obeyChild(_:)`` is set to `false`.
public func ratio(_ ratio: Float) -> Self { public func ratio(_ ratio: Float) -> Self {
var newSelf = self modify { $0.ratio = ratio }
newSelf.ratio = ratio
return newSelf
} }
/// The horizontal alignment of the child. /// The horizontal alignment of the child.
public func xalign(_ xalign: Float?) -> Self { public func xalign(_ xalign: Float?) -> Self {
var newSelf = self modify { $0.xalign = xalign }
newSelf.xalign = xalign
return newSelf
} }
/// The vertical alignment of the child. /// The vertical alignment of the child.
public func yalign(_ yalign: Float?) -> Self { public func yalign(_ yalign: Float?) -> Self {
var newSelf = self modify { $0.yalign = yalign }
newSelf.yalign = yalign
return newSelf
} }
} }

View File

@ -2,7 +2,7 @@
// Avatar.swift // Avatar.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,30 +10,35 @@ import LevenshteinTransformations
/// A widget displaying an image, with a generated fallback. /// A widget displaying an image, with a generated fallback.
/// ///
/// <picture><source srcset="avatar-dark.png" media="(prefers-color-scheme: dark)"><img src="avatar.png" alt="avatar"></picture> ///
/// ///
/// `AdwAvatar` is a widget that shows a round avatar. /// `AdwAvatar` is a widget that shows a round avatar.
/// ///
/// `AdwAvatar` generates an avatar with the initials of the /// `AdwAvatar` generates an avatar with the initials of the
/// [property@Avatar:text] on top of a colored background. /// ``text(_:)`` on top of a colored background.
/// ///
/// The color is picked based on the hash of the [property@Avatar:text]. /// The color is picked based on the hash of the ``text(_:)``.
/// ///
/// If [property@Avatar:show-initials] is set to `FALSE`, /// If ``showInitials(_:)`` is set to `false`,
/// [property@Avatar:icon-name] or `avatar-default-symbolic` is shown instead of /// ``iconName(_:)`` or `avatar-default-symbolic` is shown instead of
/// the initials. /// the initials.
/// ///
/// Use [property@Avatar:custom-image] to set a custom image. /// Use ``customImage(_:)`` to set a custom image.
/// ///
/// ## CSS nodes
/// ///
/// `AdwAvatar` has a single CSS node with name `avatar`.
public struct Avatar: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The name of an icon to use as a fallback. /// The name of an icon to use as a fallback.
/// ///
@ -41,14 +46,14 @@ public struct Avatar: AdwaitaWidget {
var iconName: String? var iconName: String?
/// Whether initials are used instead of an icon on the fallback avatar. /// Whether initials are used instead of an icon on the fallback avatar.
/// ///
/// See [property@Avatar:icon-name] for how to change the fallback icon. /// See ``iconName(_:)`` for how to change the fallback icon.
var showInitials: Bool var showInitials: Bool
/// The size of the avatar. /// The size of the avatar.
var size: Int var size: Int
/// Sets the text used to generate the fallback initials and color. /// Sets the text used to generate the fallback initials and color.
/// ///
/// It's only used to generate the color if [property@Avatar:show-initials] is /// It's only used to generate the color if ``showInitials(_:)`` is
/// `FALSE`. /// `false`.
var text: String? var text: String?
/// Initialize `Avatar`. /// Initialize `Avatar`.
@ -67,7 +72,6 @@ public struct Avatar: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -95,6 +99,7 @@ public struct Avatar: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -108,39 +113,27 @@ public struct Avatar: AdwaitaWidget {
/// ///
/// If no name is set, `avatar-default-symbolic` will be used. /// If no name is set, `avatar-default-symbolic` will be used.
public func iconName(_ iconName: String?) -> Self { public func iconName(_ iconName: String?) -> Self {
var newSelf = self modify { $0.iconName = iconName }
newSelf.iconName = iconName
return newSelf
} }
/// Whether initials are used instead of an icon on the fallback avatar. /// Whether initials are used instead of an icon on the fallback avatar.
/// ///
/// See [property@Avatar:icon-name] for how to change the fallback icon. /// See ``iconName(_:)`` for how to change the fallback icon.
public func showInitials(_ showInitials: Bool) -> Self { public func showInitials(_ showInitials: Bool) -> Self {
var newSelf = self modify { $0.showInitials = showInitials }
newSelf.showInitials = showInitials
return newSelf
} }
/// The size of the avatar. /// The size of the avatar.
public func size(_ size: Int) -> Self { public func size(_ size: Int) -> Self {
var newSelf = self modify { $0.size = size }
newSelf.size = size
return newSelf
} }
/// Sets the text used to generate the fallback initials and color. /// Sets the text used to generate the fallback initials and color.
/// ///
/// It's only used to generate the color if [property@Avatar:show-initials] is /// It's only used to generate the color if ``showInitials(_:)`` is
/// `FALSE`. /// `false`.
public func text(_ text: String?) -> Self { public func text(_ text: String?) -> Self {
var newSelf = self modify { $0.text = text }
newSelf.text = text
return newSelf
} }
} }

View File

@ -2,7 +2,7 @@
// Banner.swift // Banner.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,46 +10,54 @@ import LevenshteinTransformations
/// A bar with contextual information. /// A bar with contextual information.
/// ///
/// <picture><source srcset="banner-dark.png" media="(prefers-color-scheme: dark)"><img src="banner.png" alt="banner"></picture>
/// ///
/// Banners are hidden by default, use [property@Banner:revealed] to show them.
/// ///
/// Banners have a title, set with [property@Banner:title]. Titles can be marked /// Banners are hidden by default, use ``revealed(_:)`` to show them.
/// up with Pango markup, use [property@Banner:use-markup] to enable it. ///
/// Banners have a title, set with ``title(_:)``. Titles can be marked
/// up with Pango markup, use ``useMarkup(_:)`` to enable it.
/// ///
/// The title will be shown centered or left-aligned depending on available /// The title will be shown centered or left-aligned depending on available
/// space. /// space.
/// ///
/// Banners can optionally have a button with text on it, set through /// Banners can optionally have a button with text on it, set through
/// [property@Banner:button-label]. The button can be used with a `GAction`, /// ``buttonLabel(_:)``. The button can be used with a `GAction`,
/// or with the [signal@Banner::button-clicked] signal. /// or with the `Banner::button-clicked` signal. The button can have
/// different styles, a gray style and a suggested style.
///
///
/// ///
/// ## CSS nodes
/// ///
/// `AdwBanner` has a main CSS node with the name `banner`.
public struct Banner: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The label to show on the button. /// The label to show on the button.
/// ///
/// If set to `""` or `NULL`, the button won't be shown. /// If set to `""` or `NULL`, the button won't be shown.
/// ///
/// The button can be used with a `GAction`, or with the /// The button can be used with a `GAction`, or with the
/// [signal@Banner::button-clicked] signal. /// `Banner::button-clicked` signal.
var buttonLabel: String? var buttonLabel: String?
/// Whether the banner is currently revealed. /// Whether the banner is currently revealed.
var revealed: Bool? var revealed: Bool?
/// The title for this banner. /// The title for this banner.
/// ///
/// See also: [property@Banner:use-markup]. /// See also: ``useMarkup(_:)``.
var title: String var title: String
/// Whether to use Pango markup for the banner title. /// Whether to use Pango markup for the banner title.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
var useMarkup: Bool? var useMarkup: Bool?
/// This signal is emitted after the action button has been clicked. /// This signal is emitted after the action button has been clicked.
/// ///
@ -71,7 +79,6 @@ public struct Banner: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -104,6 +111,7 @@ public struct Banner: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -118,40 +126,28 @@ public struct Banner: AdwaitaWidget {
/// If set to `""` or `NULL`, the button won't be shown. /// If set to `""` or `NULL`, the button won't be shown.
/// ///
/// The button can be used with a `GAction`, or with the /// The button can be used with a `GAction`, or with the
/// [signal@Banner::button-clicked] signal. /// `Banner::button-clicked` signal.
public func buttonLabel(_ buttonLabel: String?) -> Self { public func buttonLabel(_ buttonLabel: String?) -> Self {
var newSelf = self modify { $0.buttonLabel = buttonLabel }
newSelf.buttonLabel = buttonLabel
return newSelf
} }
/// Whether the banner is currently revealed. /// Whether the banner is currently revealed.
public func revealed(_ revealed: Bool? = true) -> Self { public func revealed(_ revealed: Bool? = true) -> Self {
var newSelf = self modify { $0.revealed = revealed }
newSelf.revealed = revealed
return newSelf
} }
/// The title for this banner. /// The title for this banner.
/// ///
/// See also: [property@Banner:use-markup]. /// See also: ``useMarkup(_:)``.
public func title(_ title: String) -> Self { public func title(_ title: String) -> Self {
var newSelf = self modify { $0.title = title }
newSelf.title = title
return newSelf
} }
/// Whether to use Pango markup for the banner title. /// Whether to use Pango markup for the banner title.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
public func useMarkup(_ useMarkup: Bool? = true) -> Self { public func useMarkup(_ useMarkup: Bool? = true) -> Self {
var newSelf = self modify { $0.useMarkup = useMarkup }
newSelf.useMarkup = useMarkup
return newSelf
} }
/// This signal is emitted after the action button has been clicked. /// This signal is emitted after the action button has been clicked.

View File

@ -2,7 +2,7 @@
// Bin.swift // Bin.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,22 +10,29 @@ import LevenshteinTransformations
/// A widget with one child. /// A widget with one child.
/// ///
/// <picture><source srcset="bin-dark.png" media="(prefers-color-scheme: dark)"><img src="bin.png" alt="bin"></picture>
/// ///
/// The `AdwBin` widget has only one child, set with the [property@Bin:child] ///
/// The `AdwBin` widget has only one child, set with the ``child(_:)``
/// property. /// property.
/// ///
/// It is useful for deriving subclasses, since it provides common code needed /// It is useful for deriving subclasses, since it provides common code needed
/// for handling a single child widget. /// for handling a single child widget.
public struct Bin: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The child widget of the `AdwBin`. /// The child widget of the `AdwBin`.
var child: (() -> Body)? var child: Body?
/// Initialize `Bin`. /// Initialize `Bin`.
public init() { public init() {
@ -41,8 +48,7 @@ public struct Bin: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let childStorage = child?.storage(data: data, type: type) {
if let childStorage = child?().storage(data: data, type: type) {
storage.content["child"] = [childStorage] storage.content["child"] = [childStorage]
adw_bin_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast()) adw_bin_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())
} }
@ -60,10 +66,11 @@ public struct Bin: AdwaitaWidget {
storage.modify { widget in storage.modify { widget in
if let widget = storage.content["child"]?.first { if let widget = storage.content["child"]?.first {
child?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) child?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -74,11 +81,8 @@ public struct Bin: AdwaitaWidget {
} }
/// The child widget of the `AdwBin`. /// The child widget of the `AdwBin`.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self { public func child(@ViewBuilder _ child: () -> Body) -> Self {
var newSelf = self modify { $0.child = child() }
newSelf.child = child
return newSelf
} }
} }

View File

@ -2,58 +2,59 @@
// Box.swift // Box.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// The `GtkBox` widget arranges child widgets into a single row or column. /// Arranges child widgets into a single row or column.
///
/// ///
/// ![An example GtkBox](box.png)
/// ///
/// Whether it is a row or column depends on the value of its /// Whether it is a row or column depends on the value of its
/// [property@Gtk.Orientable:orientation] property. Within the other /// ``orientation(_:)`` property. Within the other
/// dimension, all children are allocated the same size. Of course, the /// dimension, all children are allocated the same size. The
/// [property@Gtk.Widget:halign] and [property@Gtk.Widget:valign] properties /// ``halign(_:)`` and ``valign(_:)``
/// can be used on the children to influence their allocation. /// properties can be used on the children to influence their allocation.
/// ///
/// Use repeated calls to [method@Gtk.Box.append] to pack widgets into a /// Use repeated calls to `Gtk.Box.append` to pack widgets into a
/// `GtkBox` from start to end. Use [method@Gtk.Box.remove] to remove widgets /// `GtkBox` from start to end. Use `Gtk.Box.remove` to remove widgets
/// from the `GtkBox`. [method@Gtk.Box.insert_child_after] can be used to add /// from the `GtkBox`. `Gtk.Box.insert_child_after` can be used to add
/// a child at a particular position. /// a child at a particular position.
/// ///
/// Use [method@Gtk.Box.set_homogeneous] to specify whether or not all children /// Use `Gtk.Box.set_homogeneous` to specify whether or not all children
/// of the `GtkBox` are forced to get the same amount of space. /// of the `GtkBox` are forced to get the same amount of space.
/// ///
/// Use [method@Gtk.Box.set_spacing] to determine how much space will be minimally /// Use `Gtk.Box.set_spacing` to determine how much space will be minimally
/// placed between all children in the `GtkBox`. Note that spacing is added /// placed between all children in the `GtkBox`. Note that spacing is added
/// *between* the children. /// *between* the children.
/// ///
/// Use [method@Gtk.Box.reorder_child_after] to move a child to a different /// Use `Gtk.Box.reorder_child_after` to move a child to a different
/// place in the box. /// place in the box.
/// ///
/// # CSS nodes
/// ///
/// `GtkBox` uses a single CSS node with name box.
///
/// # Accessibility
///
/// Until GTK 4.10, `GtkBox` used the `GTK_ACCESSIBLE_ROLE_GROUP` role.
///
/// Starting from GTK 4.12, `GtkBox` uses the `GTK_ACCESSIBLE_ROLE_GENERIC` role.
public struct Box: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
var accessibleRole: String? var accessibleRole: String?
/// The child that determines the baseline, in vertical orientation. /// The position of the child that determines the baseline.
///
/// This is only relevant if the box is in vertical orientation.
var baselineChild: Int? var baselineChild: Int?
/// Whether the children should all be the same size. /// Whether the children should all be the same size.
var homogeneous: Bool? var homogeneous: Bool?
@ -65,7 +66,7 @@ public struct Box: AdwaitaWidget {
var prepend: () -> Body = { [] } var prepend: () -> Body = { [] }
/// Initialize `Box`. /// Initialize `Box`.
public init(spacing: Int) { init(spacing: Int) {
self.spacing = spacing self.spacing = spacing
} }
@ -79,7 +80,6 @@ public struct Box: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
var appendStorage: [ViewStorage] = [] var appendStorage: [ViewStorage] = []
for view in append() { for view in append() {
@ -140,6 +140,7 @@ public struct Box: AdwaitaWidget {
} }
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -153,34 +154,24 @@ public struct Box: AdwaitaWidget {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// The child that determines the baseline, in vertical orientation. /// The position of the child that determines the baseline.
///
/// This is only relevant if the box is in vertical orientation.
public func baselineChild(_ baselineChild: Int?) -> Self { public func baselineChild(_ baselineChild: Int?) -> Self {
var newSelf = self modify { $0.baselineChild = baselineChild }
newSelf.baselineChild = baselineChild
return newSelf
} }
/// Whether the children should all be the same size. /// Whether the children should all be the same size.
public func homogeneous(_ homogeneous: Bool? = true) -> Self { public func homogeneous(_ homogeneous: Bool? = true) -> Self {
var newSelf = self modify { $0.homogeneous = homogeneous }
newSelf.homogeneous = homogeneous
return newSelf
} }
/// The amount of space between children. /// The amount of space between children.
public func spacing(_ spacing: Int) -> Self { public func spacing(_ spacing: Int) -> Self {
var newSelf = self modify { $0.spacing = spacing }
newSelf.spacing = spacing
return newSelf
} }
/// Set the body for "append". /// Set the body for "append".

View File

@ -2,54 +2,40 @@
// Button.swift // Button.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// The `GtkButton` widget is generally used to trigger a callback function that is /// Calls a callback function when the button is clicked.
/// called when the button is pressed. ///
/// ///
/// ![An example GtkButton](button.png)
/// ///
/// The `GtkButton` widget can hold any valid child widget. That is, it can hold /// The `GtkButton` widget can hold any valid child widget. That is, it can hold
/// almost any other standard `GtkWidget`. The most commonly used child is the /// almost any other standard `GtkWidget`. The most commonly used child is the
/// `GtkLabel`. /// `GtkLabel`.
/// ///
/// # CSS nodes
/// ///
/// `GtkButton` has a single CSS node with name button. The node will get the
/// style classes .image-button or .text-button, if the content is just an
/// image or label, respectively. It may also receive the .flat style class.
/// When activating a button via the keyboard, the button will temporarily
/// gain the .keyboard-activating style class.
///
/// Other style classes that are commonly used with `GtkButton` include
/// .suggested-action and .destructive-action. In special cases, buttons
/// can be made round by adding the .circular style class.
///
/// Button-like widgets like [class@Gtk.ToggleButton], [class@Gtk.MenuButton],
/// [class@Gtk.VolumeButton], [class@Gtk.LockButton], [class@Gtk.ColorButton]
/// or [class@Gtk.FontButton] use style classes such as .toggle, .popup, .scale,
/// .lock, .color on the button node to differentiate themselves from a plain
/// `GtkButton`.
///
/// # Accessibility
///
/// `GtkButton` uses the %GTK_ACCESSIBLE_ROLE_BUTTON role.
public struct Button: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
var accessibleRole: String? var accessibleRole: String?
/// action-name /// The name of the action with which this widget should be associated.
var actionName: String? var actionName: String?
/// Whether the size of the button can be made smaller than the natural /// Whether the size of the button can be made smaller than the natural
/// size of its contents. /// size of its contents.
@ -60,7 +46,7 @@ public struct Button: AdwaitaWidget {
/// property has no effect. /// property has no effect.
var canShrink: Bool? var canShrink: Bool?
/// The child widget. /// The child widget.
var child: (() -> Body)? var child: Body?
/// Whether the button has a frame. /// Whether the button has a frame.
var hasFrame: Bool? var hasFrame: Bool?
/// The name of the icon used to automatically populate the button. /// The name of the icon used to automatically populate the button.
@ -73,7 +59,7 @@ public struct Button: AdwaitaWidget {
/// Emitted to animate press then release. /// Emitted to animate press then release.
/// ///
/// This is an action signal. Applications should never connect /// This is an action signal. Applications should never connect
/// to this signal, but use the [signal@Gtk.Button::clicked] signal. /// to this signal, but use the `Gtk.Button::clicked` signal.
/// ///
/// The default bindings for this signal are all forms of the /// The default bindings for this signal are all forms of the
/// <kbd></kbd> and <kbd>Enter</kbd> keys. /// <kbd></kbd> and <kbd>Enter</kbd> keys.
@ -82,7 +68,7 @@ public struct Button: AdwaitaWidget {
var clicked: (() -> Void)? var clicked: (() -> Void)?
/// Initialize `Button`. /// Initialize `Button`.
public init() { init() {
} }
/// The view storage. /// The view storage.
@ -95,8 +81,7 @@ public struct Button: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let childStorage = child?.storage(data: data, type: type) {
if let childStorage = child?().storage(data: data, type: type) {
storage.content["child"] = [childStorage] storage.content["child"] = [childStorage]
gtk_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast()) gtk_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())
} }
@ -130,7 +115,7 @@ public struct Button: AdwaitaWidget {
gtk_button_set_can_shrink(widget?.cast(), canShrink.cBool) gtk_button_set_can_shrink(widget?.cast(), canShrink.cBool)
} }
if let widget = storage.content["child"]?.first { if let widget = storage.content["child"]?.first {
child?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) child?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let hasFrame, updateProperties, (storage.previousState as? Self)?.hasFrame != hasFrame { if let hasFrame, updateProperties, (storage.previousState as? Self)?.hasFrame != hasFrame {
gtk_button_set_has_frame(widget?.cast(), hasFrame.cBool) gtk_button_set_has_frame(widget?.cast(), hasFrame.cBool)
@ -146,6 +131,7 @@ public struct Button: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -159,18 +145,12 @@ public struct Button: AdwaitaWidget {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// action-name /// The name of the action with which this widget should be associated.
public func actionName(_ actionName: String?) -> Self { public func actionName(_ actionName: String?) -> Self {
var newSelf = self modify { $0.actionName = actionName }
newSelf.actionName = actionName
return newSelf
} }
/// Whether the size of the button can be made smaller than the natural /// Whether the size of the button can be made smaller than the natural
@ -181,57 +161,39 @@ public struct Button: AdwaitaWidget {
/// If the contents of a button are an icon or a custom widget, setting this /// If the contents of a button are an icon or a custom widget, setting this
/// property has no effect. /// property has no effect.
public func canShrink(_ canShrink: Bool? = true) -> Self { public func canShrink(_ canShrink: Bool? = true) -> Self {
var newSelf = self modify { $0.canShrink = canShrink }
newSelf.canShrink = canShrink
return newSelf
} }
/// The child widget. /// The child widget.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self { public func child(@ViewBuilder _ child: () -> Body) -> Self {
var newSelf = self modify { $0.child = child() }
newSelf.child = child
return newSelf
} }
/// Whether the button has a frame. /// Whether the button has a frame.
public func hasFrame(_ hasFrame: Bool? = true) -> Self { public func hasFrame(_ hasFrame: Bool? = true) -> Self {
var newSelf = self modify { $0.hasFrame = hasFrame }
newSelf.hasFrame = hasFrame
return newSelf
} }
/// The name of the icon used to automatically populate the button. /// The name of the icon used to automatically populate the button.
public func iconName(_ iconName: String?) -> Self { public func iconName(_ iconName: String?) -> Self {
var newSelf = self modify { $0.iconName = iconName }
newSelf.iconName = iconName
return newSelf
} }
/// Text of the label inside the button, if the button contains a label widget. /// Text of the label inside the button, if the button contains a label widget.
public func label(_ label: String?) -> Self { public func label(_ label: String?) -> Self {
var newSelf = self modify { $0.label = label }
newSelf.label = label
return newSelf
} }
/// If set, an underline in the text indicates that the following character is /// If set, an underline in the text indicates that the following character is
/// to be used as mnemonic. /// to be used as mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// Emitted to animate press then release. /// Emitted to animate press then release.
/// ///
/// This is an action signal. Applications should never connect /// This is an action signal. Applications should never connect
/// to this signal, but use the [signal@Gtk.Button::clicked] signal. /// to this signal, but use the `Gtk.Button::clicked` signal.
/// ///
/// The default bindings for this signal are all forms of the /// The default bindings for this signal are all forms of the
/// <kbd></kbd> and <kbd>Enter</kbd> keys. /// <kbd></kbd> and <kbd>Enter</kbd> keys.

View File

@ -2,7 +2,7 @@
// ButtonContent.swift // ButtonContent.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,12 +10,12 @@ import LevenshteinTransformations
/// A helper widget for creating buttons. /// A helper widget for creating buttons.
/// ///
/// <picture><source srcset="button-content-dark.png" media="(prefers-color-scheme: dark)"><img src="button-content.png" alt="button-content"></picture> ///
/// ///
/// `AdwButtonContent` is a box-like widget with an icon and a label. /// `AdwButtonContent` is a box-like widget with an icon and a label.
/// ///
/// It's intended to be used as a direct child of [class@Gtk.Button], /// It's intended to be used as a direct child of `Gtk.Button`,
/// [class@Gtk.MenuButton] or [class@SplitButton], when they need to have both an /// `Gtk.MenuButton` or `SplitButton`, when they need to have both an
/// icon and a label, as follows: /// icon and a label, as follows:
/// ///
/// ```xml /// ```xml
@ -25,37 +25,26 @@ import LevenshteinTransformations
/// `AdwButtonContent` handles style classes and connecting the mnemonic to the /// `AdwButtonContent` handles style classes and connecting the mnemonic to the
/// button automatically. /// button automatically.
/// ///
/// ## CSS nodes
/// ///
/// ```
/// buttoncontent
/// box
/// image
/// label
/// ```
///
/// `AdwButtonContent`'s CSS node is called `buttoncontent`. It contains a `box`
/// subnode that serves as a container for the `image` and `label` nodes.
///
/// When inside a `GtkButton` or `AdwSplitButton`, the button will receive the
/// `.image-text-button` style class. When inside a `GtkMenuButton`, the
/// internal `GtkButton` will receive it instead.
///
/// ## Accessibility
///
/// `AdwButtonContent` uses the `GTK_ACCESSIBLE_ROLE_GROUP` role.
public struct ButtonContent: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether the button can be smaller than the natural size of its contents. /// Whether the button can be smaller than the natural size of its contents.
/// ///
/// If set to `TRUE`, the label will ellipsize. /// If set to `true`, the label will ellipsize.
/// ///
/// See [property@Gtk.Button:can-shrink]. /// See ``canShrink(_:)``.
var canShrink: Bool? var canShrink: Bool?
/// The name of the displayed icon. /// The name of the displayed icon.
/// ///
@ -67,7 +56,7 @@ public struct ButtonContent: AdwaitaWidget {
/// ///
/// The mnemonic can be used to activate the parent button. /// The mnemonic can be used to activate the parent button.
/// ///
/// See [property@ButtonContent:label]. /// See ``label(_:)``.
var useUnderline: Bool? var useUnderline: Bool?
/// Initialize `ButtonContent`. /// Initialize `ButtonContent`.
@ -84,7 +73,6 @@ public struct ButtonContent: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -112,6 +100,7 @@ public struct ButtonContent: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -123,44 +112,32 @@ public struct ButtonContent: AdwaitaWidget {
/// Whether the button can be smaller than the natural size of its contents. /// Whether the button can be smaller than the natural size of its contents.
/// ///
/// If set to `TRUE`, the label will ellipsize. /// If set to `true`, the label will ellipsize.
/// ///
/// See [property@Gtk.Button:can-shrink]. /// See ``canShrink(_:)``.
public func canShrink(_ canShrink: Bool? = true) -> Self { public func canShrink(_ canShrink: Bool? = true) -> Self {
var newSelf = self modify { $0.canShrink = canShrink }
newSelf.canShrink = canShrink
return newSelf
} }
/// The name of the displayed icon. /// The name of the displayed icon.
/// ///
/// If empty, the icon is not shown. /// If empty, the icon is not shown.
public func iconName(_ iconName: String?) -> Self { public func iconName(_ iconName: String?) -> Self {
var newSelf = self modify { $0.iconName = iconName }
newSelf.iconName = iconName
return newSelf
} }
/// The displayed label. /// The displayed label.
public func label(_ label: String?) -> Self { public func label(_ label: String?) -> Self {
var newSelf = self modify { $0.label = label }
newSelf.label = label
return newSelf
} }
/// Whether an underline in the text indicates a mnemonic. /// Whether an underline in the text indicates a mnemonic.
/// ///
/// The mnemonic can be used to activate the parent button. /// The mnemonic can be used to activate the parent button.
/// ///
/// See [property@ButtonContent:label]. /// See ``label(_:)``.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
} }

View File

@ -2,7 +2,7 @@
// Carousel.swift // Carousel.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,35 +10,40 @@ import LevenshteinTransformations
/// A paginated scrolling widget. /// A paginated scrolling widget.
/// ///
/// <picture><source srcset="carousel-dark.png" media="(prefers-color-scheme: dark)"><img src="carousel.png" alt="carousel"></picture> ///
/// ///
/// The `AdwCarousel` widget can be used to display a set of pages with /// The `AdwCarousel` widget can be used to display a set of pages with
/// swipe-based navigation between them. /// swipe-based navigation between them.
/// ///
/// [class@CarouselIndicatorDots] and [class@CarouselIndicatorLines] can be used /// `CarouselIndicatorDots` and `CarouselIndicatorLines` can be used
/// to provide page indicators for `AdwCarousel`. /// to provide page indicators for `AdwCarousel`.
/// ///
/// ## CSS nodes
/// ///
/// `AdwCarousel` has a single CSS node with name `carousel`. public struct Carousel<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
#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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether to allow swiping for more than one page at a time. /// Whether to allow swiping for more than one page at a time.
/// ///
/// If the value is `FALSE`, each swipe can only move to the adjacent pages. /// If the value is `false`, each swipe can only move to the adjacent pages.
var allowLongSwipes: Bool? var allowLongSwipes: Bool?
/// Sets whether the `AdwCarousel` can be dragged with mouse pointer. /// Sets whether the `AdwCarousel` can be dragged with mouse pointer.
/// ///
/// If the value is `FALSE`, dragging is only available on touch. /// If the value is `false`, dragging is only available on touch.
var allowMouseDrag: Bool? var allowMouseDrag: Bool?
/// Whether the widget will respond to scroll wheel events. /// Whether the widget will respond to scroll wheel events.
/// ///
/// If the value is `FALSE`, wheel events will be ignored. /// If the value is `false`, wheel events will be ignored.
var allowScrollWheel: Bool? var allowScrollWheel: Bool?
/// Whether the carousel can be navigated. /// Whether the carousel can be navigated.
/// ///
@ -58,18 +63,21 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
/// It can be used to implement "infinite scrolling" by amending the pages /// It can be used to implement "infinite scrolling" by amending the pages
/// after every scroll. /// after every scroll.
/// ///
/// ::: note /// > [!NOTE]
/// An empty carousel is indicated by `(int)index == -1`. /// > An empty carousel is indicated by `(int)index == -1`.
var pageChanged: (() -> Void)? var pageChanged: (() -> Void)?
/// The dynamic widget elements. /// The dynamic widget elements.
var elements: [Element] var elements: [Element]
/// The dynamic widget content. /// The dynamic widget content.
var content: (Element) -> Body var content: (Element) -> Body
/// The dynamic widget identifier key path.
var id: KeyPath<Element, Identifier>
/// Initialize `Carousel`. /// 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.elements = elements
self.content = content self.content = content
self.id = id
} }
/// The view storage. /// The view storage.
@ -82,7 +90,6 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -122,15 +129,10 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? [] var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? [] let old = storage.fields["element"] as? [Element] ?? []
old.identifiableTransform( old.transform(
to: elements, to: elements,
functions: .init { index, element in id: id,
let child = content(element).storage(data: data, type: type) functions: .init { index in
adw_carousel_remove(widget, adw_carousel_get_nth_page(widget, UInt(index).cInt))
adw_carousel_insert(widget, child.opaquePointer?.cast(), index.cInt)
contentStorage.remove(at: index)
contentStorage.insert(child, at: index)
} delete: { index in
adw_carousel_remove(widget, adw_carousel_get_nth_page(widget, UInt(index).cInt)) adw_carousel_remove(widget, adw_carousel_get_nth_page(widget, UInt(index).cInt))
contentStorage.remove(at: index) contentStorage.remove(at: index)
} insert: { index, element in } insert: { index, element in
@ -144,6 +146,7 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
for (index, element) in elements.enumerated() { for (index, element) in elements.enumerated() {
content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type) content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type)
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -155,32 +158,23 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
/// Whether to allow swiping for more than one page at a time. /// Whether to allow swiping for more than one page at a time.
/// ///
/// If the value is `FALSE`, each swipe can only move to the adjacent pages. /// If the value is `false`, each swipe can only move to the adjacent pages.
public func allowLongSwipes(_ allowLongSwipes: Bool? = true) -> Self { public func allowLongSwipes(_ allowLongSwipes: Bool? = true) -> Self {
var newSelf = self modify { $0.allowLongSwipes = allowLongSwipes }
newSelf.allowLongSwipes = allowLongSwipes
return newSelf
} }
/// Sets whether the `AdwCarousel` can be dragged with mouse pointer. /// Sets whether the `AdwCarousel` can be dragged with mouse pointer.
/// ///
/// If the value is `FALSE`, dragging is only available on touch. /// If the value is `false`, dragging is only available on touch.
public func allowMouseDrag(_ allowMouseDrag: Bool? = true) -> Self { public func allowMouseDrag(_ allowMouseDrag: Bool? = true) -> Self {
var newSelf = self modify { $0.allowMouseDrag = allowMouseDrag }
newSelf.allowMouseDrag = allowMouseDrag
return newSelf
} }
/// Whether the widget will respond to scroll wheel events. /// Whether the widget will respond to scroll wheel events.
/// ///
/// If the value is `FALSE`, wheel events will be ignored. /// If the value is `false`, wheel events will be ignored.
public func allowScrollWheel(_ allowScrollWheel: Bool? = true) -> Self { public func allowScrollWheel(_ allowScrollWheel: Bool? = true) -> Self {
var newSelf = self modify { $0.allowScrollWheel = allowScrollWheel }
newSelf.allowScrollWheel = allowScrollWheel
return newSelf
} }
/// Whether the carousel can be navigated. /// Whether the carousel can be navigated.
@ -188,36 +182,24 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
/// This can be used to temporarily disable the carousel to only allow /// This can be used to temporarily disable the carousel to only allow
/// navigating it in a certain state. /// navigating it in a certain state.
public func interactive(_ interactive: Bool? = true) -> Self { public func interactive(_ interactive: Bool? = true) -> Self {
var newSelf = self modify { $0.interactive = interactive }
newSelf.interactive = interactive
return newSelf
} }
/// The number of pages in a `AdwCarousel`. /// The number of pages in a `AdwCarousel`.
public func nPages(_ nPages: UInt?) -> Self { public func nPages(_ nPages: UInt?) -> Self {
var newSelf = self modify { $0.nPages = nPages }
newSelf.nPages = nPages
return newSelf
} }
/// Page reveal duration, in milliseconds. /// Page reveal duration, in milliseconds.
/// ///
/// Reveal duration is used when animating adding or removing pages. /// Reveal duration is used when animating adding or removing pages.
public func revealDuration(_ revealDuration: UInt?) -> Self { public func revealDuration(_ revealDuration: UInt?) -> Self {
var newSelf = self modify { $0.revealDuration = revealDuration }
newSelf.revealDuration = revealDuration
return newSelf
} }
/// Spacing between pages in pixels. /// Spacing between pages in pixels.
public func spacing(_ spacing: UInt?) -> Self { public func spacing(_ spacing: UInt?) -> Self {
var newSelf = self modify { $0.spacing = spacing }
newSelf.spacing = spacing
return newSelf
} }
/// This signal is emitted after a page has been changed. /// This signal is emitted after a page has been changed.
@ -225,8 +207,8 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
/// It can be used to implement "infinite scrolling" by amending the pages /// It can be used to implement "infinite scrolling" by amending the pages
/// after every scroll. /// after every scroll.
/// ///
/// ::: note /// > [!NOTE]
/// An empty carousel is indicated by `(int)index == -1`. /// > An empty carousel is indicated by `(int)index == -1`.
public func pageChanged(_ pageChanged: @escaping () -> Void) -> Self { public func pageChanged(_ pageChanged: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.pageChanged = pageChanged newSelf.pageChanged = pageChanged
@ -234,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,80 +2,66 @@
// CenterBox.swift // CenterBox.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// `GtkCenterBox` arranges three children in a row, keeping the middle child /// Arranges three children in a row, keeping the middle child
/// centered as well as possible. /// centered as well as possible.
/// ///
/// ![An example GtkCenterBox](centerbox.png)
/// ///
/// To add children to `GtkCenterBox`, use [method@Gtk.CenterBox.set_start_widget], ///
/// [method@Gtk.CenterBox.set_center_widget] and /// To add children to `GtkCenterBox`, use `Gtk.CenterBox.set_start_widget`,
/// [method@Gtk.CenterBox.set_end_widget]. /// `Gtk.CenterBox.set_center_widget` and
/// `Gtk.CenterBox.set_end_widget`.
/// ///
/// The sizing and positioning of children can be influenced with the /// The sizing and positioning of children can be influenced with the
/// align and expand properties of the children. /// align and expand properties of the children.
/// ///
/// # GtkCenterBox as GtkBuildable
/// ///
/// The `GtkCenterBox` implementation of the `GtkBuildable` interface
/// supports placing children in the 3 positions by specifying start, center
/// or end as the type attribute of a `<child>` element.
///
/// # CSS nodes
///
/// `GtkCenterBox` uses a single CSS node with the name box,
///
/// The first child of the `GtkCenterBox` will be allocated depending on the
/// text direction, i.e. in left-to-right layouts it will be allocated on the
/// left and in right-to-left layouts on the right.
///
/// In vertical orientation, the nodes of the children are arranged from top to
/// bottom.
///
/// # Accessibility
///
/// Until GTK 4.10, `GtkCenterBox` used the `GTK_ACCESSIBLE_ROLE_GROUP` role.
///
/// Starting from GTK 4.12, `GtkCenterBox` uses the `GTK_ACCESSIBLE_ROLE_GENERIC` role.
public struct CenterBox: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
var accessibleRole: String? var accessibleRole: String?
/// The widget that is placed at the center position. /// The widget that is placed at the center position.
var centerWidget: (() -> Body)? var centerWidget: Body?
/// The widget that is placed at the end position. /// The widget that is placed at the end position.
/// ///
/// In vertical orientation, the end position is at the bottom. /// In vertical orientation, the end position is at the bottom.
/// In horizontal orientation, the end position is at the trailing /// In horizontal orientation, the end position is at the trailing
/// edge wrt. to the text direction. /// edge with respect to the text direction.
var endWidget: (() -> Body)? var endWidget: Body?
/// Whether to shrink the center widget after other children. /// Whether to shrink the center widget after other children.
/// ///
/// By default, when there's no space to give all three children their /// By default, when there's no space to give all three children their
/// natural widths, the start and end widgets start shrinking and the /// natural widths, the start and end widgets start shrinking and the
/// center child keeps natural width until they reach minimum width. /// center child keeps natural width until they reach minimum width.
/// ///
/// If set to `FALSE`, start and end widgets keep natural width and the /// If false, start and end widgets keep natural width and the
/// center widget starts shrinking instead. /// center widget starts shrinking instead.
var shrinkCenterLast: Bool? var shrinkCenterLast: Bool?
/// The widget that is placed at the start position. /// The widget that is placed at the start position.
/// ///
/// In vertical orientation, the start position is at the top. /// In vertical orientation, the start position is at the top.
/// In horizontal orientation, the start position is at the leading /// In horizontal orientation, the start position is at the leading
/// edge wrt. to the text direction. /// edge with respect to the text direction.
var startWidget: (() -> Body)? var startWidget: Body?
/// Initialize `CenterBox`. /// Initialize `CenterBox`.
public init() { public init() {
@ -91,16 +77,15 @@ public struct CenterBox: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let centerWidgetStorage = centerWidget?.storage(data: data, type: type) {
if let centerWidgetStorage = centerWidget?().storage(data: data, type: type) {
storage.content["centerWidget"] = [centerWidgetStorage] storage.content["centerWidget"] = [centerWidgetStorage]
gtk_center_box_set_center_widget(storage.opaquePointer, centerWidgetStorage.opaquePointer?.cast()) gtk_center_box_set_center_widget(storage.opaquePointer, centerWidgetStorage.opaquePointer?.cast())
} }
if let endWidgetStorage = endWidget?().storage(data: data, type: type) { if let endWidgetStorage = endWidget?.storage(data: data, type: type) {
storage.content["endWidget"] = [endWidgetStorage] storage.content["endWidget"] = [endWidgetStorage]
gtk_center_box_set_end_widget(storage.opaquePointer, endWidgetStorage.opaquePointer?.cast()) gtk_center_box_set_end_widget(storage.opaquePointer, endWidgetStorage.opaquePointer?.cast())
} }
if let startWidgetStorage = startWidget?().storage(data: data, type: type) { if let startWidgetStorage = startWidget?.storage(data: data, type: type) {
storage.content["startWidget"] = [startWidgetStorage] storage.content["startWidget"] = [startWidgetStorage]
gtk_center_box_set_start_widget(storage.opaquePointer, startWidgetStorage.opaquePointer?.cast()) gtk_center_box_set_start_widget(storage.opaquePointer, startWidgetStorage.opaquePointer?.cast())
} }
@ -118,19 +103,20 @@ public struct CenterBox: AdwaitaWidget {
storage.modify { widget in storage.modify { widget in
if let widget = storage.content["centerWidget"]?.first { if let widget = storage.content["centerWidget"]?.first {
centerWidget?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) centerWidget?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let widget = storage.content["endWidget"]?.first { if let widget = storage.content["endWidget"]?.first {
endWidget?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) endWidget?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let shrinkCenterLast, updateProperties, (storage.previousState as? Self)?.shrinkCenterLast != shrinkCenterLast { if let shrinkCenterLast, updateProperties, (storage.previousState as? Self)?.shrinkCenterLast != shrinkCenterLast {
gtk_center_box_set_shrink_center_last(widget, shrinkCenterLast.cBool) gtk_center_box_set_shrink_center_last(widget, shrinkCenterLast.cBool)
} }
if let widget = storage.content["startWidget"]?.first { if let widget = storage.content["startWidget"]?.first {
startWidget?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) startWidget?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -144,30 +130,21 @@ public struct CenterBox: AdwaitaWidget {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// The widget that is placed at the center position. /// The widget that is placed at the center position.
public func centerWidget(@ViewBuilder _ centerWidget: @escaping (() -> Body)) -> Self { public func centerWidget(@ViewBuilder _ centerWidget: () -> Body) -> Self {
var newSelf = self modify { $0.centerWidget = centerWidget() }
newSelf.centerWidget = centerWidget
return newSelf
} }
/// The widget that is placed at the end position. /// The widget that is placed at the end position.
/// ///
/// In vertical orientation, the end position is at the bottom. /// In vertical orientation, the end position is at the bottom.
/// In horizontal orientation, the end position is at the trailing /// In horizontal orientation, the end position is at the trailing
/// edge wrt. to the text direction. /// edge with respect to the text direction.
public func endWidget(@ViewBuilder _ endWidget: @escaping (() -> Body)) -> Self { public func endWidget(@ViewBuilder _ endWidget: () -> Body) -> Self {
var newSelf = self modify { $0.endWidget = endWidget() }
newSelf.endWidget = endWidget
return newSelf
} }
/// Whether to shrink the center widget after other children. /// Whether to shrink the center widget after other children.
@ -176,25 +153,19 @@ public struct CenterBox: AdwaitaWidget {
/// natural widths, the start and end widgets start shrinking and the /// natural widths, the start and end widgets start shrinking and the
/// center child keeps natural width until they reach minimum width. /// center child keeps natural width until they reach minimum width.
/// ///
/// If set to `FALSE`, start and end widgets keep natural width and the /// If false, start and end widgets keep natural width and the
/// center widget starts shrinking instead. /// center widget starts shrinking instead.
public func shrinkCenterLast(_ shrinkCenterLast: Bool? = true) -> Self { public func shrinkCenterLast(_ shrinkCenterLast: Bool? = true) -> Self {
var newSelf = self modify { $0.shrinkCenterLast = shrinkCenterLast }
newSelf.shrinkCenterLast = shrinkCenterLast
return newSelf
} }
/// The widget that is placed at the start position. /// The widget that is placed at the start position.
/// ///
/// In vertical orientation, the start position is at the top. /// In vertical orientation, the start position is at the top.
/// In horizontal orientation, the start position is at the leading /// In horizontal orientation, the start position is at the leading
/// edge wrt. to the text direction. /// edge with respect to the text direction.
public func startWidget(@ViewBuilder _ startWidget: @escaping (() -> Body)) -> Self { public func startWidget(@ViewBuilder _ startWidget: () -> Body) -> Self {
var newSelf = self modify { $0.startWidget = startWidget() }
newSelf.startWidget = startWidget
return newSelf
} }
} }

View File

@ -2,89 +2,51 @@
// CheckButton.swift // CheckButton.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A `GtkCheckButton` places a label next to an indicator. /// Places a label next to an indicator.
/// ///
/// ![Example GtkCheckButtons](check-button.png)
/// ///
/// A `GtkCheckButton` is created by calling either [ctor@Gtk.CheckButton.new] ///
/// or [ctor@Gtk.CheckButton.new_with_label]. /// A `GtkCheckButton` is created by calling either `Gtk.CheckButton.new`
/// or `Gtk.CheckButton.new_with_label`.
/// ///
/// The state of a `GtkCheckButton` can be set specifically using /// The state of a `GtkCheckButton` can be set specifically using
/// [method@Gtk.CheckButton.set_active], and retrieved using /// `Gtk.CheckButton.set_active`, and retrieved using
/// [method@Gtk.CheckButton.get_active]. /// `Gtk.CheckButton.get_active`.
/// ///
/// # Inconsistent state
/// ///
/// In addition to "on" and "off", check buttons can be an
/// "in between" state that is neither on nor off. This can be used
/// e.g. when the user has selected a range of elements (such as some
/// text or spreadsheet cells) that are affected by a check button,
/// and the current values in that range are inconsistent.
///
/// To set a `GtkCheckButton` to inconsistent state, use
/// [method@Gtk.CheckButton.set_inconsistent].
///
/// # Grouping
///
/// Check buttons can be grouped together, to form mutually exclusive
/// groups - only one of the buttons can be toggled at a time, and toggling
/// another one will switch the currently toggled one off.
///
/// Grouped check buttons use a different indicator, and are commonly referred
/// to as *radio buttons*.
///
/// ![Example GtkCheckButtons](radio-button.png)
///
/// To add a `GtkCheckButton` to a group, use [method@Gtk.CheckButton.set_group].
///
/// When the code must keep track of the state of a group of radio buttons, it
/// is recommended to keep track of such state through a stateful
/// `GAction` with a target for each button. Using the `toggled` signals to keep
/// track of the group changes and state is discouraged.
///
/// # CSS nodes
///
/// ```
/// checkbutton[.text-button]
/// check
/// [label]
/// ```
///
/// A `GtkCheckButton` has a main node with name checkbutton. If the
/// [property@Gtk.CheckButton:label] or [property@Gtk.CheckButton:child]
/// properties are set, it contains a child widget. The indicator node
/// is named check when no group is set, and radio if the checkbutton
/// is grouped together with other checkbuttons.
///
/// # Accessibility
///
/// `GtkCheckButton` uses the %GTK_ACCESSIBLE_ROLE_CHECKBOX role.
public struct CheckButton: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
var accessibleRole: String? var accessibleRole: String?
/// action-name /// The name of the action with which this widget should be associated.
var actionName: String? var actionName: String?
/// If the check button is active. /// If the check button is active.
/// ///
/// Setting `active` to %TRUE will add the `:checked:` state to both /// Setting `active` to `true` will add the `:checked:` state to both
/// the check button and the indicator CSS node. /// the check button and the indicator CSS node.
var active: Binding<Bool>? var active: Binding<Bool>?
/// The child widget. /// The child widget.
var child: (() -> Body)? var child: Body?
/// If the check button is in an in between state. /// If the check button is in an in between state.
/// ///
/// The inconsistent state only affects visual appearance, /// The inconsistent state only affects visual appearance,
@ -101,12 +63,12 @@ public struct CheckButton: AdwaitaWidget {
/// emitting it causes the button to animate press then release. /// emitting it causes the button to animate press then release.
/// ///
/// Applications should never connect to this signal, but use the /// Applications should never connect to this signal, but use the
/// [signal@Gtk.CheckButton::toggled] signal. /// `Gtk.CheckButton::toggled` signal.
/// ///
/// The default bindings for this signal are all forms of the /// The default bindings for this signal are all forms of the
/// <kbd></kbd> and <kbd>Enter</kbd> keys. /// <kbd></kbd> and <kbd>Enter</kbd> keys.
var activate: (() -> Void)? var activate: (() -> Void)?
/// Emitted when the buttons's [property@Gtk.CheckButton:active] /// Emitted when the buttons's ``active(_:)``
/// property changes. /// property changes.
var toggled: (() -> Void)? var toggled: (() -> Void)?
@ -124,8 +86,7 @@ public struct CheckButton: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let childStorage = child?.storage(data: data, type: type) {
if let childStorage = child?().storage(data: data, type: type) {
storage.content["child"] = [childStorage] storage.content["child"] = [childStorage]
gtk_check_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast()) gtk_check_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())
} }
@ -165,7 +126,7 @@ if let active, newValue != active.wrappedValue {
gtk_check_button_set_active(storage.opaquePointer?.cast(), active.wrappedValue.cBool) gtk_check_button_set_active(storage.opaquePointer?.cast(), active.wrappedValue.cBool)
} }
if let widget = storage.content["child"]?.first { if let widget = storage.content["child"]?.first {
child?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) child?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let inconsistent, updateProperties, (storage.previousState as? Self)?.inconsistent != inconsistent { if let inconsistent, updateProperties, (storage.previousState as? Self)?.inconsistent != inconsistent {
gtk_check_button_set_inconsistent(widget?.cast(), inconsistent.cBool) gtk_check_button_set_inconsistent(widget?.cast(), inconsistent.cBool)
@ -178,6 +139,7 @@ if let active, newValue != active.wrappedValue {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -191,37 +153,25 @@ if let active, newValue != active.wrappedValue {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// action-name /// The name of the action with which this widget should be associated.
public func actionName(_ actionName: String?) -> Self { public func actionName(_ actionName: String?) -> Self {
var newSelf = self modify { $0.actionName = actionName }
newSelf.actionName = actionName
return newSelf
} }
/// If the check button is active. /// If the check button is active.
/// ///
/// Setting `active` to %TRUE will add the `:checked:` state to both /// Setting `active` to `true` will add the `:checked:` state to both
/// the check button and the indicator CSS node. /// the check button and the indicator CSS node.
public func active(_ active: Binding<Bool>?) -> Self { public func active(_ active: Binding<Bool>?) -> Self {
var newSelf = self modify { $0.active = active }
newSelf.active = active
return newSelf
} }
/// The child widget. /// The child widget.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self { public func child(@ViewBuilder _ child: () -> Body) -> Self {
var newSelf = self modify { $0.child = child() }
newSelf.child = child
return newSelf
} }
/// If the check button is in an in between state. /// If the check button is in an in between state.
@ -229,27 +179,18 @@ if let active, newValue != active.wrappedValue {
/// The inconsistent state only affects visual appearance, /// The inconsistent state only affects visual appearance,
/// not the semantics of the button. /// not the semantics of the button.
public func inconsistent(_ inconsistent: Bool? = true) -> Self { public func inconsistent(_ inconsistent: Bool? = true) -> Self {
var newSelf = self modify { $0.inconsistent = inconsistent }
newSelf.inconsistent = inconsistent
return newSelf
} }
/// Text of the label inside the check button, if it contains a label widget. /// Text of the label inside the check button, if it contains a label widget.
public func label(_ label: String?) -> Self { public func label(_ label: String?) -> Self {
var newSelf = self modify { $0.label = label }
newSelf.label = label
return newSelf
} }
/// If set, an underline in the text indicates that the following /// If set, an underline in the text indicates that the following
/// character is to be used as mnemonic. /// character is to be used as mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// Emitted to when the check button is activated. /// Emitted to when the check button is activated.
@ -258,7 +199,7 @@ if let active, newValue != active.wrappedValue {
/// emitting it causes the button to animate press then release. /// emitting it causes the button to animate press then release.
/// ///
/// Applications should never connect to this signal, but use the /// Applications should never connect to this signal, but use the
/// [signal@Gtk.CheckButton::toggled] signal. /// `Gtk.CheckButton::toggled` signal.
/// ///
/// The default bindings for this signal are all forms of the /// The default bindings for this signal are all forms of the
/// <kbd></kbd> and <kbd>Enter</kbd> keys. /// <kbd></kbd> and <kbd>Enter</kbd> keys.
@ -268,7 +209,7 @@ if let active, newValue != active.wrappedValue {
return newSelf return newSelf
} }
/// Emitted when the buttons's [property@Gtk.CheckButton:active] /// Emitted when the buttons's ``active(_:)``
/// property changes. /// property changes.
public func toggled(_ toggled: @escaping () -> Void) -> Self { public func toggled(_ toggled: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self

View File

@ -2,7 +2,7 @@
// Clamp.swift // Clamp.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,7 +10,7 @@ import LevenshteinTransformations
/// A widget constraining its child to a given size. /// A widget constraining its child to a given size.
/// ///
/// <picture><source srcset="clamp-wide-dark.png" media="(prefers-color-scheme: dark)"><img src="clamp-wide.png" alt="clamp-wide"></picture><picture><source srcset="clamp-narrow-dark.png" media="(prefers-color-scheme: dark)"><img src="clamp-narrow.png" alt="clamp-narrow"></picture> ///
/// ///
/// The `AdwClamp` widget constrains the size of the widget it contains to a /// The `AdwClamp` widget constrains the size of the widget it contains to a
/// given maximum size. It will constrain the width if it is horizontal, or the /// given maximum size. It will constrain the width if it is horizontal, or the
@ -21,20 +21,27 @@ import LevenshteinTransformations
/// allocated the minimum size it can fit in instead. /// allocated the minimum size it can fit in instead.
/// ///
/// `AdwClamp` can scale with the text scale factor, use the /// `AdwClamp` can scale with the text scale factor, use the
/// [property@ClampLayout:unit] property to enable that behavior. /// ``unit(_:)`` property to enable that behavior.
///
/// See also: `ClampLayout`, `ClampScrollable`.
/// ///
/// ## CSS nodes
/// ///
/// `AdwClamp` has a single CSS node with name `clamp`.
public struct Clamp: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The child widget of the `AdwClamp`. /// The child widget of the `AdwClamp`.
var child: (() -> Body)? var child: Body?
/// The maximum size allocated to the child. /// The maximum size allocated to the child.
/// ///
/// It is the width if the clamp is horizontal, or the height if it is vertical. /// It is the width if the clamp is horizontal, or the height if it is vertical.
@ -69,8 +76,7 @@ public struct Clamp: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let childStorage = child?.storage(data: data, type: type) {
if let childStorage = child?().storage(data: data, type: type) {
storage.content["child"] = [childStorage] storage.content["child"] = [childStorage]
adw_clamp_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast()) adw_clamp_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())
} }
@ -88,7 +94,7 @@ public struct Clamp: AdwaitaWidget {
storage.modify { widget in storage.modify { widget in
if let widget = storage.content["child"]?.first { if let widget = storage.content["child"]?.first {
child?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) child?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let maximumSize, updateProperties, (storage.previousState as? Self)?.maximumSize != maximumSize { if let maximumSize, updateProperties, (storage.previousState as? Self)?.maximumSize != maximumSize {
adw_clamp_set_maximum_size(widget, maximumSize.cInt) adw_clamp_set_maximum_size(widget, maximumSize.cInt)
@ -98,6 +104,7 @@ public struct Clamp: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -108,21 +115,15 @@ public struct Clamp: AdwaitaWidget {
} }
/// The child widget of the `AdwClamp`. /// The child widget of the `AdwClamp`.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self { public func child(@ViewBuilder _ child: () -> Body) -> Self {
var newSelf = self modify { $0.child = child() }
newSelf.child = child
return newSelf
} }
/// The maximum size allocated to the child. /// The maximum size allocated to the child.
/// ///
/// It is the width if the clamp is horizontal, or the height if it is vertical. /// It is the width if the clamp is horizontal, or the height if it is vertical.
public func maximumSize(_ maximumSize: Int?) -> Self { public func maximumSize(_ maximumSize: Int?) -> Self {
var newSelf = self modify { $0.maximumSize = maximumSize }
newSelf.maximumSize = maximumSize
return newSelf
} }
/// The size above which the child is clamped. /// The size above which the child is clamped.
@ -140,10 +141,7 @@ public struct Clamp: AdwaitaWidget {
/// Effectively, tightening the grip on the child before it reaches its maximum /// Effectively, tightening the grip on the child before it reaches its maximum
/// size makes transitions to and from the maximum size smoother when resizing. /// size makes transitions to and from the maximum size smoother when resizing.
public func tighteningThreshold(_ tighteningThreshold: Int?) -> Self { public func tighteningThreshold(_ tighteningThreshold: Int?) -> Self {
var newSelf = self modify { $0.tighteningThreshold = tighteningThreshold }
newSelf.tighteningThreshold = tighteningThreshold
return newSelf
} }
} }

View File

@ -2,15 +2,15 @@
// ComboRow.swift // ComboRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A [class@Gtk.ListBoxRow] used to choose from a list of items. /// A `Gtk.ListBoxRow` used to choose from a list of items.
///
/// ///
/// <picture><source srcset="combo-row-dark.png" media="(prefers-color-scheme: dark)"><img src="combo-row.png" alt="combo-row"></picture>
/// ///
/// The `AdwComboRow` widget allows the user to choose from a list of valid /// The `AdwComboRow` widget allows the user to choose from a list of valid
/// choices. The row displays the selected choice. When activated, the row /// choices. The row displays the selected choice. When activated, the row
@ -21,59 +21,55 @@ import LevenshteinTransformations
/// <object class="AdwComboRow"><property name="title" translatable="yes">Combo Row</property><property name="model"><object class="GtkStringList"><items><item translatable="yes">Foo</item><item translatable="yes">Bar</item><item translatable="yes">Baz</item></items></object></property></object> /// <object class="AdwComboRow"><property name="title" translatable="yes">Combo Row</property><property name="model"><object class="GtkStringList"><items><item translatable="yes">Foo</item><item translatable="yes">Bar</item><item translatable="yes">Baz</item></items></object></property></object>
/// ``` /// ```
/// ///
/// The [property@ComboRow:selected] and [property@ComboRow:selected-item] /// The ``selected(_:)`` and ``selectedItem(_:)``
/// properties can be used to keep track of the selected item and react to their /// properties can be used to keep track of the selected item and react to their
/// changes. /// changes.
/// ///
/// `AdwComboRow` mirrors [class@Gtk.DropDown], see that widget for details. /// `AdwComboRow` mirrors `Gtk.DropDown`, see that widget for details.
/// ///
/// `AdwComboRow` is [property@Gtk.ListBoxRow:activatable] if a model is set. /// `AdwComboRow` is ``activatable(_:)`` if a model is set.
/// ///
/// ## CSS nodes
/// ///
/// `AdwComboRow` has a main CSS node with name `row` and the `.combo` style
/// class.
///
/// Its popover has the node named `popover` with the `.menu` style class, it
/// contains a [class@Gtk.ScrolledWindow], which in turn contains a
/// [class@Gtk.ListView], both are accessible via their regular nodes.
///
/// ## Accessibility
///
/// `AdwComboRow` uses the `GTK_ACCESSIBLE_ROLE_COMBO_BOX` role.
public struct ComboRow: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The widget to activate when the row is activated. /// The widget to activate when the row is activated.
/// ///
/// The row can be activated either by clicking on it, calling /// The row can be activated either by clicking on it, calling
/// [method@ActionRow.activate], or via mnemonics in the title. /// `ActionRow.activate`, or via mnemonics in the title.
/// See the [property@PreferencesRow:use-underline] property to enable /// See the ``useUnderline(_:)`` property to enable
/// mnemonics. /// mnemonics.
/// ///
/// The target widget will be activated by emitting the /// The target widget will be activated by emitting the
/// [signal@Gtk.Widget::mnemonic-activate] signal on it. /// `Gtk.Widget::mnemonic-activate` signal on it.
var activatableWidget: (() -> Body)? var activatableWidget: Body?
/// Whether to show a search entry in the popup. /// Whether to show a search entry in the popup.
/// ///
/// If set to `TRUE`, a search entry will be shown in the popup that /// If set to `true`, a search entry will be shown in the popup that
/// allows to search for items in the list. /// allows to search for items in the list.
/// ///
/// Search requires [property@ComboRow:expression] to be set. /// Search requires ``expression(_:)`` to be set.
var enableSearch: Bool? var enableSearch: Bool?
/// The position of the selected item. /// The position of the selected item.
/// ///
/// If no item is selected, the property has the value /// If no item is selected, the property has the value
/// [const@Gtk.INVALID_LIST_POSITION] /// `Gtk.INVALID_LIST_POSITION`
var selected: Binding<UInt>? var selected: Binding<UInt>?
/// The subtitle for this row. /// The subtitle for this row.
/// ///
/// The subtitle is interpreted as Pango markup unless /// The subtitle is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
var subtitle: String? var subtitle: String?
/// The number of lines at the end of which the subtitle label will be /// The number of lines at the end of which the subtitle label will be
/// ellipsized. /// ellipsized.
@ -82,12 +78,12 @@ public struct ComboRow: AdwaitaWidget {
var subtitleLines: Int? var subtitleLines: Int?
/// Whether the user can copy the subtitle from the label. /// Whether the user can copy the subtitle from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
var subtitleSelectable: Bool? var subtitleSelectable: Bool?
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
var title: String? var title: String?
/// The number of lines at the end of which the title label will be ellipsized. /// The number of lines at the end of which the title label will be ellipsized.
/// ///
@ -95,23 +91,23 @@ public struct ComboRow: AdwaitaWidget {
var titleLines: Int? var titleLines: Int?
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
var titleSelectable: Bool? var titleSelectable: Bool?
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
var useMarkup: Bool? var useMarkup: Bool?
/// Whether to use the current value as the subtitle. /// Whether to use the current value as the subtitle.
/// ///
/// If you use a custom list item factory, you will need to give the row a /// If you use a custom list item factory, you will need to give the row a
/// name conversion expression with [property@ComboRow:expression]. /// name conversion expression with ``expression(_:)``.
/// ///
/// If set to `TRUE`, you should not access [property@ActionRow:subtitle]. /// If set to `true`, you should not access ``subtitle(_:)``.
/// ///
/// The subtitle is interpreted as Pango markup if /// The subtitle is interpreted as Pango markup if
/// [property@PreferencesRow:use-markup] is set to `TRUE`. /// ``useMarkup(_:)`` is set to `true`.
var useSubtitle: Bool? var useSubtitle: Bool?
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
var useUnderline: Bool? var useUnderline: Bool?
@ -123,7 +119,7 @@ public struct ComboRow: AdwaitaWidget {
var prefix: () -> Body = { [] } var prefix: () -> Body = { [] }
/// Initialize `ComboRow`. /// Initialize `ComboRow`.
public init() { init() {
} }
/// The view storage. /// The view storage.
@ -136,8 +132,7 @@ public struct ComboRow: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let activatableWidgetStorage = activatableWidget?.storage(data: data, type: type) {
if let activatableWidgetStorage = activatableWidget?().storage(data: data, type: type) {
storage.content["activatableWidget"] = [activatableWidgetStorage] storage.content["activatableWidget"] = [activatableWidgetStorage]
adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast()) adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast())
} }
@ -178,7 +173,7 @@ if let selected, newValue != selected.wrappedValue {
} }
} }
if let widget = storage.content["activatableWidget"]?.first { if let widget = storage.content["activatableWidget"]?.first {
activatableWidget?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) activatableWidget?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let enableSearch, updateProperties, (storage.previousState as? Self)?.enableSearch != enableSearch { if let enableSearch, updateProperties, (storage.previousState as? Self)?.enableSearch != enableSearch {
adw_combo_row_set_enable_search(widget?.cast(), enableSearch.cBool) adw_combo_row_set_enable_search(widget?.cast(), enableSearch.cBool)
@ -215,6 +210,7 @@ if let selected, newValue != selected.wrappedValue {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -227,52 +223,40 @@ if let selected, newValue != selected.wrappedValue {
/// The widget to activate when the row is activated. /// The widget to activate when the row is activated.
/// ///
/// The row can be activated either by clicking on it, calling /// The row can be activated either by clicking on it, calling
/// [method@ActionRow.activate], or via mnemonics in the title. /// `ActionRow.activate`, or via mnemonics in the title.
/// See the [property@PreferencesRow:use-underline] property to enable /// See the ``useUnderline(_:)`` property to enable
/// mnemonics. /// mnemonics.
/// ///
/// The target widget will be activated by emitting the /// The target widget will be activated by emitting the
/// [signal@Gtk.Widget::mnemonic-activate] signal on it. /// `Gtk.Widget::mnemonic-activate` signal on it.
public func activatableWidget(@ViewBuilder _ activatableWidget: @escaping (() -> Body)) -> Self { public func activatableWidget(@ViewBuilder _ activatableWidget: () -> Body) -> Self {
var newSelf = self modify { $0.activatableWidget = activatableWidget() }
newSelf.activatableWidget = activatableWidget
return newSelf
} }
/// Whether to show a search entry in the popup. /// Whether to show a search entry in the popup.
/// ///
/// If set to `TRUE`, a search entry will be shown in the popup that /// If set to `true`, a search entry will be shown in the popup that
/// allows to search for items in the list. /// allows to search for items in the list.
/// ///
/// Search requires [property@ComboRow:expression] to be set. /// Search requires ``expression(_:)`` to be set.
public func enableSearch(_ enableSearch: Bool? = true) -> Self { public func enableSearch(_ enableSearch: Bool? = true) -> Self {
var newSelf = self modify { $0.enableSearch = enableSearch }
newSelf.enableSearch = enableSearch
return newSelf
} }
/// The position of the selected item. /// The position of the selected item.
/// ///
/// If no item is selected, the property has the value /// If no item is selected, the property has the value
/// [const@Gtk.INVALID_LIST_POSITION] /// `Gtk.INVALID_LIST_POSITION`
public func selected(_ selected: Binding<UInt>?) -> Self { public func selected(_ selected: Binding<UInt>?) -> Self {
var newSelf = self modify { $0.selected = selected }
newSelf.selected = selected
return newSelf
} }
/// The subtitle for this row. /// The subtitle for this row.
/// ///
/// The subtitle is interpreted as Pango markup unless /// The subtitle is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
public func subtitle(_ subtitle: String?) -> Self { public func subtitle(_ subtitle: String?) -> Self {
var newSelf = self modify { $0.subtitle = subtitle }
newSelf.subtitle = subtitle
return newSelf
} }
/// The number of lines at the end of which the subtitle label will be /// The number of lines at the end of which the subtitle label will be
@ -280,87 +264,63 @@ if let selected, newValue != selected.wrappedValue {
/// ///
/// If the value is 0, the number of lines won't be limited. /// If the value is 0, the number of lines won't be limited.
public func subtitleLines(_ subtitleLines: Int?) -> Self { public func subtitleLines(_ subtitleLines: Int?) -> Self {
var newSelf = self modify { $0.subtitleLines = subtitleLines }
newSelf.subtitleLines = subtitleLines
return newSelf
} }
/// Whether the user can copy the subtitle from the label. /// Whether the user can copy the subtitle from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
public func subtitleSelectable(_ subtitleSelectable: Bool? = true) -> Self { public func subtitleSelectable(_ subtitleSelectable: Bool? = true) -> Self {
var newSelf = self modify { $0.subtitleSelectable = subtitleSelectable }
newSelf.subtitleSelectable = subtitleSelectable
return newSelf
} }
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
public func title(_ title: String?) -> Self { public func title(_ title: String?) -> Self {
var newSelf = self modify { $0.title = title }
newSelf.title = title
return newSelf
} }
/// The number of lines at the end of which the title label will be ellipsized. /// The number of lines at the end of which the title label will be ellipsized.
/// ///
/// If the value is 0, the number of lines won't be limited. /// If the value is 0, the number of lines won't be limited.
public func titleLines(_ titleLines: Int?) -> Self { public func titleLines(_ titleLines: Int?) -> Self {
var newSelf = self modify { $0.titleLines = titleLines }
newSelf.titleLines = titleLines
return newSelf
} }
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
public func titleSelectable(_ titleSelectable: Bool? = true) -> Self { public func titleSelectable(_ titleSelectable: Bool? = true) -> Self {
var newSelf = self modify { $0.titleSelectable = titleSelectable }
newSelf.titleSelectable = titleSelectable
return newSelf
} }
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
public func useMarkup(_ useMarkup: Bool? = true) -> Self { public func useMarkup(_ useMarkup: Bool? = true) -> Self {
var newSelf = self modify { $0.useMarkup = useMarkup }
newSelf.useMarkup = useMarkup
return newSelf
} }
/// Whether to use the current value as the subtitle. /// Whether to use the current value as the subtitle.
/// ///
/// If you use a custom list item factory, you will need to give the row a /// If you use a custom list item factory, you will need to give the row a
/// name conversion expression with [property@ComboRow:expression]. /// name conversion expression with ``expression(_:)``.
/// ///
/// If set to `TRUE`, you should not access [property@ActionRow:subtitle]. /// If set to `true`, you should not access ``subtitle(_:)``.
/// ///
/// The subtitle is interpreted as Pango markup if /// The subtitle is interpreted as Pango markup if
/// [property@PreferencesRow:use-markup] is set to `TRUE`. /// ``useMarkup(_:)`` is set to `true`.
public func useSubtitle(_ useSubtitle: Bool? = true) -> Self { public func useSubtitle(_ useSubtitle: Bool? = true) -> Self {
var newSelf = self modify { $0.useSubtitle = useSubtitle }
newSelf.useSubtitle = useSubtitle
return newSelf
} }
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// This signal is emitted after the row has been activated. /// This signal is emitted after the row has been activated.

View File

@ -0,0 +1,182 @@
//
// DropDown.swift
// Adwaita
//
// Created by auto-generation on 04.02.26.
//
import CAdw
import LevenshteinTransformations
/// Allows the user to choose an item from a list of options.
///
///
///
/// The `GtkDropDown` displays the [selected]``selected(_:)``
/// choice.
///
/// The options are given to `GtkDropDown` in the form of `GListModel`
/// and how the individual options are represented is determined by
/// a `Gtk.ListItemFactory`. The default factory displays simple strings,
/// and adds a checkmark to the selected item in the popup.
///
/// To set your own factory, use `Gtk.DropDown.set_factory`. It is
/// possible to use a separate factory for the items in the popup, with
/// `Gtk.DropDown.set_list_factory`.
///
/// `GtkDropDown` knows how to obtain strings from the items in a
/// `Gtk.StringList`; for other models, you have to provide an expression
/// to find the strings via `Gtk.DropDown.set_expression`.
///
/// `GtkDropDown` can optionally allow search in the popup, which is
/// useful if the list of options is long. To enable the search entry,
/// use `Gtk.DropDown.set_enable_search`.
///
/// Here is a UI definition example for `GtkDropDown` with a simple model:
///
/// ```xml
/// <object class="GtkDropDown"><property name="model"><object class="GtkStringList"><items><item translatable="yes">Factory</item><item translatable="yes">Home</item><item translatable="yes">Subway</item></items></object></property></object>
/// ```
///
/// If a `GtkDropDown` is created in this manner, or with
/// `Gtk.DropDown.new_from_strings`, for instance, the object returned from
/// `Gtk.DropDown.get_selected_item` will be a `Gtk.StringObject`.
///
/// To learn more about the list widget framework, see the
/// [overview](section-list-widget.html).
///
///
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.
///
/// The accessible role cannot be changed once set.
var accessibleRole: String?
/// Whether to show a search entry in the popup.
///
/// Note that search requires ``expression(_:)``
/// to be set.
var enableSearch: Bool?
/// The position of the selected item.
///
/// If no item is selected, the property has the value
/// %GTK_INVALID_LIST_POSITION.
var selected: Binding<UInt>?
/// Whether to show an arrow within the GtkDropDown widget.
var showArrow: Bool?
/// Emitted to when the drop down is activated.
///
/// The `::activate` signal on `GtkDropDown` is an action signal and
/// emitting it causes the drop down to pop up its dropdown.
var activate: (() -> Void)?
/// Initialize `DropDown`.
init() {
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The view render data type.
/// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let storage = ViewStorage(gtk_drop_down_new(gtk_string_list_new(nil), nil)?.opaque())
for function in appearFunctions {
function(storage, data)
}
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.
public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) where Data: ViewRenderData {
if let activate {
storage.connectSignal(name: "activate", argCount: 0) {
activate()
}
}
storage.modify { widget in
storage.notify(name: "selected") {
let newValue = UInt(gtk_drop_down_get_selected(storage.opaquePointer))
if let selected, newValue != selected.wrappedValue {
selected.wrappedValue = newValue
}
}
if let enableSearch, updateProperties, (storage.previousState as? Self)?.enableSearch != enableSearch {
gtk_drop_down_set_enable_search(widget, enableSearch.cBool)
}
if let selected, updateProperties, (UInt(gtk_drop_down_get_selected(storage.opaquePointer))) != selected.wrappedValue {
gtk_drop_down_set_selected(storage.opaquePointer, selected.wrappedValue.cInt)
}
if let showArrow, updateProperties, (storage.previousState as? Self)?.showArrow != showArrow {
gtk_drop_down_set_show_arrow(widget, showArrow.cBool)
}
}
for function in updateFunctions {
function(storage, data, updateProperties)
}
if updateProperties {
storage.previousState = self
}
}
/// The accessible role of the given `GtkAccessible` implementation.
///
/// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self {
modify { $0.accessibleRole = accessibleRole }
}
/// Whether to show a search entry in the popup.
///
/// Note that search requires ``expression(_:)``
/// to be set.
public func enableSearch(_ enableSearch: Bool? = true) -> Self {
modify { $0.enableSearch = enableSearch }
}
/// The position of the selected item.
///
/// If no item is selected, the property has the value
/// %GTK_INVALID_LIST_POSITION.
public func selected(_ selected: Binding<UInt>?) -> Self {
modify { $0.selected = selected }
}
/// Whether to show an arrow within the GtkDropDown widget.
public func showArrow(_ showArrow: Bool? = true) -> Self {
modify { $0.showArrow = showArrow }
}
/// Emitted to when the drop down is activated.
///
/// The `::activate` signal on `GtkDropDown` is an action signal and
/// emitting it causes the drop down to pop up its dropdown.
public func activate(_ activate: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.activate = activate
return newSelf
}
}

View File

@ -0,0 +1,779 @@
//
// Entry.swift
// Adwaita
//
// Created by auto-generation on 04.02.26.
//
import CAdw
import LevenshteinTransformations
/// A single-line text entry widget.
///
///
///
/// A fairly large set of key bindings are supported by default. If the
/// entered text is longer than the allocation of the widget, the widget
/// will scroll so that the cursor position is visible.
///
/// When using an entry for passwords and other sensitive information, it
/// can be put into password mode using `Gtk.Entry.set_visibility`.
/// In this mode, entered text is displayed using a invisible character.
/// By default, GTK picks the best invisible character that is available
/// in the current font, but it can be changed with
/// `Gtk.Entry.set_invisible_char`.
///
/// `GtkEntry` has the ability to display progress or activity
/// information behind the text. To make an entry display such information,
/// use `Gtk.Entry.set_progress_fraction` or
/// `Gtk.Entry.set_progress_pulse_step`.
///
/// Additionally, `GtkEntry` can show icons at either side of the entry.
/// These icons can be activatable by clicking, can be set up as drag source
/// and can have tooltips. To add an icon, use
/// `Gtk.Entry.set_icon_from_gicon` or one of the various other functions
/// that set an icon from an icon name or a paintable. To trigger an action when
/// the user clicks an icon, connect to the `Gtk.Entry::icon-press` signal.
/// To allow DND operations from an icon, use
/// `Gtk.Entry.set_icon_drag_source`. To set a tooltip on an icon, use
/// `Gtk.Entry.set_icon_tooltip_text` or the corresponding function
/// for markup.
///
/// Note that functionality or information that is only available by clicking
/// on an icon in an entry may not be accessible at all to users which are not
/// able to use a mouse or other pointing device. It is therefore recommended
/// that any such functionality should also be available by other means, e.g.
/// via the context menu of the entry.
///
///
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.
///
/// The accessible role cannot be changed once set.
var accessibleRole: String?
/// The current position of the insertion cursor in chars.
var cursorPosition: Int?
/// Whether the entry contents can be edited.
var editable: Bool?
/// Indicates whether editing on the cell has been canceled.
var editingCanceled: Bool?
/// Whether to suggest Emoji replacements for :-delimited names
/// like `:heart:`.
var enableEmojiCompletion: Bool?
/// If undo/redo should be enabled for the editable.
var enableUndo: Bool?
/// A menu model whose contents will be appended to the context menu.
var extraMenu: Body?
/// Whether the entry should draw a frame.
var hasFrame: Bool?
/// Which IM (input method) module should be used for this entry.
///
/// See `Gtk.IMContext`.
///
/// Setting this to a non-%NULL value overrides the system-wide IM
/// module setting. See the GtkSettings ``gtkImModule(_:)``
/// property.
var imModule: String?
/// The character to use when masking entry contents (password mode).
var invisibleCharacter: UInt?
/// Whether the invisible char has been set for the `GtkEntry`.
var invisibleCharacterSet: Bool?
/// Maximum number of characters for this entry.
var maxLength: Int?
/// The desired maximum width of the entry, in characters.
var maxWidthChars: Int?
/// Text for an item in the context menu to activate the primary icon action.
///
/// When the primary icon is activatable and this property has been set, a new entry
/// in the context menu of this GtkEntry will appear with this text. Selecting that
/// menu entry will result in the primary icon being activated, exactly in the same way
/// as it would be activated from a mouse click.
///
/// This simplifies adding accessibility support to applications using activatable
/// icons. The activatable icons aren't focusable when navigating the interface with
/// the keyboard This is why Gtk recommends to also add those actions in the context
/// menu. This set of methods greatly simplifies this, by adding a menu item that, when
/// enabled, calls the same callback than clicking on the icon.
var menuEntryIconPrimaryText: String?
/// Text for an item in the context menu to activate the secondary icon action.
///
/// When the primary icon is activatable and this property has been set, a new entry
/// in the context menu of this GtkEntry will appear with this text. Selecting that
/// menu entry will result in the primary icon being activated, exactly in the same way
/// as it would be activated from a mouse click.
///
/// This simplifies adding accessibility support to applications using activatable
/// icons. The activatable icons aren't focusable when navigating the interface with
/// the keyboard This is why Gtk recommends to also add those actions in the context
/// menu. This set of methods greatly simplifies this, by adding a menu item that, when
/// enabled, calls the same callback than clicking on the icon.
var menuEntryIconSecondaryText: String?
/// If text is overwritten when typing in the `GtkEntry`.
var overwriteMode: Bool?
/// The text that will be displayed in the `GtkEntry` when it is empty
/// and unfocused.
var placeholderText: String?
/// Whether the primary icon is activatable.
///
/// GTK emits the `Gtk.Entry::icon-press` and
/// `Gtk.Entry::icon-release` signals only on sensitive,
/// activatable icons.
///
/// Sensitive, but non-activatable icons can be used for purely
/// informational purposes.
var primaryIconActivatable: Bool?
/// The icon name to use for the primary icon for the entry.
var primaryIconName: String?
/// Whether the primary icon is sensitive.
///
/// An insensitive icon appears grayed out. GTK does not emit the
/// `Gtk.Entry::icon-press` and `Gtk.Entry::icon-release`
/// signals and does not allow DND from insensitive icons.
///
/// An icon should be set insensitive if the action that would trigger
/// when clicked is currently not available.
var primaryIconSensitive: Bool?
/// The contents of the tooltip on the primary icon, with markup.
///
/// Also see `Gtk.Entry.set_icon_tooltip_markup`.
var primaryIconTooltipMarkup: String?
/// The contents of the tooltip on the primary icon.
///
/// Also see `Gtk.Entry.set_icon_tooltip_text`.
var primaryIconTooltipText: String?
/// The current fraction of the task that's been completed.
var progressFraction: Double?
/// The fraction of total entry width to move the progress
/// bouncing block for each pulse.
///
/// See `Gtk.Entry.progress_pulse`.
var progressPulseStep: Double?
/// Number of pixels of the entry scrolled off the screen to the left.
var scrollOffset: Int?
/// Whether the secondary icon is activatable.
///
/// GTK emits the `Gtk.Entry::icon-press` and
/// `Gtk.Entry::icon-release` signals only on sensitive,
/// activatable icons.
///
/// Sensitive, but non-activatable icons can be used for purely
/// informational purposes.
var secondaryIconActivatable: Bool?
/// The icon name to use for the secondary icon for the entry.
var secondaryIconName: String?
/// Whether the secondary icon is sensitive.
///
/// An insensitive icon appears grayed out. GTK does not emit the
/// `Gtk.Entry::icon-press[ and [signal@Gtk.Entry::icon-release`
/// signals and does not allow DND from insensitive icons.
///
/// An icon should be set insensitive if the action that would trigger
/// when clicked is currently not available.
var secondaryIconSensitive: Bool?
/// The contents of the tooltip on the secondary icon, with markup.
///
/// Also see `Gtk.Entry.set_icon_tooltip_markup`.
var secondaryIconTooltipMarkup: String?
/// The contents of the tooltip on the secondary icon.
///
/// Also see `Gtk.Entry.set_icon_tooltip_text`.
var secondaryIconTooltipText: String?
/// The position of the opposite end of the selection from the cursor in chars.
var selectionBound: Int?
/// Whether the entry will show an Emoji icon in the secondary icon position
/// to open the Emoji chooser.
var showEmojiIcon: Bool?
/// The contents of the entry.
var text: Binding<String>?
/// The length of the text in the `GtkEntry`.
var textLength: UInt?
/// When `true`, pasted multi-line text is truncated to the first line.
var truncateMultiline: Bool?
/// Whether the entry should show the invisible char instead of the
/// actual text (password mode).
var visibility: Bool?
/// Number of characters to leave space for in the entry.
var widthChars: Int?
/// The horizontal alignment, from 0 (left) to 1 (right).
///
/// Reversed for RTL layouts.
var xalign: Float?
/// Emitted when the entry is activated.
///
/// The keybindings for this signal are all forms of the Enter key.
var activate: (() -> Void)?
/// Emitted at the end of a single user-visible operation on the
/// contents.
///
/// E.g., a paste operation that replaces the contents of the
/// selection will cause only one signal emission (even though it
/// is implemented by first deleting the selection, then inserting
/// the new content, and may cause multiple ::notify::text signals
/// to be emitted).
var changed: (() -> Void)?
/// Emitted when text is deleted from the widget by the user.
///
/// The default handler for this signal will normally be responsible for
/// deleting the text, so by connecting to this signal and then stopping
/// the signal with g_signal_stop_emission(), it is possible to modify the
/// range of deleted text, or prevent it from being deleted entirely.
///
/// The @start_pos and @end_pos parameters are interpreted as for
/// `Gtk.Editable.delete_text`.
var deleteText: (() -> Void)?
/// This signal is a sign for the cell renderer to update its
/// value from the @cell_editable.
///
/// Implementations of `GtkCellEditable` are responsible for
/// emitting this signal when they are done editing, e.g.
/// `GtkEntry` emits this signal when the user presses Enter. Typical things to
/// do in a handler for ::editing-done are to capture the edited value,
/// disconnect the @cell_editable from signals on the `GtkCellRenderer`, etc.
///
/// gtk_cell_editable_editing_done() is a convenience method
/// for emitting `GtkCellEditable::editing-done`.
var editingDone: (() -> Void)?
/// Emitted when an activatable icon is clicked.
var iconPress: (() -> Void)?
/// Emitted on the button release from a mouse click
/// over an activatable icon.
var iconRelease: (() -> Void)?
/// Emitted when text is inserted into the widget by the user.
///
/// The default handler for this signal will normally be responsible
/// for inserting the text, so by connecting to this signal and then
/// stopping the signal with g_signal_stop_emission(), it is possible
/// to modify the inserted text, or prevent it from being inserted entirely.
var insertText: (() -> Void)?
/// This signal is meant to indicate that the cell is finished
/// editing, and the @cell_editable widget is being removed and may
/// subsequently be destroyed.
///
/// Implementations of `GtkCellEditable` are responsible for
/// emitting this signal when they are done editing. It must
/// be emitted after the `GtkCellEditable::editing-done` signal,
/// to give the cell renderer a chance to update the cell's value
/// before the widget is removed.
///
/// gtk_cell_editable_remove_widget() is a convenience method
/// for emitting `GtkCellEditable::remove-widget`.
var removeWidget: (() -> Void)?
/// Initialize `Entry`.
init() {
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The view render data type.
/// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let storage = ViewStorage(gtk_entry_new()?.opaque())
for function in appearFunctions {
function(storage, data)
}
if let extraMenu {
let childStorage = MenuCollection { extraMenu }.getMenu(data: data)
storage.content["extraMenu"] = [childStorage]
gtk_entry_set_extra_menu(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())
}
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.
public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) where Data: ViewRenderData {
if let activate {
storage.connectSignal(name: "activate", argCount: 0) {
activate()
}
}
if let changed {
storage.connectSignal(name: "changed", argCount: 0) {
changed()
}
}
if let deleteText {
storage.connectSignal(name: "delete-text", argCount: 2) {
deleteText()
}
}
if let editingDone {
storage.connectSignal(name: "editing-done", argCount: 0) {
editingDone()
}
}
if let iconPress {
storage.connectSignal(name: "icon-press", argCount: 1) {
iconPress()
}
}
if let iconRelease {
storage.connectSignal(name: "icon-release", argCount: 1) {
iconRelease()
}
}
if let insertText {
storage.connectSignal(name: "insert-text", argCount: 3) {
insertText()
}
}
if let removeWidget {
storage.connectSignal(name: "remove-widget", argCount: 0) {
removeWidget()
}
}
storage.modify { widget in
storage.notify(name: "text") {
let newValue = String(cString: gtk_editable_get_text(storage.opaquePointer))
if let text, newValue != text.wrappedValue {
text.wrappedValue = newValue
}
}
if let cursorPosition, updateProperties, (storage.previousState as? Self)?.cursorPosition != cursorPosition {
gtk_editable_set_position(widget, cursorPosition.cInt)
}
if let editable, updateProperties, (storage.previousState as? Self)?.editable != editable {
gtk_editable_set_editable(widget, editable.cBool)
}
if let enableUndo, updateProperties, (storage.previousState as? Self)?.enableUndo != enableUndo {
gtk_editable_set_enable_undo(widget, enableUndo.cBool)
}
if let menu = storage.content["extraMenu"]?.first {
MenuCollection { extraMenu ?? [] }
.updateStorage(menu, data: data.noModifiers, updateProperties: updateProperties, type: MenuContext.self)
}
if let hasFrame, updateProperties, (storage.previousState as? Self)?.hasFrame != hasFrame {
gtk_entry_set_has_frame(widget?.cast(), hasFrame.cBool)
}
if let invisibleCharacter, updateProperties, (storage.previousState as? Self)?.invisibleCharacter != invisibleCharacter {
gtk_entry_set_invisible_char(widget?.cast(), invisibleCharacter.cInt)
}
if let maxLength, updateProperties, (storage.previousState as? Self)?.maxLength != maxLength {
gtk_entry_set_max_length(widget?.cast(), maxLength.cInt)
}
if let maxWidthChars, updateProperties, (storage.previousState as? Self)?.maxWidthChars != maxWidthChars {
gtk_editable_set_max_width_chars(widget, maxWidthChars.cInt)
}
if let overwriteMode, updateProperties, (storage.previousState as? Self)?.overwriteMode != overwriteMode {
gtk_entry_set_overwrite_mode(widget?.cast(), overwriteMode.cBool)
}
if let placeholderText, updateProperties, (storage.previousState as? Self)?.placeholderText != placeholderText {
gtk_entry_set_placeholder_text(widget?.cast(), placeholderText)
}
if let progressFraction, updateProperties, (storage.previousState as? Self)?.progressFraction != progressFraction {
gtk_entry_set_progress_fraction(widget?.cast(), progressFraction)
}
if let progressPulseStep, updateProperties, (storage.previousState as? Self)?.progressPulseStep != progressPulseStep {
gtk_entry_set_progress_pulse_step(widget?.cast(), progressPulseStep)
}
if let text, updateProperties, (String(cString: gtk_editable_get_text(storage.opaquePointer))) != text.wrappedValue {
gtk_editable_set_text(storage.opaquePointer, text.wrappedValue)
}
if let visibility, updateProperties, (storage.previousState as? Self)?.visibility != visibility {
gtk_entry_set_visibility(widget?.cast(), visibility.cBool)
}
if let widthChars, updateProperties, (storage.previousState as? Self)?.widthChars != widthChars {
gtk_editable_set_width_chars(widget, widthChars.cInt)
}
if let xalign, updateProperties, (storage.previousState as? Self)?.xalign != xalign {
gtk_editable_set_alignment(widget, xalign)
}
}
for function in updateFunctions {
function(storage, data, updateProperties)
}
if updateProperties {
storage.previousState = self
}
}
/// The accessible role of the given `GtkAccessible` implementation.
///
/// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self {
modify { $0.accessibleRole = accessibleRole }
}
/// The current position of the insertion cursor in chars.
public func cursorPosition(_ cursorPosition: Int?) -> Self {
modify { $0.cursorPosition = cursorPosition }
}
/// Whether the entry contents can be edited.
public func editable(_ editable: Bool? = true) -> Self {
modify { $0.editable = editable }
}
/// Indicates whether editing on the cell has been canceled.
public func editingCanceled(_ editingCanceled: Bool? = true) -> Self {
modify { $0.editingCanceled = editingCanceled }
}
/// Whether to suggest Emoji replacements for :-delimited names
/// like `:heart:`.
public func enableEmojiCompletion(_ enableEmojiCompletion: Bool? = true) -> Self {
modify { $0.enableEmojiCompletion = enableEmojiCompletion }
}
/// If undo/redo should be enabled for the editable.
public func enableUndo(_ enableUndo: Bool? = true) -> Self {
modify { $0.enableUndo = enableUndo }
}
/// A menu model whose contents will be appended to the context menu.
public func extraMenu(@ViewBuilder _ extraMenu: () -> Body) -> Self {
modify { $0.extraMenu = extraMenu() }
}
/// Whether the entry should draw a frame.
public func hasFrame(_ hasFrame: Bool? = true) -> Self {
modify { $0.hasFrame = hasFrame }
}
/// Which IM (input method) module should be used for this entry.
///
/// See `Gtk.IMContext`.
///
/// Setting this to a non-%NULL value overrides the system-wide IM
/// module setting. See the GtkSettings ``gtkImModule(_:)``
/// property.
public func imModule(_ imModule: String?) -> Self {
modify { $0.imModule = imModule }
}
/// The character to use when masking entry contents (password mode).
public func invisibleCharacter(_ invisibleCharacter: UInt?) -> Self {
modify { $0.invisibleCharacter = invisibleCharacter }
}
/// Whether the invisible char has been set for the `GtkEntry`.
public func invisibleCharacterSet(_ invisibleCharacterSet: Bool? = true) -> Self {
modify { $0.invisibleCharacterSet = invisibleCharacterSet }
}
/// Maximum number of characters for this entry.
public func maxLength(_ maxLength: Int?) -> Self {
modify { $0.maxLength = maxLength }
}
/// The desired maximum width of the entry, in characters.
public func maxWidthChars(_ maxWidthChars: Int?) -> Self {
modify { $0.maxWidthChars = maxWidthChars }
}
/// Text for an item in the context menu to activate the primary icon action.
///
/// When the primary icon is activatable and this property has been set, a new entry
/// in the context menu of this GtkEntry will appear with this text. Selecting that
/// menu entry will result in the primary icon being activated, exactly in the same way
/// as it would be activated from a mouse click.
///
/// This simplifies adding accessibility support to applications using activatable
/// icons. The activatable icons aren't focusable when navigating the interface with
/// the keyboard This is why Gtk recommends to also add those actions in the context
/// menu. This set of methods greatly simplifies this, by adding a menu item that, when
/// enabled, calls the same callback than clicking on the icon.
public func menuEntryIconPrimaryText(_ menuEntryIconPrimaryText: String?) -> Self {
modify { $0.menuEntryIconPrimaryText = menuEntryIconPrimaryText }
}
/// Text for an item in the context menu to activate the secondary icon action.
///
/// When the primary icon is activatable and this property has been set, a new entry
/// in the context menu of this GtkEntry will appear with this text. Selecting that
/// menu entry will result in the primary icon being activated, exactly in the same way
/// as it would be activated from a mouse click.
///
/// This simplifies adding accessibility support to applications using activatable
/// icons. The activatable icons aren't focusable when navigating the interface with
/// the keyboard This is why Gtk recommends to also add those actions in the context
/// menu. This set of methods greatly simplifies this, by adding a menu item that, when
/// enabled, calls the same callback than clicking on the icon.
public func menuEntryIconSecondaryText(_ menuEntryIconSecondaryText: String?) -> Self {
modify { $0.menuEntryIconSecondaryText = menuEntryIconSecondaryText }
}
/// If text is overwritten when typing in the `GtkEntry`.
public func overwriteMode(_ overwriteMode: Bool? = true) -> Self {
modify { $0.overwriteMode = overwriteMode }
}
/// The text that will be displayed in the `GtkEntry` when it is empty
/// and unfocused.
public func placeholderText(_ placeholderText: String?) -> Self {
modify { $0.placeholderText = placeholderText }
}
/// Whether the primary icon is activatable.
///
/// GTK emits the `Gtk.Entry::icon-press` and
/// `Gtk.Entry::icon-release` signals only on sensitive,
/// activatable icons.
///
/// Sensitive, but non-activatable icons can be used for purely
/// informational purposes.
public func primaryIconActivatable(_ primaryIconActivatable: Bool? = true) -> Self {
modify { $0.primaryIconActivatable = primaryIconActivatable }
}
/// The icon name to use for the primary icon for the entry.
public func primaryIconName(_ primaryIconName: String?) -> Self {
modify { $0.primaryIconName = primaryIconName }
}
/// Whether the primary icon is sensitive.
///
/// An insensitive icon appears grayed out. GTK does not emit the
/// `Gtk.Entry::icon-press` and `Gtk.Entry::icon-release`
/// signals and does not allow DND from insensitive icons.
///
/// An icon should be set insensitive if the action that would trigger
/// when clicked is currently not available.
public func primaryIconSensitive(_ primaryIconSensitive: Bool? = true) -> Self {
modify { $0.primaryIconSensitive = primaryIconSensitive }
}
/// The contents of the tooltip on the primary icon, with markup.
///
/// Also see `Gtk.Entry.set_icon_tooltip_markup`.
public func primaryIconTooltipMarkup(_ primaryIconTooltipMarkup: String?) -> Self {
modify { $0.primaryIconTooltipMarkup = primaryIconTooltipMarkup }
}
/// The contents of the tooltip on the primary icon.
///
/// Also see `Gtk.Entry.set_icon_tooltip_text`.
public func primaryIconTooltipText(_ primaryIconTooltipText: String?) -> Self {
modify { $0.primaryIconTooltipText = primaryIconTooltipText }
}
/// The current fraction of the task that's been completed.
public func progressFraction(_ progressFraction: Double?) -> Self {
modify { $0.progressFraction = progressFraction }
}
/// The fraction of total entry width to move the progress
/// bouncing block for each pulse.
///
/// See `Gtk.Entry.progress_pulse`.
public func progressPulseStep(_ progressPulseStep: Double?) -> Self {
modify { $0.progressPulseStep = progressPulseStep }
}
/// Number of pixels of the entry scrolled off the screen to the left.
public func scrollOffset(_ scrollOffset: Int?) -> Self {
modify { $0.scrollOffset = scrollOffset }
}
/// Whether the secondary icon is activatable.
///
/// GTK emits the `Gtk.Entry::icon-press` and
/// `Gtk.Entry::icon-release` signals only on sensitive,
/// activatable icons.
///
/// Sensitive, but non-activatable icons can be used for purely
/// informational purposes.
public func secondaryIconActivatable(_ secondaryIconActivatable: Bool? = true) -> Self {
modify { $0.secondaryIconActivatable = secondaryIconActivatable }
}
/// The icon name to use for the secondary icon for the entry.
public func secondaryIconName(_ secondaryIconName: String?) -> Self {
modify { $0.secondaryIconName = secondaryIconName }
}
/// Whether the secondary icon is sensitive.
///
/// An insensitive icon appears grayed out. GTK does not emit the
/// `Gtk.Entry::icon-press[ and [signal@Gtk.Entry::icon-release`
/// signals and does not allow DND from insensitive icons.
///
/// An icon should be set insensitive if the action that would trigger
/// when clicked is currently not available.
public func secondaryIconSensitive(_ secondaryIconSensitive: Bool? = true) -> Self {
modify { $0.secondaryIconSensitive = secondaryIconSensitive }
}
/// The contents of the tooltip on the secondary icon, with markup.
///
/// Also see `Gtk.Entry.set_icon_tooltip_markup`.
public func secondaryIconTooltipMarkup(_ secondaryIconTooltipMarkup: String?) -> Self {
modify { $0.secondaryIconTooltipMarkup = secondaryIconTooltipMarkup }
}
/// The contents of the tooltip on the secondary icon.
///
/// Also see `Gtk.Entry.set_icon_tooltip_text`.
public func secondaryIconTooltipText(_ secondaryIconTooltipText: String?) -> Self {
modify { $0.secondaryIconTooltipText = secondaryIconTooltipText }
}
/// The position of the opposite end of the selection from the cursor in chars.
public func selectionBound(_ selectionBound: Int?) -> Self {
modify { $0.selectionBound = selectionBound }
}
/// Whether the entry will show an Emoji icon in the secondary icon position
/// to open the Emoji chooser.
public func showEmojiIcon(_ showEmojiIcon: Bool? = true) -> Self {
modify { $0.showEmojiIcon = showEmojiIcon }
}
/// The contents of the entry.
public func text(_ text: Binding<String>?) -> Self {
modify { $0.text = text }
}
/// The length of the text in the `GtkEntry`.
public func textLength(_ textLength: UInt?) -> Self {
modify { $0.textLength = textLength }
}
/// When `true`, pasted multi-line text is truncated to the first line.
public func truncateMultiline(_ truncateMultiline: Bool? = true) -> Self {
modify { $0.truncateMultiline = truncateMultiline }
}
/// Whether the entry should show the invisible char instead of the
/// actual text (password mode).
public func visibility(_ visibility: Bool? = true) -> Self {
modify { $0.visibility = visibility }
}
/// Number of characters to leave space for in the entry.
public func widthChars(_ widthChars: Int?) -> Self {
modify { $0.widthChars = widthChars }
}
/// The horizontal alignment, from 0 (left) to 1 (right).
///
/// Reversed for RTL layouts.
public func xalign(_ xalign: Float?) -> Self {
modify { $0.xalign = xalign }
}
/// Emitted when the entry is activated.
///
/// The keybindings for this signal are all forms of the Enter key.
public func activate(_ activate: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.activate = activate
return newSelf
}
/// Emitted at the end of a single user-visible operation on the
/// contents.
///
/// E.g., a paste operation that replaces the contents of the
/// selection will cause only one signal emission (even though it
/// is implemented by first deleting the selection, then inserting
/// the new content, and may cause multiple ::notify::text signals
/// to be emitted).
public func changed(_ changed: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.changed = changed
return newSelf
}
/// Emitted when text is deleted from the widget by the user.
///
/// The default handler for this signal will normally be responsible for
/// deleting the text, so by connecting to this signal and then stopping
/// the signal with g_signal_stop_emission(), it is possible to modify the
/// range of deleted text, or prevent it from being deleted entirely.
///
/// The @start_pos and @end_pos parameters are interpreted as for
/// `Gtk.Editable.delete_text`.
public func deleteText(_ deleteText: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.deleteText = deleteText
return newSelf
}
/// This signal is a sign for the cell renderer to update its
/// value from the @cell_editable.
///
/// Implementations of `GtkCellEditable` are responsible for
/// emitting this signal when they are done editing, e.g.
/// `GtkEntry` emits this signal when the user presses Enter. Typical things to
/// do in a handler for ::editing-done are to capture the edited value,
/// disconnect the @cell_editable from signals on the `GtkCellRenderer`, etc.
///
/// gtk_cell_editable_editing_done() is a convenience method
/// for emitting `GtkCellEditable::editing-done`.
public func editingDone(_ editingDone: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.editingDone = editingDone
return newSelf
}
/// Emitted when an activatable icon is clicked.
public func iconPress(_ iconPress: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.iconPress = iconPress
return newSelf
}
/// Emitted on the button release from a mouse click
/// over an activatable icon.
public func iconRelease(_ iconRelease: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.iconRelease = iconRelease
return newSelf
}
/// Emitted when text is inserted into the widget by the user.
///
/// The default handler for this signal will normally be responsible
/// for inserting the text, so by connecting to this signal and then
/// stopping the signal with g_signal_stop_emission(), it is possible
/// to modify the inserted text, or prevent it from being inserted entirely.
public func insertText(_ insertText: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.insertText = insertText
return newSelf
}
/// This signal is meant to indicate that the cell is finished
/// editing, and the @cell_editable widget is being removed and may
/// subsequently be destroyed.
///
/// Implementations of `GtkCellEditable` are responsible for
/// emitting this signal when they are done editing. It must
/// be emitted after the `GtkCellEditable::editing-done` signal,
/// to give the cell renderer a chance to update the cell's value
/// before the widget is removed.
///
/// gtk_cell_editable_remove_widget() is a convenience method
/// for emitting `GtkCellEditable::remove-widget`.
public func removeWidget(_ removeWidget: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.removeWidget = removeWidget
return newSelf
}
}

View File

@ -2,49 +2,44 @@
// EntryRow.swift // EntryRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A [class@Gtk.ListBoxRow] with an embedded text entry. /// A `Gtk.ListBoxRow` with an embedded text entry.
///
/// ///
/// <picture><source srcset="entry-row-dark.png" media="(prefers-color-scheme: dark)"><img src="entry-row.png" alt="entry-row"></picture>
/// ///
/// `AdwEntryRow` has a title that doubles as placeholder text. It shows an icon /// `AdwEntryRow` has a title that doubles as placeholder text. It shows an icon
/// indicating that it's editable and can receive additional widgets before or /// indicating that it's editable and can receive additional widgets before or
/// after the editable part. /// after the editable part.
/// ///
/// If [property@EntryRow:show-apply-button] is set to `TRUE`, `AdwEntryRow` can /// If ``showApplyButton(_:)`` is set to `true`, `AdwEntryRow` can
/// show an apply button when editing its contents. This can be useful if /// show an apply button when editing its contents. This can be useful if
/// changing its contents can result in an expensive operation, such as network /// changing its contents can result in an expensive operation, such as network
/// activity. /// activity.
/// ///
/// `AdwEntryRow` provides only minimal API and should be used with the /// `AdwEntryRow` provides only minimal API and should be used with the
/// [iface@Gtk.Editable] API. /// `Gtk.Editable` API.
/// ///
/// See also [class@PasswordEntryRow]. /// See also `PasswordEntryRow`.
/// ///
/// ## AdwEntryRow as GtkBuildable
/// ///
/// The `AdwEntryRow` implementation of the [iface@Gtk.Buildable] interface
/// supports adding a child at its end by specifying suffix or omitting the
/// type attribute of a <child> element.
///
/// It also supports adding a child as a prefix widget by specifying prefix as
/// the type attribute of a <child> element.
///
/// ## CSS nodes
///
/// `AdwEntryRow` has a single CSS node with name `row` and the `.entry` style
/// class.
public struct EntryRow: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether activating the embedded entry can activate the default widget. /// Whether activating the embedded entry can activate the default widget.
var activatesDefault: Bool? var activatesDefault: Bool?
@ -52,11 +47,13 @@ public struct EntryRow: AdwaitaWidget {
/// ///
/// Emoji replacement is done with :-delimited names, like `:heart:`. /// Emoji replacement is done with :-delimited names, like `:heart:`.
var enableEmojiCompletion: Bool? var enableEmojiCompletion: Bool?
/// Maximum number of characters for the entry.
var maxLength: Int?
/// Whether to show the apply button. /// Whether to show the apply button.
/// ///
/// When set to `TRUE`, typing text in the entry will reveal an apply button. /// When set to `true`, typing text in the entry will reveal an apply button.
/// Clicking it or pressing the <kbd>Enter</kbd> key will hide the button and /// Clicking it or pressing the <kbd>Enter</kbd> key will hide the button and
/// emit the [signal@EntryRow::apply] signal. /// emit the `EntryRow::apply` signal.
/// ///
/// This is useful if changing the entry contents can trigger an expensive /// This is useful if changing the entry contents can trigger an expensive
/// operation, e.g. network activity, to avoid triggering it after typing every /// operation, e.g. network activity, to avoid triggering it after typing every
@ -67,23 +64,23 @@ public struct EntryRow: AdwaitaWidget {
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
var title: String? var title: String?
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
var titleSelectable: Bool? var titleSelectable: Bool?
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
var useMarkup: Bool? var useMarkup: Bool?
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
var useUnderline: Bool? var useUnderline: Bool?
/// Emitted when the apply button is pressed. /// Emitted when the apply button is pressed.
/// ///
/// See [property@EntryRow:show-apply-button]. /// See ``showApplyButton(_:)``.
var apply: (() -> Void)? var apply: (() -> Void)?
/// Emitted when the embedded entry is activated. /// Emitted when the embedded entry is activated.
var entryActivated: (() -> Void)? var entryActivated: (() -> Void)?
@ -93,7 +90,7 @@ public struct EntryRow: AdwaitaWidget {
var prefix: () -> Body = { [] } var prefix: () -> Body = { [] }
/// Initialize `EntryRow`. /// Initialize `EntryRow`.
public init() { init() {
} }
/// The view storage. /// The view storage.
@ -106,7 +103,6 @@ public struct EntryRow: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
var suffixStorage: [ViewStorage] = [] var suffixStorage: [ViewStorage] = []
for view in suffix() { for view in suffix() {
@ -148,6 +144,9 @@ public struct EntryRow: AdwaitaWidget {
if let enableEmojiCompletion, updateProperties, (storage.previousState as? Self)?.enableEmojiCompletion != enableEmojiCompletion { if let enableEmojiCompletion, updateProperties, (storage.previousState as? Self)?.enableEmojiCompletion != enableEmojiCompletion {
adw_entry_row_set_enable_emoji_completion(widget?.cast(), enableEmojiCompletion.cBool) adw_entry_row_set_enable_emoji_completion(widget?.cast(), enableEmojiCompletion.cBool)
} }
if let maxLength, updateProperties, (storage.previousState as? Self)?.maxLength != maxLength {
adw_entry_row_set_max_length(widget?.cast(), maxLength.cInt)
}
if let showApplyButton, updateProperties, (storage.previousState as? Self)?.showApplyButton != showApplyButton { if let showApplyButton, updateProperties, (storage.previousState as? Self)?.showApplyButton != showApplyButton {
adw_entry_row_set_show_apply_button(widget?.cast(), showApplyButton.cBool) adw_entry_row_set_show_apply_button(widget?.cast(), showApplyButton.cBool)
} }
@ -189,6 +188,7 @@ public struct EntryRow: AdwaitaWidget {
} }
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -200,90 +200,71 @@ public struct EntryRow: AdwaitaWidget {
/// Whether activating the embedded entry can activate the default widget. /// Whether activating the embedded entry can activate the default widget.
public func activatesDefault(_ activatesDefault: Bool? = true) -> Self { public func activatesDefault(_ activatesDefault: Bool? = true) -> Self {
var newSelf = self modify { $0.activatesDefault = activatesDefault }
newSelf.activatesDefault = activatesDefault
return newSelf
} }
/// Whether to suggest emoji replacements on the entry row. /// Whether to suggest emoji replacements on the entry row.
/// ///
/// Emoji replacement is done with :-delimited names, like `:heart:`. /// Emoji replacement is done with :-delimited names, like `:heart:`.
public func enableEmojiCompletion(_ enableEmojiCompletion: Bool? = true) -> Self { public func enableEmojiCompletion(_ enableEmojiCompletion: Bool? = true) -> Self {
var newSelf = self modify { $0.enableEmojiCompletion = enableEmojiCompletion }
newSelf.enableEmojiCompletion = enableEmojiCompletion }
return newSelf /// Maximum number of characters for the entry.
public func maxLength(_ maxLength: Int?) -> Self {
modify { $0.maxLength = maxLength }
} }
/// Whether to show the apply button. /// Whether to show the apply button.
/// ///
/// When set to `TRUE`, typing text in the entry will reveal an apply button. /// When set to `true`, typing text in the entry will reveal an apply button.
/// Clicking it or pressing the <kbd>Enter</kbd> key will hide the button and /// Clicking it or pressing the <kbd>Enter</kbd> key will hide the button and
/// emit the [signal@EntryRow::apply] signal. /// emit the `EntryRow::apply` signal.
/// ///
/// This is useful if changing the entry contents can trigger an expensive /// This is useful if changing the entry contents can trigger an expensive
/// operation, e.g. network activity, to avoid triggering it after typing every /// operation, e.g. network activity, to avoid triggering it after typing every
/// character. /// character.
public func showApplyButton(_ showApplyButton: Bool? = true) -> Self { public func showApplyButton(_ showApplyButton: Bool? = true) -> Self {
var newSelf = self modify { $0.showApplyButton = showApplyButton }
newSelf.showApplyButton = showApplyButton
return newSelf
} }
/// The length of the text in the entry row. /// The length of the text in the entry row.
public func textLength(_ textLength: UInt?) -> Self { public func textLength(_ textLength: UInt?) -> Self {
var newSelf = self modify { $0.textLength = textLength }
newSelf.textLength = textLength
return newSelf
} }
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
public func title(_ title: String?) -> Self { public func title(_ title: String?) -> Self {
var newSelf = self modify { $0.title = title }
newSelf.title = title
return newSelf
} }
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
public func titleSelectable(_ titleSelectable: Bool? = true) -> Self { public func titleSelectable(_ titleSelectable: Bool? = true) -> Self {
var newSelf = self modify { $0.titleSelectable = titleSelectable }
newSelf.titleSelectable = titleSelectable
return newSelf
} }
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
public func useMarkup(_ useMarkup: Bool? = true) -> Self { public func useMarkup(_ useMarkup: Bool? = true) -> Self {
var newSelf = self modify { $0.useMarkup = useMarkup }
newSelf.useMarkup = useMarkup
return newSelf
} }
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// Emitted when the apply button is pressed. /// Emitted when the apply button is pressed.
/// ///
/// See [property@EntryRow:show-apply-button]. /// See ``showApplyButton(_:)``.
public func apply(_ apply: @escaping () -> Void) -> Self { public func apply(_ apply: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.apply = apply newSelf.apply = apply

View File

@ -2,43 +2,34 @@
// ExpanderRow.swift // ExpanderRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A [class@Gtk.ListBoxRow] used to reveal widgets. /// A `Gtk.ListBoxRow` used to reveal widgets.
///
/// ///
/// <picture><source srcset="expander-row-dark.png" media="(prefers-color-scheme: dark)"><img src="expander-row.png" alt="expander-row"></picture>
/// ///
/// The `AdwExpanderRow` widget allows the user to reveal or hide widgets below /// The `AdwExpanderRow` widget allows the user to reveal or hide widgets below
/// it. It also allows the user to enable the expansion of the row, allowing to /// it. It also allows the user to enable the expansion of the row, allowing to
/// disable all that the row contains. /// disable all that the row contains.
/// ///
/// ## AdwExpanderRow as GtkBuildable
/// ///
/// The `AdwExpanderRow` implementation of the [iface@Gtk.Buildable] interface
/// supports adding a child as an suffix widget by specifying suffix as the
/// type attribute of a <child> element.
///
/// It also supports adding it as a prefix widget by specifying prefix as the
/// type attribute of a <child> element.
///
/// ## CSS nodes
///
/// `AdwExpanderRow` has a main CSS node with name `row` and the `.expander`
/// style class. It has the `.empty` style class when it contains no children.
///
/// It contains the subnodes `row.header` for its main embedded row,
/// `list.nested` for the list it can expand, and `image.expander-row-arrow` for
/// its arrow.
public struct ExpanderRow: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether expansion is enabled. /// Whether expansion is enabled.
var enableExpansion: Binding<Bool>? var enableExpansion: Binding<Bool>?
@ -49,7 +40,7 @@ public struct ExpanderRow: AdwaitaWidget {
/// The subtitle for this row. /// The subtitle for this row.
/// ///
/// The subtitle is interpreted as Pango markup unless /// The subtitle is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
var subtitle: String? var subtitle: String?
/// The number of lines at the end of which the subtitle label will be /// The number of lines at the end of which the subtitle label will be
/// ellipsized. /// ellipsized.
@ -59,7 +50,7 @@ public struct ExpanderRow: AdwaitaWidget {
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
var title: String? var title: String?
/// The number of lines at the end of which the title label will be ellipsized. /// The number of lines at the end of which the title label will be ellipsized.
/// ///
@ -67,13 +58,13 @@ public struct ExpanderRow: AdwaitaWidget {
var titleLines: Int? var titleLines: Int?
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
var titleSelectable: Bool? var titleSelectable: Bool?
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
var useMarkup: Bool? var useMarkup: Bool?
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
var useUnderline: Bool? var useUnderline: Bool?
@ -98,7 +89,6 @@ public struct ExpanderRow: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
var rowsStorage: [ViewStorage] = [] var rowsStorage: [ViewStorage] = []
for view in rows() { for view in rows() {
@ -210,6 +200,7 @@ if let expanded, newValue != expanded.wrappedValue {
} }
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -221,37 +212,25 @@ if let expanded, newValue != expanded.wrappedValue {
/// Whether expansion is enabled. /// Whether expansion is enabled.
public func enableExpansion(_ enableExpansion: Binding<Bool>?) -> Self { public func enableExpansion(_ enableExpansion: Binding<Bool>?) -> Self {
var newSelf = self modify { $0.enableExpansion = enableExpansion }
newSelf.enableExpansion = enableExpansion
return newSelf
} }
/// Whether the row is expanded. /// Whether the row is expanded.
public func expanded(_ expanded: Binding<Bool>?) -> Self { public func expanded(_ expanded: Binding<Bool>?) -> Self {
var newSelf = self modify { $0.expanded = expanded }
newSelf.expanded = expanded
return newSelf
} }
/// Whether the switch enabling the expansion is visible. /// Whether the switch enabling the expansion is visible.
public func showEnableSwitch(_ showEnableSwitch: Bool? = true) -> Self { public func showEnableSwitch(_ showEnableSwitch: Bool? = true) -> Self {
var newSelf = self modify { $0.showEnableSwitch = showEnableSwitch }
newSelf.showEnableSwitch = showEnableSwitch
return newSelf
} }
/// The subtitle for this row. /// The subtitle for this row.
/// ///
/// The subtitle is interpreted as Pango markup unless /// The subtitle is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
public func subtitle(_ subtitle: String?) -> Self { public func subtitle(_ subtitle: String?) -> Self {
var newSelf = self modify { $0.subtitle = subtitle }
newSelf.subtitle = subtitle
return newSelf
} }
/// The number of lines at the end of which the subtitle label will be /// The number of lines at the end of which the subtitle label will be
@ -259,61 +238,43 @@ if let expanded, newValue != expanded.wrappedValue {
/// ///
/// If the value is 0, the number of lines won't be limited. /// If the value is 0, the number of lines won't be limited.
public func subtitleLines(_ subtitleLines: Int?) -> Self { public func subtitleLines(_ subtitleLines: Int?) -> Self {
var newSelf = self modify { $0.subtitleLines = subtitleLines }
newSelf.subtitleLines = subtitleLines
return newSelf
} }
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
public func title(_ title: String?) -> Self { public func title(_ title: String?) -> Self {
var newSelf = self modify { $0.title = title }
newSelf.title = title
return newSelf
} }
/// The number of lines at the end of which the title label will be ellipsized. /// The number of lines at the end of which the title label will be ellipsized.
/// ///
/// If the value is 0, the number of lines won't be limited. /// If the value is 0, the number of lines won't be limited.
public func titleLines(_ titleLines: Int?) -> Self { public func titleLines(_ titleLines: Int?) -> Self {
var newSelf = self modify { $0.titleLines = titleLines }
newSelf.titleLines = titleLines
return newSelf
} }
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
public func titleSelectable(_ titleSelectable: Bool? = true) -> Self { public func titleSelectable(_ titleSelectable: Bool? = true) -> Self {
var newSelf = self modify { $0.titleSelectable = titleSelectable }
newSelf.titleSelectable = titleSelectable
return newSelf
} }
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
public func useMarkup(_ useMarkup: Bool? = true) -> Self { public func useMarkup(_ useMarkup: Bool? = true) -> Self {
var newSelf = self modify { $0.useMarkup = useMarkup }
newSelf.useMarkup = useMarkup
return newSelf
} }
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// Set the body for "rows". /// Set the body for "rows".

View File

@ -2,13 +2,13 @@
// Fixed.swift // Fixed.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// `GtkFixed` places its child widgets at fixed positions and with fixed sizes. /// Places its child widgets at fixed positions and with fixed sizes.
/// ///
/// `GtkFixed` performs no automatic layout management. /// `GtkFixed` performs no automatic layout management.
/// ///
@ -47,10 +47,17 @@ import LevenshteinTransformations
/// widget. But you should be aware of the tradeoffs. /// widget. But you should be aware of the tradeoffs.
public struct Fixed: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
@ -71,7 +78,6 @@ public struct Fixed: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -87,6 +93,7 @@ public struct Fixed: AdwaitaWidget {
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -100,10 +107,7 @@ public struct Fixed: AdwaitaWidget {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
} }

View File

@ -2,13 +2,15 @@
// FlowBox.swift // FlowBox.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A `GtkFlowBox` puts child widgets in reflowing grid. /// Puts child widgets in a reflowing grid.
///
///
/// ///
/// For instance, with the horizontal orientation, the widgets will be /// For instance, with the horizontal orientation, the widgets will be
/// arranged from left to right, starting a new row under the previous /// arranged from left to right, starting a new row under the previous
@ -28,38 +30,28 @@ import LevenshteinTransformations
/// The children of a `GtkFlowBox` can be dynamically sorted and filtered. /// The children of a `GtkFlowBox` can be dynamically sorted and filtered.
/// ///
/// Although a `GtkFlowBox` must have only `GtkFlowBoxChild` children, you /// Although a `GtkFlowBox` must have only `GtkFlowBoxChild` children, you
/// can add any kind of widget to it via [method@Gtk.FlowBox.insert], and a /// can add any kind of widget to it via `Gtk.FlowBox.insert`, and a
/// `GtkFlowBoxChild` widget will automatically be inserted between the box /// `GtkFlowBoxChild` widget will automatically be inserted between the box
/// and the widget. /// and the widget.
/// ///
/// Also see [class@Gtk.ListBox]. /// Also see `Gtk.ListBox`.
/// ///
/// # CSS nodes
/// ///
/// ``` public struct FlowBox<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
/// flowbox
/// flowboxchild
/// <child> flowboxchild
/// <child>
/// [rubberband]
/// ```
///
/// `GtkFlowBox` uses a single CSS node with name flowbox. `GtkFlowBoxChild`
/// uses a single CSS node with name flowboxchild. For rubberband selection,
/// a subnode with name rubberband is used.
///
/// # Accessibility
///
/// `GtkFlowBox` uses the %GTK_ACCESSIBLE_ROLE_GRID role, and `GtkFlowBoxChild`
/// uses the %GTK_ACCESSIBLE_ROLE_GRID_CELL role.
public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
#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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// accept-unpaired-release /// Whether to accept unpaired release events.
var acceptUnpairedRelease: Bool? var acceptUnpairedRelease: Bool?
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
@ -117,8 +109,8 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
var selectAll: (() -> Void)? var selectAll: (() -> Void)?
/// Emitted when the set of selected children changes. /// Emitted when the set of selected children changes.
/// ///
/// Use [method@Gtk.FlowBox.selected_foreach] or /// Use `Gtk.FlowBox.selected_foreach` or
/// [method@Gtk.FlowBox.get_selected_children] to obtain the /// `Gtk.FlowBox.get_selected_children` to obtain the
/// selected children. /// selected children.
var selectedChildrenChanged: (() -> Void)? var selectedChildrenChanged: (() -> Void)?
/// Emitted to toggle the selection of the child that has the focus. /// Emitted to toggle the selection of the child that has the focus.
@ -138,11 +130,14 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
var elements: [Element] var elements: [Element]
/// The dynamic widget content. /// The dynamic widget content.
var content: (Element) -> Body var content: (Element) -> Body
/// The dynamic widget identifier key path.
var id: KeyPath<Element, Identifier>
/// Initialize `FlowBox`. /// Initialize `FlowBox`.
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) { init(_ elements: [Element], id: KeyPath<Element, Identifier>, @ViewBuilder content: @escaping (Element) -> Body) {
self.elements = elements self.elements = elements
self.content = content self.content = content
self.id = id
} }
/// The view storage. /// The view storage.
@ -155,7 +150,6 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -225,15 +219,10 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? [] var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? [] let old = storage.fields["element"] as? [Element] ?? []
old.identifiableTransform( old.transform(
to: elements, to: elements,
functions: .init { index, element in id: id,
let child = content(element).storage(data: data, type: type) functions: .init { index in
gtk_flow_box_remove(widget, gtk_flow_box_get_child_at_index(widget, index.cInt)?.cast())
gtk_flow_box_insert(widget, child.opaquePointer?.cast(), index.cInt)
contentStorage.remove(at: index)
contentStorage.insert(child, at: index)
} delete: { index in
gtk_flow_box_remove(widget, gtk_flow_box_get_child_at_index(widget, index.cInt)?.cast()) gtk_flow_box_remove(widget, gtk_flow_box_get_child_at_index(widget, index.cInt)?.cast())
contentStorage.remove(at: index) contentStorage.remove(at: index)
} insert: { index, element in } insert: { index, element in
@ -247,6 +236,7 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
for (index, element) in elements.enumerated() { for (index, element) in elements.enumerated() {
content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type) content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type)
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -256,57 +246,39 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
} }
} }
/// accept-unpaired-release /// Whether to accept unpaired release events.
public func acceptUnpairedRelease(_ acceptUnpairedRelease: Bool? = true) -> Self { public func acceptUnpairedRelease(_ acceptUnpairedRelease: Bool? = true) -> Self {
var newSelf = self modify { $0.acceptUnpairedRelease = acceptUnpairedRelease }
newSelf.acceptUnpairedRelease = acceptUnpairedRelease
return newSelf
} }
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// Determines whether children can be activated with a single /// Determines whether children can be activated with a single
/// click, or require a double-click. /// click, or require a double-click.
public func activateOnSingleClick(_ activateOnSingleClick: Bool? = true) -> Self { public func activateOnSingleClick(_ activateOnSingleClick: Bool? = true) -> Self {
var newSelf = self modify { $0.activateOnSingleClick = activateOnSingleClick }
newSelf.activateOnSingleClick = activateOnSingleClick
return newSelf
} }
/// The amount of horizontal space between two children. /// The amount of horizontal space between two children.
public func columnSpacing(_ columnSpacing: UInt?) -> Self { public func columnSpacing(_ columnSpacing: UInt?) -> Self {
var newSelf = self modify { $0.columnSpacing = columnSpacing }
newSelf.columnSpacing = columnSpacing
return newSelf
} }
/// Determines whether all children should be allocated the /// Determines whether all children should be allocated the
/// same size. /// same size.
public func homogeneous(_ homogeneous: Bool? = true) -> Self { public func homogeneous(_ homogeneous: Bool? = true) -> Self {
var newSelf = self modify { $0.homogeneous = homogeneous }
newSelf.homogeneous = homogeneous
return newSelf
} }
/// The maximum amount of children to request space for consecutively /// The maximum amount of children to request space for consecutively
/// in the given orientation. /// in the given orientation.
public func maxChildrenPerLine(_ maxChildrenPerLine: UInt?) -> Self { public func maxChildrenPerLine(_ maxChildrenPerLine: UInt?) -> Self {
var newSelf = self modify { $0.maxChildrenPerLine = maxChildrenPerLine }
newSelf.maxChildrenPerLine = maxChildrenPerLine
return newSelf
} }
/// The minimum number of children to allocate consecutively /// The minimum number of children to allocate consecutively
@ -316,18 +288,12 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
/// that a reasonably small height will be requested /// that a reasonably small height will be requested
/// for the overall minimum width of the box. /// for the overall minimum width of the box.
public func minChildrenPerLine(_ minChildrenPerLine: UInt?) -> Self { public func minChildrenPerLine(_ minChildrenPerLine: UInt?) -> Self {
var newSelf = self modify { $0.minChildrenPerLine = minChildrenPerLine }
newSelf.minChildrenPerLine = minChildrenPerLine
return newSelf
} }
/// The amount of vertical space between two children. /// The amount of vertical space between two children.
public func rowSpacing(_ rowSpacing: UInt?) -> Self { public func rowSpacing(_ rowSpacing: UInt?) -> Self {
var newSelf = self modify { $0.rowSpacing = rowSpacing }
newSelf.rowSpacing = rowSpacing
return newSelf
} }
/// Emitted when the user activates the @box. /// Emitted when the user activates the @box.
@ -382,8 +348,8 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
/// Emitted when the set of selected children changes. /// Emitted when the set of selected children changes.
/// ///
/// Use [method@Gtk.FlowBox.selected_foreach] or /// Use `Gtk.FlowBox.selected_foreach` or
/// [method@Gtk.FlowBox.get_selected_children] to obtain the /// `Gtk.FlowBox.get_selected_children` to obtain the
/// selected children. /// selected children.
public func selectedChildrenChanged(_ selectedChildrenChanged: @escaping () -> Void) -> Self { public func selectedChildrenChanged(_ selectedChildrenChanged: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
@ -415,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 // HeaderBar.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,99 +10,31 @@ import LevenshteinTransformations
/// A title bar widget. /// A title bar widget.
/// ///
/// <picture><source srcset="header-bar-dark.png" media="(prefers-color-scheme: dark)"><img src="header-bar.png" alt="header-bar"></picture>
/// ///
/// `AdwHeaderBar` is similar to [class@Gtk.HeaderBar], but provides additional ///
/// `AdwHeaderBar` is similar to `Gtk.HeaderBar`, but provides additional
/// features compared to it. Refer to `GtkHeaderBar` for details. It is typically /// features compared to it. Refer to `GtkHeaderBar` for details. It is typically
/// used as a top bar within [class@ToolbarView]. /// used as a top bar within `ToolbarView`.
/// ///
/// ## Dialog Integration
/// ///
/// When placed inside an [class@Dialog], `AdwHeaderBar` will display the dialog
/// title intead of window title. It will also adjust the decoration layout to
/// ensure it always has a close button and nothing else. Set
/// [property@HeaderBar:show-start-title-buttons] and
/// [property@HeaderBar:show-end-title-buttons] to `FALSE` to remove it if it's
/// unwanted.
///
/// ## Navigation View Integration
///
/// When placed inside an [class@NavigationPage], `AdwHeaderBar` will display the
/// page title instead of window title.
///
/// When used together with [class@NavigationView] or [class@NavigationSplitView],
/// it will also display a back button that can be used to go back to the previous
/// page. The button also has a context menu, allowing to pop multiple pages at
/// once, potentially across multiple navigation views.
///
/// Set [property@HeaderBar:show-back-button] to `FALSE` to disable this behavior
/// in rare scenarios where it's unwanted.
///
/// ## Split View Integration
///
/// When placed inside [class@NavigationSplitView] or [class@OverlaySplitView],
/// `AdwHeaderBar` will automatically hide the title buttons other than at the
/// edges of the window.
///
/// ## Centering Policy
///
/// [property@HeaderBar:centering-policy] allows to enforce strict centering of
/// the title widget. This can be useful for entries inside [class@Clamp].
///
/// ## Title Buttons
///
/// Unlike `GtkHeaderBar`, `AdwHeaderBar` allows to toggle title button
/// visibility for each side individually, using the
/// [property@HeaderBar:show-start-title-buttons] and
/// [property@HeaderBar:show-end-title-buttons] properties.
///
/// ## CSS nodes
///
/// ```
/// headerbar
/// windowhandle
/// box
/// widget
/// box.start
/// windowcontrols.start
/// widget
/// [button.back]
/// [other children]
/// widget
/// [Title Widget]
/// widget
/// box.end
/// [other children]
/// windowcontrols.end
/// ```
///
/// `AdwHeaderBar`'s CSS node is called `headerbar`. It contains a `windowhandle`
/// subnode, which contains a `box` subnode, which contains three `widget`
/// subnodes at the start, center and end of the header bar. The start and end
/// subnotes contain a `box` subnode with the `.start` and `.end` style classes
/// respectively, and the center node contains a node that represents the title.
///
/// Each of the boxes contains a `windowcontrols` subnode, see
/// [class@Gtk.WindowControls] for details, as well as other children.
///
/// When [property@HeaderBar:show-back-button] is `TRUE`, the start box also
/// contains a node with the name `widget` that contains a node with the name
/// `button` and `.back` style class.
///
/// ## Accessibility
///
/// `AdwHeaderBar` uses the `GTK_ACCESSIBLE_ROLE_GROUP` role.
public struct HeaderBar: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The decoration layout for buttons. /// The decoration layout for buttons.
/// ///
/// If this property is not set, the /// If this property is not set, the
/// [property@Gtk.Settings:gtk-decoration-layout] setting is used. /// ``gtkDecorationLayout(_:)`` setting is used.
/// ///
/// The format of the string is button names, separated by commas. A colon /// The format of the string is button names, separated by commas. A colon
/// separates the buttons that should appear at the start from those at the /// separates the buttons that should appear at the start from those at the
@ -115,23 +47,23 @@ public struct HeaderBar: AdwaitaWidget {
/// Whether the header bar can show the back button. /// Whether the header bar can show the back button.
/// ///
/// The back button will never be shown unless the header bar is placed inside an /// The back button will never be shown unless the header bar is placed inside an
/// [class@NavigationView]. Usually, there is no reason to set this to `FALSE`. /// `NavigationView`. Usually, there is no reason to set this to `false`.
var showBackButton: Bool? var showBackButton: Bool?
/// Whether to show title buttons at the end of the header bar. /// Whether to show title buttons at the end of the header bar.
/// ///
/// See [property@HeaderBar:show-start-title-buttons] for the other side. /// See ``showStartTitleButtons(_:)`` for the other side.
/// ///
/// Which buttons are actually shown and where is determined by the /// Which buttons are actually shown and where is determined by the
/// [property@HeaderBar:decoration-layout] property, and by the state of the /// ``decorationLayout(_:)`` property, and by the state of the
/// window (e.g. a close button will not be shown if the window can't be /// window (e.g. a close button will not be shown if the window can't be
/// closed). /// closed).
var showEndTitleButtons: Bool? var showEndTitleButtons: Bool?
/// Whether to show title buttons at the start of the header bar. /// Whether to show title buttons at the start of the header bar.
/// ///
/// See [property@HeaderBar:show-end-title-buttons] for the other side. /// See ``showEndTitleButtons(_:)`` for the other side.
/// ///
/// Which buttons are actually shown and where is determined by the /// Which buttons are actually shown and where is determined by the
/// [property@HeaderBar:decoration-layout] property, and by the state of the /// ``decorationLayout(_:)`` property, and by the state of the
/// window (e.g. a close button will not be shown if the window can't be /// window (e.g. a close button will not be shown if the window can't be
/// closed). /// closed).
var showStartTitleButtons: Bool? var showStartTitleButtons: Bool?
@ -142,12 +74,12 @@ public struct HeaderBar: AdwaitaWidget {
/// When set to `NULL`, the header bar will display the title of the window it /// When set to `NULL`, the header bar will display the title of the window it
/// is contained in. /// is contained in.
/// ///
/// To use a different title, use [class@WindowTitle]: /// To use a different title, use `WindowTitle`:
/// ///
/// ```xml /// ```xml
/// <object class="AdwHeaderBar"><property name="title-widget"><object class="AdwWindowTitle"><property name="title" translatable="yes">Title</property></object></property></object> /// <object class="AdwHeaderBar"><property name="title-widget"><object class="AdwWindowTitle"><property name="title" translatable="yes">Title</property></object></property></object>
/// ``` /// ```
var titleWidget: (() -> Body)? var titleWidget: Body?
/// The body for the widget "start". /// The body for the widget "start".
var start: () -> Body = { [] } var start: () -> Body = { [] }
/// The body for the widget "end". /// The body for the widget "end".
@ -167,8 +99,7 @@ public struct HeaderBar: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let titleWidgetStorage = titleWidget?.storage(data: data, type: type) {
if let titleWidgetStorage = titleWidget?().storage(data: data, type: type) {
storage.content["titleWidget"] = [titleWidgetStorage] storage.content["titleWidget"] = [titleWidgetStorage]
adw_header_bar_set_title_widget(storage.opaquePointer, titleWidgetStorage.opaquePointer?.cast()) adw_header_bar_set_title_widget(storage.opaquePointer, titleWidgetStorage.opaquePointer?.cast())
} }
@ -213,7 +144,7 @@ public struct HeaderBar: AdwaitaWidget {
adw_header_bar_set_show_title(widget, showTitle.cBool) adw_header_bar_set_show_title(widget, showTitle.cBool)
} }
if let widget = storage.content["titleWidget"]?.first { if let widget = storage.content["titleWidget"]?.first {
titleWidget?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) titleWidget?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let startStorage = storage.content["start"] { if let startStorage = storage.content["start"] {
@ -241,6 +172,7 @@ public struct HeaderBar: AdwaitaWidget {
} }
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -253,7 +185,7 @@ public struct HeaderBar: AdwaitaWidget {
/// The decoration layout for buttons. /// The decoration layout for buttons.
/// ///
/// If this property is not set, the /// If this property is not set, the
/// [property@Gtk.Settings:gtk-decoration-layout] setting is used. /// ``gtkDecorationLayout(_:)`` setting is used.
/// ///
/// The format of the string is button names, separated by commas. A colon /// The format of the string is button names, separated by commas. A colon
/// separates the buttons that should appear at the start from those at the /// separates the buttons that should appear at the start from those at the
@ -263,59 +195,44 @@ public struct HeaderBar: AdwaitaWidget {
/// For example, icon:minimize,maximize,close specifies an icon at the start, /// For example, icon:minimize,maximize,close specifies an icon at the start,
/// and minimize, maximize and close buttons at the end. /// and minimize, maximize and close buttons at the end.
public func decorationLayout(_ decorationLayout: String?) -> Self { public func decorationLayout(_ decorationLayout: String?) -> Self {
var newSelf = self modify { $0.decorationLayout = decorationLayout }
newSelf.decorationLayout = decorationLayout
return newSelf
} }
/// Whether the header bar can show the back button. /// Whether the header bar can show the back button.
/// ///
/// The back button will never be shown unless the header bar is placed inside an /// The back button will never be shown unless the header bar is placed inside an
/// [class@NavigationView]. Usually, there is no reason to set this to `FALSE`. /// `NavigationView`. Usually, there is no reason to set this to `false`.
public func showBackButton(_ showBackButton: Bool? = true) -> Self { public func showBackButton(_ showBackButton: Bool? = true) -> Self {
var newSelf = self modify { $0.showBackButton = showBackButton }
newSelf.showBackButton = showBackButton
return newSelf
} }
/// Whether to show title buttons at the end of the header bar. /// Whether to show title buttons at the end of the header bar.
/// ///
/// See [property@HeaderBar:show-start-title-buttons] for the other side. /// See ``showStartTitleButtons(_:)`` for the other side.
/// ///
/// Which buttons are actually shown and where is determined by the /// Which buttons are actually shown and where is determined by the
/// [property@HeaderBar:decoration-layout] property, and by the state of the /// ``decorationLayout(_:)`` property, and by the state of the
/// window (e.g. a close button will not be shown if the window can't be /// window (e.g. a close button will not be shown if the window can't be
/// closed). /// closed).
public func showEndTitleButtons(_ showEndTitleButtons: Bool? = true) -> Self { public func showEndTitleButtons(_ showEndTitleButtons: Bool? = true) -> Self {
var newSelf = self modify { $0.showEndTitleButtons = showEndTitleButtons }
newSelf.showEndTitleButtons = showEndTitleButtons
return newSelf
} }
/// Whether to show title buttons at the start of the header bar. /// Whether to show title buttons at the start of the header bar.
/// ///
/// See [property@HeaderBar:show-end-title-buttons] for the other side. /// See ``showEndTitleButtons(_:)`` for the other side.
/// ///
/// Which buttons are actually shown and where is determined by the /// Which buttons are actually shown and where is determined by the
/// [property@HeaderBar:decoration-layout] property, and by the state of the /// ``decorationLayout(_:)`` property, and by the state of the
/// window (e.g. a close button will not be shown if the window can't be /// window (e.g. a close button will not be shown if the window can't be
/// closed). /// closed).
public func showStartTitleButtons(_ showStartTitleButtons: Bool? = true) -> Self { public func showStartTitleButtons(_ showStartTitleButtons: Bool? = true) -> Self {
var newSelf = self modify { $0.showStartTitleButtons = showStartTitleButtons }
newSelf.showStartTitleButtons = showStartTitleButtons
return newSelf
} }
/// Whether the title widget should be shown. /// Whether the title widget should be shown.
public func showTitle(_ showTitle: Bool? = true) -> Self { public func showTitle(_ showTitle: Bool? = true) -> Self {
var newSelf = self modify { $0.showTitle = showTitle }
newSelf.showTitle = showTitle
return newSelf
} }
/// The title widget to display. /// The title widget to display.
@ -323,16 +240,13 @@ public struct HeaderBar: AdwaitaWidget {
/// When set to `NULL`, the header bar will display the title of the window it /// When set to `NULL`, the header bar will display the title of the window it
/// is contained in. /// is contained in.
/// ///
/// To use a different title, use [class@WindowTitle]: /// To use a different title, use `WindowTitle`:
/// ///
/// ```xml /// ```xml
/// <object class="AdwHeaderBar"><property name="title-widget"><object class="AdwWindowTitle"><property name="title" translatable="yes">Title</property></object></property></object> /// <object class="AdwHeaderBar"><property name="title-widget"><object class="AdwWindowTitle"><property name="title" translatable="yes">Title</property></object></property></object>
/// ``` /// ```
public func titleWidget(@ViewBuilder _ titleWidget: @escaping (() -> Body)) -> Self { public func titleWidget(@ViewBuilder _ titleWidget: () -> Body) -> Self {
var newSelf = self modify { $0.titleWidget = titleWidget() }
newSelf.titleWidget = titleWidget
return newSelf
} }
/// Set the body for "start". /// Set the body for "start".

View File

@ -0,0 +1,168 @@
//
// Image.swift
// Adwaita
//
// Created by auto-generation on 04.02.26.
//
import CAdw
import LevenshteinTransformations
/// Displays an image.
///
///
///
/// Various kinds of object can be displayed as an image; most typically,
/// you would load a `GdkTexture` from a file, using the convenience function
/// `Gtk.Image.new_from_file`, for instance:
///
/// ```c
/// GtkWidget *image = gtk_image_new_from_file ("myfile.png");
/// ```
///
/// If the file isnt loaded successfully, the image will contain a
/// broken image icon similar to that used in many web browsers.
///
/// If you want to handle errors in loading the file yourself, for example
/// by displaying an error message, then load the image with an image
/// loading framework such as libglycin, then create the `GtkImage` with
/// `Gtk.Image.new_from_paintable`.
///
/// Sometimes an application will want to avoid depending on external data
/// files, such as image files. See the documentation of `GResource` inside
/// GIO, for details. In this case, ``resource(_:)``,
/// `Gtk.Image.new_from_resource`, and `Gtk.Image.set_from_resource`
/// should be used.
///
/// `GtkImage` displays its image as an icon, with a size that is determined
/// by the application. See `Gtk.Picture` if you want to show an image
/// at is actual size.
///
///
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.
///
/// The accessible role cannot be changed once set.
var accessibleRole: String?
/// The name of the icon in the icon theme.
///
/// If the icon theme is changed, the image will be updated automatically.
var iconName: String?
/// The size in pixels to display icons at.
///
/// If set to a value != -1, this property overrides the
/// ``iconSize(_:)`` property for images of type
/// `GTK_IMAGE_ICON_NAME`.
var pixelSize: Int?
/// A path to a resource file to display.
var resource: String?
/// The representation being used for image data.
var storageType: String?
/// Whether the icon displayed in the `GtkImage` will use
/// standard icon names fallback.
///
/// The value of this property is only relevant for images of type
/// %GTK_IMAGE_ICON_NAME and %GTK_IMAGE_GICON.
var useFallback: Bool?
/// Initialize `Image`.
public init() {
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The view render data type.
/// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let storage = ViewStorage(gtk_image_new()?.opaque())
for function in appearFunctions {
function(storage, data)
}
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.
public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) where Data: ViewRenderData {
storage.modify { widget in
if let iconName, updateProperties, (storage.previousState as? Self)?.iconName != iconName {
gtk_image_set_from_icon_name(widget, iconName)
}
if let pixelSize, updateProperties, (storage.previousState as? Self)?.pixelSize != pixelSize {
gtk_image_set_pixel_size(widget, pixelSize.cInt)
}
}
for function in updateFunctions {
function(storage, data, updateProperties)
}
if updateProperties {
storage.previousState = self
}
}
/// The accessible role of the given `GtkAccessible` implementation.
///
/// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self {
modify { $0.accessibleRole = accessibleRole }
}
/// The name of the icon in the icon theme.
///
/// If the icon theme is changed, the image will be updated automatically.
public func iconName(_ iconName: String?) -> Self {
modify { $0.iconName = iconName }
}
/// The size in pixels to display icons at.
///
/// If set to a value != -1, this property overrides the
/// ``iconSize(_:)`` property for images of type
/// `GTK_IMAGE_ICON_NAME`.
public func pixelSize(_ pixelSize: Int?) -> Self {
modify { $0.pixelSize = pixelSize }
}
/// A path to a resource file to display.
public func resource(_ resource: String?) -> Self {
modify { $0.resource = resource }
}
/// The representation being used for image data.
public func storageType(_ storageType: String?) -> Self {
modify { $0.storageType = storageType }
}
/// Whether the icon displayed in the `GtkImage` will use
/// standard icon names fallback.
///
/// The value of this property is only relevant for images of type
/// %GTK_IMAGE_ICON_NAME and %GTK_IMAGE_GICON.
public func useFallback(_ useFallback: Bool? = true) -> Self {
modify { $0.useFallback = useFallback }
}
}

View File

@ -0,0 +1,331 @@
//
// Label.swift
// Adwaita
//
// Created by auto-generation on 04.02.26.
//
import CAdw
import LevenshteinTransformations
/// Displays a small amount of text.
///
/// Most labels are used to label another widget (such as an `Entry`).
///
///
///
///
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.
///
/// The accessible role cannot be changed once set.
var accessibleRole: String?
/// The contents of the label.
///
/// If the string contains Pango markup (see `Pango.parse_markup`),
/// you will have to set the ``useMarkup(_:)`` property to
/// true in order for the label to display the markup attributes. See also
/// `Gtk.Label.set_markup` for a convenience function that sets both
/// this property and the ``useMarkup(_:)`` property at the
/// same time.
///
/// If the string contains underlines acting as mnemonics, you will have to
/// set the ``useUnderline(_:)`` property to true in order
/// for the label to display them.
var label: String
/// The number of lines to which an ellipsized, wrapping label
/// should display before it gets ellipsized. This both prevents the label
/// from ellipsizing before this many lines are displayed, and limits the
/// height request of the label to this many lines.
///
/// > [!WARNING]
/// > Setting this property has unintuitive and unfortunate consequences
/// for the minimum _width_ of the label. Specifically, if the height
/// of the label is such that it fits a smaller number of lines than
/// the value of this property, the label can not be ellipsized at all,
/// which means it must be wide enough to fit all the text fully.
///
/// This property has no effect if the label is not wrapping or ellipsized.
///
/// Set this property to -1 if you don't want to limit the number of lines.
var lines: Int?
/// The desired maximum width of the label, in characters.
///
/// If this property is set to -1, the width will be calculated automatically.
///
/// See the section on [text layout](class.Label.html
var maxWidthChars: Int?
/// The mnemonic accelerator key for the label.
var mnemonicKeyval: UInt?
/// The widget to be activated when the labels mnemonic key is pressed.
var mnemonicWidget: Body?
/// Whether the label text can be selected with the mouse.
var selectable: Bool?
/// Whether the label is in single line mode.
///
/// In single line mode, the height of the label does not depend on the
/// actual text, it is always set to ascent + descent of the font. This
/// can be an advantage in situations where resizing the label because
/// of text changes would be distracting, e.g. in a statusbar.
var singleLineMode: Bool?
/// True if the text of the label includes Pango markup.
///
/// See `Pango.parse_markup`.
var useMarkup: Bool?
/// True if the text of the label indicates a mnemonic with an `_`
/// before the mnemonic character.
var useUnderline: Bool?
/// The desired width of the label, in characters.
///
/// If this property is set to -1, the width will be calculated automatically.
///
/// See the section on [text layout](class.Label.html
var widthChars: Int?
/// True if the label text will wrap if it gets too wide.
var wrap: Bool?
/// The horizontal alignment of the label text inside its size allocation.
///
/// Compare this to ``halign(_:)``, which determines how the
/// labels size allocation is positioned in the space available for the label.
var xalign: Float?
/// The vertical alignment of the label text inside its size allocation.
///
/// Compare this to ``valign(_:)``, which determines how the
/// labels size allocation is positioned in the space available for the label.
var yalign: Float?
/// Gets emitted to copy the selection to the clipboard.
///
/// The `::copy-clipboard` signal is a [keybinding signal](class.SignalAction.html).
///
/// The default binding for this signal is <kbd>Ctrl</kbd>+<kbd>c</kbd>.
var copyClipboard: (() -> Void)?
/// Initialize `Label`.
public init(label: String) {
self.label = label
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The view render data type.
/// - Returns: The view storage.
public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
let storage = ViewStorage(gtk_label_new(label)?.opaque())
for function in appearFunctions {
function(storage, data)
}
if let mnemonicWidgetStorage = mnemonicWidget?.storage(data: data, type: type) {
storage.content["mnemonicWidget"] = [mnemonicWidgetStorage]
gtk_label_set_mnemonic_widget(storage.opaquePointer, mnemonicWidgetStorage.opaquePointer?.cast())
}
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.
public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) where Data: ViewRenderData {
if let copyClipboard {
storage.connectSignal(name: "copy-clipboard", argCount: 0) {
copyClipboard()
}
}
storage.modify { widget in
if updateProperties, (storage.previousState as? Self)?.label != label {
gtk_label_set_label(widget, label)
}
if let lines, updateProperties, (storage.previousState as? Self)?.lines != lines {
gtk_label_set_lines(widget, lines.cInt)
}
if let maxWidthChars, updateProperties, (storage.previousState as? Self)?.maxWidthChars != maxWidthChars {
gtk_label_set_max_width_chars(widget, maxWidthChars.cInt)
}
if let widget = storage.content["mnemonicWidget"]?.first {
mnemonicWidget?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
}
if let selectable, updateProperties, (storage.previousState as? Self)?.selectable != selectable {
gtk_label_set_selectable(widget, selectable.cBool)
}
if let singleLineMode, updateProperties, (storage.previousState as? Self)?.singleLineMode != singleLineMode {
gtk_label_set_single_line_mode(widget, singleLineMode.cBool)
}
if let useMarkup, updateProperties, (storage.previousState as? Self)?.useMarkup != useMarkup {
gtk_label_set_use_markup(widget, useMarkup.cBool)
}
if let useUnderline, updateProperties, (storage.previousState as? Self)?.useUnderline != useUnderline {
gtk_label_set_use_underline(widget, useUnderline.cBool)
}
if let widthChars, updateProperties, (storage.previousState as? Self)?.widthChars != widthChars {
gtk_label_set_width_chars(widget, widthChars.cInt)
}
if let wrap, updateProperties, (storage.previousState as? Self)?.wrap != wrap {
gtk_label_set_wrap(widget, wrap.cBool)
}
if let xalign, updateProperties, (storage.previousState as? Self)?.xalign != xalign {
gtk_label_set_xalign(widget, xalign)
}
if let yalign, updateProperties, (storage.previousState as? Self)?.yalign != yalign {
gtk_label_set_yalign(widget, yalign)
}
}
for function in updateFunctions {
function(storage, data, updateProperties)
}
if updateProperties {
storage.previousState = self
}
}
/// The accessible role of the given `GtkAccessible` implementation.
///
/// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self {
modify { $0.accessibleRole = accessibleRole }
}
/// The contents of the label.
///
/// If the string contains Pango markup (see `Pango.parse_markup`),
/// you will have to set the ``useMarkup(_:)`` property to
/// true in order for the label to display the markup attributes. See also
/// `Gtk.Label.set_markup` for a convenience function that sets both
/// this property and the ``useMarkup(_:)`` property at the
/// same time.
///
/// If the string contains underlines acting as mnemonics, you will have to
/// set the ``useUnderline(_:)`` property to true in order
/// for the label to display them.
public func label(_ label: String) -> Self {
modify { $0.label = label }
}
/// The number of lines to which an ellipsized, wrapping label
/// should display before it gets ellipsized. This both prevents the label
/// from ellipsizing before this many lines are displayed, and limits the
/// height request of the label to this many lines.
///
/// > [!WARNING]
/// > Setting this property has unintuitive and unfortunate consequences
/// for the minimum _width_ of the label. Specifically, if the height
/// of the label is such that it fits a smaller number of lines than
/// the value of this property, the label can not be ellipsized at all,
/// which means it must be wide enough to fit all the text fully.
///
/// This property has no effect if the label is not wrapping or ellipsized.
///
/// Set this property to -1 if you don't want to limit the number of lines.
public func lines(_ lines: Int?) -> Self {
modify { $0.lines = lines }
}
/// The desired maximum width of the label, in characters.
///
/// If this property is set to -1, the width will be calculated automatically.
///
/// See the section on [text layout](class.Label.html
public func maxWidthChars(_ maxWidthChars: Int?) -> Self {
modify { $0.maxWidthChars = maxWidthChars }
}
/// The mnemonic accelerator key for the label.
public func mnemonicKeyval(_ mnemonicKeyval: UInt?) -> Self {
modify { $0.mnemonicKeyval = mnemonicKeyval }
}
/// The widget to be activated when the labels mnemonic key is pressed.
public func mnemonicWidget(@ViewBuilder _ mnemonicWidget: () -> Body) -> Self {
modify { $0.mnemonicWidget = mnemonicWidget() }
}
/// Whether the label text can be selected with the mouse.
public func selectable(_ selectable: Bool? = true) -> Self {
modify { $0.selectable = selectable }
}
/// Whether the label is in single line mode.
///
/// In single line mode, the height of the label does not depend on the
/// actual text, it is always set to ascent + descent of the font. This
/// can be an advantage in situations where resizing the label because
/// of text changes would be distracting, e.g. in a statusbar.
public func singleLineMode(_ singleLineMode: Bool? = true) -> Self {
modify { $0.singleLineMode = singleLineMode }
}
/// True if the text of the label includes Pango markup.
///
/// See `Pango.parse_markup`.
public func useMarkup(_ useMarkup: Bool? = true) -> Self {
modify { $0.useMarkup = useMarkup }
}
/// True if the text of the label indicates a mnemonic with an `_`
/// before the mnemonic character.
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
modify { $0.useUnderline = useUnderline }
}
/// The desired width of the label, in characters.
///
/// If this property is set to -1, the width will be calculated automatically.
///
/// See the section on [text layout](class.Label.html
public func widthChars(_ widthChars: Int?) -> Self {
modify { $0.widthChars = widthChars }
}
/// True if the label text will wrap if it gets too wide.
public func wrap(_ wrap: Bool? = true) -> Self {
modify { $0.wrap = wrap }
}
/// The horizontal alignment of the label text inside its size allocation.
///
/// Compare this to ``halign(_:)``, which determines how the
/// labels size allocation is positioned in the space available for the label.
public func xalign(_ xalign: Float?) -> Self {
modify { $0.xalign = xalign }
}
/// The vertical alignment of the label text inside its size allocation.
///
/// Compare this to ``valign(_:)``, which determines how the
/// labels size allocation is positioned in the space available for the label.
public func yalign(_ yalign: Float?) -> Self {
modify { $0.yalign = yalign }
}
/// Gets emitted to copy the selection to the clipboard.
///
/// The `::copy-clipboard` signal is a [keybinding signal](class.SignalAction.html).
///
/// The default binding for this signal is <kbd>Ctrl</kbd>+<kbd>c</kbd>.
public func copyClipboard(_ copyClipboard: @escaping () -> Void) -> Self {
var newSelf = self
newSelf.copyClipboard = copyClipboard
return newSelf
}
}

View File

@ -2,21 +2,21 @@
// LevelBar.swift // LevelBar.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// `GtkLevelBar` is a widget that can be used as a level indicator. /// Shows a level indicator.
/// ///
/// Typical use cases are displaying the strength of a password, or /// Typical use cases are displaying the strength of a password, or
/// showing the charge level of a battery. /// showing the charge level of a battery.
/// ///
/// ![An example GtkLevelBar](levelbar.png)
/// ///
/// Use [method@Gtk.LevelBar.set_value] to set the current value, and ///
/// [method@Gtk.LevelBar.add_offset_value] to set the value offsets at which /// Use `Gtk.LevelBar.set_value` to set the current value, and
/// `Gtk.LevelBar.add_offset_value` to set the value offsets at which
/// the bar will be considered in a different state. GTK will add a few /// the bar will be considered in a different state. GTK will add a few
/// offsets by default on the level bar: %GTK_LEVEL_BAR_OFFSET_LOW, /// offsets by default on the level bar: %GTK_LEVEL_BAR_OFFSET_LOW,
/// %GTK_LEVEL_BAR_OFFSET_HIGH and %GTK_LEVEL_BAR_OFFSET_FULL, with /// %GTK_LEVEL_BAR_OFFSET_HIGH and %GTK_LEVEL_BAR_OFFSET_FULL, with
@ -26,91 +26,20 @@ import LevenshteinTransformations
/// when changing the minimum or maximum value. GTK will simply clamp /// when changing the minimum or maximum value. GTK will simply clamp
/// them to the new range. /// them to the new range.
/// ///
/// ## Adding a custom offset on the bar
/// ///
/// ```c
/// static GtkWidget *
/// create_level_bar (void)
/// {
/// GtkWidget *widget;
/// GtkLevelBar *bar;
///
/// widget = gtk_level_bar_new ();
/// bar = GTK_LEVEL_BAR (widget);
///
/// // This changes the value of the default low offset
///
/// gtk_level_bar_add_offset_value (bar,
/// GTK_LEVEL_BAR_OFFSET_LOW,
/// 0.10);
///
/// // This adds a new offset to the bar; the application will
/// // be able to change its color CSS like this:
/// //
/// // levelbar block.my-offset {
/// // background-color: magenta;
/// // border-style: solid;
/// // border-color: black;
/// // border-width: 1px;
/// // }
///
/// gtk_level_bar_add_offset_value (bar, "my-offset", 0.60);
///
/// return widget;
/// }
/// ```
///
/// The default interval of values is between zero and one, but its possible
/// to modify the interval using [method@Gtk.LevelBar.set_min_value] and
/// [method@Gtk.LevelBar.set_max_value]. The value will be always drawn in
/// proportion to the admissible interval, i.e. a value of 15 with a specified
/// interval between 10 and 20 is equivalent to a value of 0.5 with an interval
/// between 0 and 1. When %GTK_LEVEL_BAR_MODE_DISCRETE is used, the bar level
/// is rendered as a finite number of separated blocks instead of a single one.
/// The number of blocks that will be rendered is equal to the number of units
/// specified by the admissible interval.
///
/// For instance, to build a bar rendered with five blocks, its sufficient to
/// set the minimum value to 0 and the maximum value to 5 after changing the
/// indicator mode to discrete.
///
/// # GtkLevelBar as GtkBuildable
///
/// The `GtkLevelBar` implementation of the `GtkBuildable` interface supports a
/// custom `<offsets>` element, which can contain any number of `<offset>` elements,
/// each of which must have "name" and "value" attributes.
///
/// # CSS nodes
///
/// ```
/// levelbar[.discrete]
/// trough
/// block.filled.level-name
///
/// block.empty
///
/// ```
///
/// `GtkLevelBar` has a main CSS node with name levelbar and one of the style
/// classes .discrete or .continuous and a subnode with name trough. Below the
/// trough node are a number of nodes with name block and style class .filled
/// or .empty. In continuous mode, there is exactly one node of each, in discrete
/// mode, the number of filled and unfilled nodes corresponds to blocks that are
/// drawn. The block.filled nodes also get a style class .level-name corresponding
/// to the level for the current value.
///
/// In horizontal orientation, the nodes are always arranged from left to right,
/// regardless of text direction.
///
/// # Accessibility
///
/// `GtkLevelBar` uses the %GTK_ACCESSIBLE_ROLE_METER role.
public struct LevelBar: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
@ -129,7 +58,7 @@ public struct LevelBar: AdwaitaWidget {
var value: Double? var value: Double?
/// Emitted when an offset specified on the bar changes value. /// Emitted when an offset specified on the bar changes value.
/// ///
/// This typically is the result of a [method@Gtk.LevelBar.add_offset_value] /// This typically is the result of a `Gtk.LevelBar.add_offset_value`
/// call. /// call.
/// ///
/// The signal supports detailed connections; you can connect to the /// The signal supports detailed connections; you can connect to the
@ -151,7 +80,6 @@ public struct LevelBar: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -184,6 +112,7 @@ public struct LevelBar: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -197,10 +126,7 @@ public struct LevelBar: AdwaitaWidget {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// Whether the `GtkLeveBar` is inverted. /// Whether the `GtkLeveBar` is inverted.
@ -208,39 +134,27 @@ public struct LevelBar: AdwaitaWidget {
/// Level bars normally grow from top to bottom or left to right. /// Level bars normally grow from top to bottom or left to right.
/// Inverted level bars grow in the opposite direction. /// Inverted level bars grow in the opposite direction.
public func inverted(_ inverted: Bool? = true) -> Self { public func inverted(_ inverted: Bool? = true) -> Self {
var newSelf = self modify { $0.inverted = inverted }
newSelf.inverted = inverted
return newSelf
} }
/// Determines the maximum value of the interval that can be displayed by the bar. /// Determines the maximum value of the interval that can be displayed by the bar.
public func maxValue(_ maxValue: Double?) -> Self { public func maxValue(_ maxValue: Double?) -> Self {
var newSelf = self modify { $0.maxValue = maxValue }
newSelf.maxValue = maxValue
return newSelf
} }
/// Determines the minimum value of the interval that can be displayed by the bar. /// Determines the minimum value of the interval that can be displayed by the bar.
public func minValue(_ minValue: Double?) -> Self { public func minValue(_ minValue: Double?) -> Self {
var newSelf = self modify { $0.minValue = minValue }
newSelf.minValue = minValue
return newSelf
} }
/// Determines the currently filled value of the level bar. /// Determines the currently filled value of the level bar.
public func value(_ value: Double?) -> Self { public func value(_ value: Double?) -> Self {
var newSelf = self modify { $0.value = value }
newSelf.value = value
return newSelf
} }
/// Emitted when an offset specified on the bar changes value. /// Emitted when an offset specified on the bar changes value.
/// ///
/// This typically is the result of a [method@Gtk.LevelBar.add_offset_value] /// This typically is the result of a `Gtk.LevelBar.add_offset_value`
/// call. /// call.
/// ///
/// The signal supports detailed connections; you can connect to the /// The signal supports detailed connections; you can connect to the

View File

@ -2,50 +2,50 @@
// LinkButton.swift // LinkButton.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A `GtkLinkButton` is a button with a hyperlink. /// A button with a hyperlink.
///
/// ///
/// ![An example GtkLinkButton](link-button.png)
/// ///
/// It is useful to show quick links to resources. /// It is useful to show quick links to resources.
/// ///
/// A link button is created by calling either [ctor@Gtk.LinkButton.new] or /// A link button is created by calling either `Gtk.LinkButton.new` or
/// [ctor@Gtk.LinkButton.new_with_label]. If using the former, the URI you /// `Gtk.LinkButton.new_with_label`. If using the former, the URI you
/// pass to the constructor is used as a label for the widget. /// pass to the constructor is used as a label for the widget.
/// ///
/// The URI bound to a `GtkLinkButton` can be set specifically using /// The URI bound to a `GtkLinkButton` can be set specifically using
/// [method@Gtk.LinkButton.set_uri]. /// `Gtk.LinkButton.set_uri`.
/// ///
/// By default, `GtkLinkButton` calls [method@Gtk.FileLauncher.launch] when the button /// By default, `GtkLinkButton` calls `Gtk.FileLauncher.launch` when the button
/// is clicked. This behaviour can be overridden by connecting to the /// is clicked. This behaviour can be overridden by connecting to the
/// [signal@Gtk.LinkButton::activate-link] signal and returning %TRUE from /// `Gtk.LinkButton::activate-link` signal and returning `true` from
/// the signal handler. /// the signal handler.
/// ///
/// # CSS nodes
/// ///
/// `GtkLinkButton` has a single CSS node with name button. To differentiate
/// it from a plain `GtkButton`, it gets the .link style class.
///
/// # Accessibility
///
/// `GtkLinkButton` uses the %GTK_ACCESSIBLE_ROLE_LINK role.
public struct LinkButton: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
var accessibleRole: String? var accessibleRole: String?
/// action-name /// The name of the action with which this widget should be associated.
var actionName: String? var actionName: String?
/// Whether the size of the button can be made smaller than the natural /// Whether the size of the button can be made smaller than the natural
/// size of its contents. /// size of its contents.
@ -56,7 +56,7 @@ public struct LinkButton: AdwaitaWidget {
/// property has no effect. /// property has no effect.
var canShrink: Bool? var canShrink: Bool?
/// The child widget. /// The child widget.
var child: (() -> Body)? var child: Body?
/// Whether the button has a frame. /// Whether the button has a frame.
var hasFrame: Bool? var hasFrame: Bool?
/// The name of the icon used to automatically populate the button. /// The name of the icon used to automatically populate the button.
@ -75,7 +75,7 @@ public struct LinkButton: AdwaitaWidget {
/// Emitted to animate press then release. /// Emitted to animate press then release.
/// ///
/// This is an action signal. Applications should never connect /// This is an action signal. Applications should never connect
/// to this signal, but use the [signal@Gtk.Button::clicked] signal. /// to this signal, but use the `Gtk.Button::clicked` signal.
/// ///
/// The default bindings for this signal are all forms of the /// The default bindings for this signal are all forms of the
/// <kbd></kbd> and <kbd>Enter</kbd> keys. /// <kbd></kbd> and <kbd>Enter</kbd> keys.
@ -98,8 +98,7 @@ public struct LinkButton: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let childStorage = child?.storage(data: data, type: type) {
if let childStorage = child?().storage(data: data, type: type) {
storage.content["child"] = [childStorage] storage.content["child"] = [childStorage]
gtk_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast()) gtk_button_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())
} }
@ -133,7 +132,7 @@ public struct LinkButton: AdwaitaWidget {
gtk_button_set_can_shrink(widget?.cast(), canShrink.cBool) gtk_button_set_can_shrink(widget?.cast(), canShrink.cBool)
} }
if let widget = storage.content["child"]?.first { if let widget = storage.content["child"]?.first {
child?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) child?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let hasFrame, updateProperties, (storage.previousState as? Self)?.hasFrame != hasFrame { if let hasFrame, updateProperties, (storage.previousState as? Self)?.hasFrame != hasFrame {
gtk_button_set_has_frame(widget?.cast(), hasFrame.cBool) gtk_button_set_has_frame(widget?.cast(), hasFrame.cBool)
@ -155,6 +154,7 @@ public struct LinkButton: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -168,18 +168,12 @@ public struct LinkButton: AdwaitaWidget {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// action-name /// The name of the action with which this widget should be associated.
public func actionName(_ actionName: String?) -> Self { public func actionName(_ actionName: String?) -> Self {
var newSelf = self modify { $0.actionName = actionName }
newSelf.actionName = actionName
return newSelf
} }
/// Whether the size of the button can be made smaller than the natural /// Whether the size of the button can be made smaller than the natural
@ -190,75 +184,51 @@ public struct LinkButton: AdwaitaWidget {
/// If the contents of a button are an icon or a custom widget, setting this /// If the contents of a button are an icon or a custom widget, setting this
/// property has no effect. /// property has no effect.
public func canShrink(_ canShrink: Bool? = true) -> Self { public func canShrink(_ canShrink: Bool? = true) -> Self {
var newSelf = self modify { $0.canShrink = canShrink }
newSelf.canShrink = canShrink
return newSelf
} }
/// The child widget. /// The child widget.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self { public func child(@ViewBuilder _ child: () -> Body) -> Self {
var newSelf = self modify { $0.child = child() }
newSelf.child = child
return newSelf
} }
/// Whether the button has a frame. /// Whether the button has a frame.
public func hasFrame(_ hasFrame: Bool? = true) -> Self { public func hasFrame(_ hasFrame: Bool? = true) -> Self {
var newSelf = self modify { $0.hasFrame = hasFrame }
newSelf.hasFrame = hasFrame
return newSelf
} }
/// The name of the icon used to automatically populate the button. /// The name of the icon used to automatically populate the button.
public func iconName(_ iconName: String?) -> Self { public func iconName(_ iconName: String?) -> Self {
var newSelf = self modify { $0.iconName = iconName }
newSelf.iconName = iconName
return newSelf
} }
/// Text of the label inside the button, if the button contains a label widget. /// Text of the label inside the button, if the button contains a label widget.
public func label(_ label: String?) -> Self { public func label(_ label: String?) -> Self {
var newSelf = self modify { $0.label = label }
newSelf.label = label
return newSelf
} }
/// The URI bound to this button. /// The URI bound to this button.
public func uri(_ uri: String) -> Self { public func uri(_ uri: String) -> Self {
var newSelf = self modify { $0.uri = uri }
newSelf.uri = uri
return newSelf
} }
/// If set, an underline in the text indicates that the following character is /// If set, an underline in the text indicates that the following character is
/// to be used as mnemonic. /// to be used as mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// The 'visited' state of this button. /// The 'visited' state of this button.
/// ///
/// A visited link is drawn in a different color. /// A visited link is drawn in a different color.
public func visited(_ visited: Bool? = true) -> Self { public func visited(_ visited: Bool? = true) -> Self {
var newSelf = self modify { $0.visited = visited }
newSelf.visited = visited
return newSelf
} }
/// Emitted to animate press then release. /// Emitted to animate press then release.
/// ///
/// This is an action signal. Applications should never connect /// This is an action signal. Applications should never connect
/// to this signal, but use the [signal@Gtk.Button::clicked] signal. /// to this signal, but use the `Gtk.Button::clicked` signal.
/// ///
/// The default bindings for this signal are all forms of the /// The default bindings for this signal are all forms of the
/// <kbd></kbd> and <kbd>Enter</kbd> keys. /// <kbd></kbd> and <kbd>Enter</kbd> keys.

View File

@ -2,13 +2,15 @@
// ListBox.swift // ListBox.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// `GtkListBox` is a vertical list. /// Shows a vertical list.
///
///
/// ///
/// A `GtkListBox` only contains `GtkListBoxRow` children. These rows can /// A `GtkListBox` only contains `GtkListBoxRow` children. These rows can
/// by dynamically sorted and filtered, and headers can be added dynamically /// by dynamically sorted and filtered, and headers can be added dynamically
@ -21,52 +23,30 @@ import LevenshteinTransformations
/// button in it). /// button in it).
/// ///
/// Although a `GtkListBox` must have only `GtkListBoxRow` children, you can /// Although a `GtkListBox` must have only `GtkListBoxRow` children, you can
/// add any kind of widget to it via [method@Gtk.ListBox.prepend], /// add any kind of widget to it via `Gtk.ListBox.prepend`,
/// [method@Gtk.ListBox.append] and [method@Gtk.ListBox.insert] and a /// `Gtk.ListBox.append` and `Gtk.ListBox.insert` and a
/// `GtkListBoxRow` widget will automatically be inserted between the list /// `GtkListBoxRow` widget will automatically be inserted between the list
/// and the widget. /// and the widget.
/// ///
/// `GtkListBoxRows` can be marked as activatable or selectable. If a row is /// `GtkListBoxRows` can be marked as activatable or selectable. If a row is
/// activatable, [signal@Gtk.ListBox::row-activated] will be emitted for it when /// activatable, `Gtk.ListBox::row-activated` will be emitted for it when
/// the user tries to activate it. If it is selectable, the row will be marked /// the user tries to activate it. If it is selectable, the row will be marked
/// as selected when the user tries to select it. /// as selected when the user tries to select it.
/// ///
/// # GtkListBox as GtkBuildable
/// ///
/// The `GtkListBox` implementation of the `GtkBuildable` interface supports public struct ListBox<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
/// setting a child as the placeholder by specifying placeholder as the type
/// attribute of a `<child>` element. See [method@Gtk.ListBox.set_placeholder]
/// for info.
///
/// # CSS nodes
///
/// |[<!-- language="plain" -->
/// list[.separators][.rich-list][.navigation-sidebar][.boxed-list]
/// row[.activatable]
/// ]|
///
/// `GtkListBox` uses a single CSS node named list. It may carry the .separators
/// style class, when the [property@Gtk.ListBox:show-separators] property is set.
/// Each `GtkListBoxRow` uses a single CSS node named row. The row nodes get the
/// .activatable style class added when appropriate.
///
/// It may also carry the .boxed-list style class. In this case, the list will be
/// automatically surrounded by a frame and have separators.
///
/// The main list node may also carry style classes to select
/// the style of [list presentation](section-list-widget.html#list-styles):
/// .rich-list, .navigation-sidebar or .data-table.
///
/// # Accessibility
///
/// `GtkListBox` uses the %GTK_ACCESSIBLE_ROLE_LIST role and `GtkListBoxRow` uses
/// the %GTK_ACCESSIBLE_ROLE_LIST_ITEM role.
public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
#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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether to accept unpaired release events. /// Whether to accept unpaired release events.
var acceptUnpairedRelease: Bool? var acceptUnpairedRelease: Bool?
@ -79,9 +59,19 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
var activateOnSingleClick: Bool? var activateOnSingleClick: Bool?
/// Whether to show separators between rows. /// Whether to show separators between rows.
var showSeparators: Bool? var showSeparators: Bool?
/// activateCursorRow /// Emitted when the cursor row is activated.
var activateCursorRow: (() -> Void)? var activateCursorRow: (() -> Void)?
/// moveCursor /// Emitted when the user initiates a cursor movement.
///
/// The default bindings for this signal come in two variants, the variant with
/// the Shift modifier extends the selection, the variant without the Shift
/// modifier does not. There are too many key combinations to list them all
/// here.
///
/// - <kbd></kbd>, <kbd></kbd>, <kbd></kbd>, <kbd></kbd>
/// move by individual children
/// - <kbd>Home</kbd>, <kbd>End</kbd> move to the ends of the box
/// - <kbd>PgUp</kbd>, <kbd>PgDn</kbd> move vertically by pages
var moveCursor: (() -> Void)? var moveCursor: (() -> Void)?
/// Emitted when a row has been activated by the user. /// Emitted when a row has been activated by the user.
var rowActivated: (() -> Void)? var rowActivated: (() -> Void)?
@ -90,7 +80,7 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
/// ///
/// When the @box is using %GTK_SELECTION_MULTIPLE, this signal will not /// When the @box is using %GTK_SELECTION_MULTIPLE, this signal will not
/// give you the full picture of selection changes, and you should use /// give you the full picture of selection changes, and you should use
/// the [signal@Gtk.ListBox::selected-rows-changed] signal instead. /// the `Gtk.ListBox::selected-rows-changed` signal instead.
var rowSelected: (() -> Void)? var rowSelected: (() -> Void)?
/// Emitted to select all children of the box, if the selection /// Emitted to select all children of the box, if the selection
/// mode permits it. /// mode permits it.
@ -101,7 +91,9 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
var selectAll: (() -> Void)? var selectAll: (() -> Void)?
/// Emitted when the set of selected rows changes. /// Emitted when the set of selected rows changes.
var selectedRowsChanged: (() -> Void)? var selectedRowsChanged: (() -> Void)?
/// toggleCursorRow /// Emitted when the cursor row is toggled.
///
/// The default bindings for this signal is <kbd>Ctrl</kbd>+<kbd></kbd>.
var toggleCursorRow: (() -> Void)? var toggleCursorRow: (() -> Void)?
/// Emitted to unselect all children of the box, if the selection /// Emitted to unselect all children of the box, if the selection
/// mode permits it. /// mode permits it.
@ -115,11 +107,14 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
var elements: [Element] var elements: [Element]
/// The dynamic widget content. /// The dynamic widget content.
var content: (Element) -> Body var content: (Element) -> Body
/// The dynamic widget identifier key path.
var id: KeyPath<Element, Identifier>
/// Initialize `ListBox`. /// 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.elements = elements
self.content = content self.content = content
self.id = id
} }
/// The view storage. /// The view storage.
@ -132,7 +127,6 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -195,15 +189,10 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? [] var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
let old = storage.fields["element"] as? [Element] ?? [] let old = storage.fields["element"] as? [Element] ?? []
old.identifiableTransform( old.transform(
to: elements, to: elements,
functions: .init { index, element in id: id,
let child = content(element).storage(data: data, type: type) functions: .init { index in
gtk_list_box_remove(widget, gtk_list_box_get_row_at_index(widget, index.cInt)?.cast())
gtk_list_box_insert(widget, child.opaquePointer?.cast(), index.cInt)
contentStorage.remove(at: index)
contentStorage.insert(child, at: index)
} delete: { index in
gtk_list_box_remove(widget, gtk_list_box_get_row_at_index(widget, index.cInt)?.cast()) gtk_list_box_remove(widget, gtk_list_box_get_row_at_index(widget, index.cInt)?.cast())
contentStorage.remove(at: index) contentStorage.remove(at: index)
} insert: { index, element in } insert: { index, element in
@ -217,6 +206,7 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
for (index, element) in elements.enumerated() { for (index, element) in elements.enumerated() {
content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type) content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type)
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -228,47 +218,45 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
/// Whether to accept unpaired release events. /// Whether to accept unpaired release events.
public func acceptUnpairedRelease(_ acceptUnpairedRelease: Bool? = true) -> Self { public func acceptUnpairedRelease(_ acceptUnpairedRelease: Bool? = true) -> Self {
var newSelf = self modify { $0.acceptUnpairedRelease = acceptUnpairedRelease }
newSelf.acceptUnpairedRelease = acceptUnpairedRelease
return newSelf
} }
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// Determines whether children can be activated with a single /// Determines whether children can be activated with a single
/// click, or require a double-click. /// click, or require a double-click.
public func activateOnSingleClick(_ activateOnSingleClick: Bool? = true) -> Self { public func activateOnSingleClick(_ activateOnSingleClick: Bool? = true) -> Self {
var newSelf = self modify { $0.activateOnSingleClick = activateOnSingleClick }
newSelf.activateOnSingleClick = activateOnSingleClick
return newSelf
} }
/// Whether to show separators between rows. /// Whether to show separators between rows.
public func showSeparators(_ showSeparators: Bool? = true) -> Self { public func showSeparators(_ showSeparators: Bool? = true) -> Self {
var newSelf = self modify { $0.showSeparators = showSeparators }
newSelf.showSeparators = showSeparators
return newSelf
} }
/// activateCursorRow /// Emitted when the cursor row is activated.
public func activateCursorRow(_ activateCursorRow: @escaping () -> Void) -> Self { public func activateCursorRow(_ activateCursorRow: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.activateCursorRow = activateCursorRow newSelf.activateCursorRow = activateCursorRow
return newSelf return newSelf
} }
/// moveCursor /// Emitted when the user initiates a cursor movement.
///
/// The default bindings for this signal come in two variants, the variant with
/// the Shift modifier extends the selection, the variant without the Shift
/// modifier does not. There are too many key combinations to list them all
/// here.
///
/// - <kbd></kbd>, <kbd></kbd>, <kbd></kbd>, <kbd></kbd>
/// move by individual children
/// - <kbd>Home</kbd>, <kbd>End</kbd> move to the ends of the box
/// - <kbd>PgUp</kbd>, <kbd>PgDn</kbd> move vertically by pages
public func moveCursor(_ moveCursor: @escaping () -> Void) -> Self { public func moveCursor(_ moveCursor: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.moveCursor = moveCursor newSelf.moveCursor = moveCursor
@ -287,7 +275,7 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
/// ///
/// When the @box is using %GTK_SELECTION_MULTIPLE, this signal will not /// When the @box is using %GTK_SELECTION_MULTIPLE, this signal will not
/// give you the full picture of selection changes, and you should use /// give you the full picture of selection changes, and you should use
/// the [signal@Gtk.ListBox::selected-rows-changed] signal instead. /// the `Gtk.ListBox::selected-rows-changed` signal instead.
public func rowSelected(_ rowSelected: @escaping () -> Void) -> Self { public func rowSelected(_ rowSelected: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.rowSelected = rowSelected newSelf.rowSelected = rowSelected
@ -313,7 +301,9 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
return newSelf return newSelf
} }
/// toggleCursorRow /// Emitted when the cursor row is toggled.
///
/// The default bindings for this signal is <kbd>Ctrl</kbd>+<kbd></kbd>.
public func toggleCursorRow(_ toggleCursorRow: @escaping () -> Void) -> Self { public func toggleCursorRow(_ toggleCursorRow: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.toggleCursorRow = toggleCursorRow newSelf.toggleCursorRow = toggleCursorRow
@ -334,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,30 +2,30 @@
// Menu.swift // Menu.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// The `GtkMenuButton` widget is used to display a popup when clicked. /// Displays a popup when clicked.
///
/// ///
/// ![An example GtkMenuButton](menu-button.png)
/// ///
/// This popup can be provided either as a `GtkPopover` or as an abstract /// This popup can be provided either as a `GtkPopover` or as an abstract
/// `GMenuModel`. /// `GMenuModel`.
/// ///
/// The `GtkMenuButton` widget can show either an icon (set with the /// The `GtkMenuButton` widget can show either an icon (set with the
/// [property@Gtk.MenuButton:icon-name] property) or a label (set with the /// ``iconName(_:)`` property) or a label (set with the
/// [property@Gtk.MenuButton:label] property). If neither is explicitly set, /// ``label(_:)`` property). If neither is explicitly set,
/// a [class@Gtk.Image] is automatically created, using an arrow image oriented /// a `Gtk.Image` is automatically created, using an arrow image oriented
/// according to [property@Gtk.MenuButton:direction] or the generic /// according to ``direction(_:)`` or the generic
/// open-menu-symbolic icon if the direction is not set. /// open-menu-symbolic icon if the direction is not set.
/// ///
/// The positioning of the popup is determined by the /// The positioning of the popup is determined by the
/// [property@Gtk.MenuButton:direction] property of the menu button. /// ``direction(_:)`` property of the menu button.
/// ///
/// For menus, the [property@Gtk.Widget:halign] and [property@Gtk.Widget:valign] /// For menus, the ``halign(_:)`` and ``valign(_:)``
/// properties of the menu are also taken into account. For example, when the /// properties of the menu are also taken into account. For example, when the
/// direction is %GTK_ARROW_DOWN and the horizontal alignment is %GTK_ALIGN_START, /// direction is %GTK_ARROW_DOWN and the horizontal alignment is %GTK_ALIGN_START,
/// the menu will be positioned below the button, with the starting edge /// the menu will be positioned below the button, with the starting edge
@ -41,40 +41,20 @@ import LevenshteinTransformations
/// | **left** | ![](left-start.png) | ![](left-center.png) | ![](left-end.png) | /// | **left** | ![](left-start.png) | ![](left-center.png) | ![](left-end.png) |
/// | **right** | ![](right-start.png) | ![](right-center.png) | ![](right-end.png) | /// | **right** | ![](right-start.png) | ![](right-center.png) | ![](right-end.png) |
/// ///
/// # CSS nodes
/// ///
/// ```
/// menubutton
/// button.toggle
/// <content> [arrow]
/// ```
///
/// `GtkMenuButton` has a single CSS node with name `menubutton`
/// which contains a `button` node with a `.toggle` style class.
///
/// If the button contains an icon, it will have the `.image-button` style class,
/// if it contains text, it will have `.text-button` style class. If an arrow is
/// visible in addition to an icon, text or a custom child, it will also have
/// `.arrow-button` style class.
///
/// Inside the toggle button content, there is an `arrow` node for
/// the indicator, which will carry one of the `.none`, `.up`, `.down`,
/// `.left` or `.right` style classes to indicate the direction that
/// the menu will appear in. The CSS is expected to provide a suitable
/// image for each of these cases using the `-gtk-icon-source` property.
///
/// Optionally, the `menubutton` node can carry the `.circular` style class
/// to request a round appearance.
///
/// # Accessibility
///
/// `GtkMenuButton` uses the %GTK_ACCESSIBLE_ROLE_BUTTON role.
public struct Menu: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
@ -88,7 +68,7 @@ public struct Menu: AdwaitaWidget {
/// size of its contents. /// size of its contents.
var canShrink: Bool? var canShrink: Bool?
/// The child widget. /// The child widget.
var child: (() -> Body)? var child: Body?
/// Whether the button has a frame. /// Whether the button has a frame.
var hasFrame: Bool? var hasFrame: Bool?
/// The name of the icon used to automatically populate the button. /// The name of the icon used to automatically populate the button.
@ -97,9 +77,9 @@ public struct Menu: AdwaitaWidget {
var label: String? var label: String?
/// The `GMenuModel` from which the popup will be created. /// The `GMenuModel` from which the popup will be created.
/// ///
/// See [method@Gtk.MenuButton.set_menu_model] for the interaction /// See `Gtk.MenuButton.set_menu_model` for the interaction
/// with the [property@Gtk.MenuButton:popover] property. /// with the ``popover(_:)`` property.
var menuModel: (() -> Body)? var menuModel: Body?
/// Whether the menu button acts as a primary menu. /// Whether the menu button acts as a primary menu.
/// ///
/// Primary menus can be opened using the <kbd>F10</kbd> key /// Primary menus can be opened using the <kbd>F10</kbd> key
@ -113,7 +93,7 @@ public struct Menu: AdwaitaWidget {
var activate: (() -> Void)? var activate: (() -> Void)?
/// Initialize `Menu`. /// Initialize `Menu`.
public init() { init() {
} }
/// The view storage. /// The view storage.
@ -126,13 +106,12 @@ public struct Menu: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let childStorage = child?.storage(data: data, type: type) {
if let childStorage = child?().storage(data: data, type: type) {
storage.content["child"] = [childStorage] storage.content["child"] = [childStorage]
gtk_menu_button_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast()) gtk_menu_button_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())
} }
if let menu = menuModel?() { if let menuModel {
let childStorage = MenuCollection { menu }.getMenu(data: data) let childStorage = MenuCollection { menuModel }.getMenu(data: data)
storage.content["menuModel"] = [childStorage] storage.content["menuModel"] = [childStorage]
gtk_menu_button_set_menu_model(storage.opaquePointer, childStorage.opaquePointer?.cast()) gtk_menu_button_set_menu_model(storage.opaquePointer, childStorage.opaquePointer?.cast())
} }
@ -170,7 +149,7 @@ if let active, newValue != active.wrappedValue {
gtk_menu_button_set_can_shrink(widget, canShrink.cBool) gtk_menu_button_set_can_shrink(widget, canShrink.cBool)
} }
if let widget = storage.content["child"]?.first { if let widget = storage.content["child"]?.first {
child?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) child?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let hasFrame, updateProperties, (storage.previousState as? Self)?.hasFrame != hasFrame { if let hasFrame, updateProperties, (storage.previousState as? Self)?.hasFrame != hasFrame {
gtk_menu_button_set_has_frame(widget, hasFrame.cBool) gtk_menu_button_set_has_frame(widget, hasFrame.cBool)
@ -182,7 +161,7 @@ if let active, newValue != active.wrappedValue {
gtk_menu_button_set_label(widget, label) gtk_menu_button_set_label(widget, label)
} }
if let menu = storage.content["menuModel"]?.first { if let menu = storage.content["menuModel"]?.first {
MenuCollection { menuModel?() ?? [] } MenuCollection { menuModel ?? [] }
.updateStorage(menu, data: data.noModifiers, updateProperties: updateProperties, type: MenuContext.self) .updateStorage(menu, data: data.noModifiers, updateProperties: updateProperties, type: MenuContext.self)
} }
if let primary, updateProperties, (storage.previousState as? Self)?.primary != primary { if let primary, updateProperties, (storage.previousState as? Self)?.primary != primary {
@ -193,6 +172,7 @@ if let active, newValue != active.wrappedValue {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -206,96 +186,63 @@ if let active, newValue != active.wrappedValue {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// Whether the menu button is active. /// Whether the menu button is active.
public func active(_ active: Binding<Bool>?) -> Self { public func active(_ active: Binding<Bool>?) -> Self {
var newSelf = self modify { $0.active = active }
newSelf.active = active
return newSelf
} }
/// Whether to show a dropdown arrow even when using an icon or a custom child. /// Whether to show a dropdown arrow even when using an icon or a custom child.
public func alwaysShowArrow(_ alwaysShowArrow: Bool? = true) -> Self { public func alwaysShowArrow(_ alwaysShowArrow: Bool? = true) -> Self {
var newSelf = self modify { $0.alwaysShowArrow = alwaysShowArrow }
newSelf.alwaysShowArrow = alwaysShowArrow
return newSelf
} }
/// Whether the size of the button can be made smaller than the natural /// Whether the size of the button can be made smaller than the natural
/// size of its contents. /// size of its contents.
public func canShrink(_ canShrink: Bool? = true) -> Self { public func canShrink(_ canShrink: Bool? = true) -> Self {
var newSelf = self modify { $0.canShrink = canShrink }
newSelf.canShrink = canShrink
return newSelf
} }
/// The child widget. /// The child widget.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self { public func child(@ViewBuilder _ child: () -> Body) -> Self {
var newSelf = self modify { $0.child = child() }
newSelf.child = child
return newSelf
} }
/// Whether the button has a frame. /// Whether the button has a frame.
public func hasFrame(_ hasFrame: Bool? = true) -> Self { public func hasFrame(_ hasFrame: Bool? = true) -> Self {
var newSelf = self modify { $0.hasFrame = hasFrame }
newSelf.hasFrame = hasFrame
return newSelf
} }
/// The name of the icon used to automatically populate the button. /// The name of the icon used to automatically populate the button.
public func iconName(_ iconName: String?) -> Self { public func iconName(_ iconName: String?) -> Self {
var newSelf = self modify { $0.iconName = iconName }
newSelf.iconName = iconName
return newSelf
} }
/// The label for the button. /// The label for the button.
public func label(_ label: String?) -> Self { public func label(_ label: String?) -> Self {
var newSelf = self modify { $0.label = label }
newSelf.label = label
return newSelf
} }
/// The `GMenuModel` from which the popup will be created. /// The `GMenuModel` from which the popup will be created.
/// ///
/// See [method@Gtk.MenuButton.set_menu_model] for the interaction /// See `Gtk.MenuButton.set_menu_model` for the interaction
/// with the [property@Gtk.MenuButton:popover] property. /// with the ``popover(_:)`` property.
public func menuModel(@ViewBuilder _ menuModel: @escaping (() -> Body)) -> Self { public func menuModel(@ViewBuilder _ menuModel: () -> Body) -> Self {
var newSelf = self modify { $0.menuModel = menuModel() }
newSelf.menuModel = menuModel
return newSelf
} }
/// Whether the menu button acts as a primary menu. /// Whether the menu button acts as a primary menu.
/// ///
/// Primary menus can be opened using the <kbd>F10</kbd> key /// Primary menus can be opened using the <kbd>F10</kbd> key
public func primary(_ primary: Bool? = true) -> Self { public func primary(_ primary: Bool? = true) -> Self {
var newSelf = self modify { $0.primary = primary }
newSelf.primary = primary
return newSelf
} }
/// If set an underscore in the text indicates a mnemonic. /// If set an underscore in the text indicates a mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// Emitted to when the menu button is activated. /// Emitted to when the menu button is activated.

View File

@ -2,7 +2,7 @@
// NavigationView.swift // NavigationView.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,130 +10,74 @@ import LevenshteinTransformations
/// A page-based navigation container. /// A page-based navigation container.
/// ///
/// <picture><source srcset="navigation-view-dark.png" media="(prefers-color-scheme: dark)"><img src="navigation-view.png" alt="navigation-view"></picture> ///
/// ///
/// `AdwNavigationView` presents one child at a time, similar to /// `AdwNavigationView` presents one child at a time, similar to
/// [class@Gtk.Stack]. /// `Gtk.Stack`.
/// ///
/// `AdwNavigationView` can only contain [class@NavigationPage] children. /// `AdwNavigationView` can only contain `NavigationPage` children.
/// ///
/// It maintains a navigation stack that can be controlled with /// It maintains a navigation stack that can be controlled with
/// [method@NavigationView.push] and [method@NavigationView.pop]. The whole /// `NavigationView.push` and `NavigationView.pop`. The whole
/// navigation stack can also be replaced using [method@NavigationView.replace]. /// navigation stack can also be replaced using `NavigationView.replace`.
/// ///
/// `AdwNavigationView` allows to manage pages statically or dynamically. /// `AdwNavigationView` allows to manage pages statically or dynamically.
/// ///
/// Static pages can be added using the [method@NavigationView.add] method. The /// Static pages can be added using the `NavigationView.add` method. The
/// `AdwNavigationView` will keep a reference to these pages, but they aren't /// `AdwNavigationView` will keep a reference to these pages, but they aren't
/// accessible to the user until [method@NavigationView.push] is called (except /// accessible to the user until `NavigationView.push` is called (except
/// for the first page, which is pushed automatically). Use the /// for the first page, which is pushed automatically). Use the
/// [method@NavigationView.remove] method to remove them. This is useful for /// `NavigationView.remove` method to remove them. This is useful for
/// applications that have a small number of unique pages and just need /// applications that have a small number of unique pages and just need
/// navigation between them. /// navigation between them.
/// ///
/// Dynamic pages are automatically destroyed once they are popped off the /// Dynamic pages are automatically destroyed once they are popped off the
/// navigation stack. To add a page like this, push it using the /// navigation stack. To add a page like this, push it using the
/// [method@NavigationView.push] method without calling /// `NavigationView.push` method without calling
/// [method@NavigationView.add] first. /// `NavigationView.add` first.
/// ///
/// ## Tags
/// ///
/// Static pages, as well as any pages in the navigation stack, can be accessed
/// by their [property@NavigationPage:tag]. For example,
/// [method@NavigationView.push_by_tag] can be used to push a static page that's
/// not in the navigation stack without having to keep a reference to it manually.
///
/// ## Header Bar Integration
///
/// When used inside `AdwNavigationView`, [class@HeaderBar] will automatically
/// display a back button that can be used to go back to the previous page when
/// possible. The button also has a context menu, allowing to pop multiple pages
/// at once, potentially across multiple navigation views.
///
/// Set [property@HeaderBar:show-back-button] to `FALSE` to disable this behavior
/// in rare scenarios where it's unwanted.
///
/// `AdwHeaderBar` will also display the title of the `AdwNavigationPage` it's
/// placed into, so most applications shouldn't need to customize it at all.
///
/// ## Shortcuts and Gestures
///
/// `AdwNavigationView` supports the following shortcuts for going to the
/// previous page:
///
/// - <kbd>Escape</kbd> (unless [property@NavigationView:pop-on-escape] is set to
/// `FALSE`)
/// - <kbd>Alt</kbd>+<kbd></kbd>
/// - Back mouse button
///
/// Additionally, it supports interactive gestures:
///
/// - One-finger swipe towards the right on touchscreens
/// - Scrolling towards the right on touchpads (usually two-finger swipe)
///
/// These gestures have transitions enabled regardless of the
/// [property@NavigationView:animate-transitions] value.
///
/// Applications can also enable shortcuts for pushing another page onto the
/// navigation stack via connecting to the [signal@NavigationView::get-next-page]
/// signal, in that case the following shortcuts are supported:
///
/// - <kbd>Alt</kbd>+<kbd></kbd>
/// - Forward mouse button
/// - Swipe/scrolling towards the left
///
/// For right-to-left locales, the gestures and shortcuts are reversed.
///
/// [property@NavigationPage:can-pop] can be used to disable them, along with the
/// header bar back buttons.
///
/// ## Actions
///
/// `AdwNavigationView` defines actions for controlling the navigation stack.
/// actions for controlling the navigation stack:
///
/// - `navigation.push` takes a string parameter specifying the tag of the page to
/// push, and is equivalent to calling [method@NavigationView.push_by_tag].
///
/// - `navigation.pop` doesn't take any parameters and pops the current page from
/// the navigation stack, equivalent to calling [method@NavigationView.pop].
///
/// ## `AdwNavigationView` as `GtkBuildable`
///
/// `AdwNavigationView` allows to add pages as children, equivalent to using the
/// [method@NavigationView.add] method.
///
/// Example of an `AdwNavigationView` UI definition:
///
/// ```xml
/// <object class="AdwNavigationView"><child><object class="AdwNavigationPage"><property name="title" translatable="yes">Page 1</property><property name="child"><object class="AdwToolbarView"><child type="top"><object class="AdwHeaderBar"/></child><property name="content"><object class="GtkButton"><property name="label" translatable="yes">Open Page 2</property><property name="halign">center</property><property name="valign">center</property><property name="action-name">navigation.push</property><property name="action-target">'page-2'</property><style><class name="pill"/></style></object></property></object></property></object></child><child><object class="AdwNavigationPage"><property name="title" translatable="yes">Page 2</property><property name="tag">page-2</property><property name="child"><object class="AdwToolbarView"><child type="top"><object class="AdwHeaderBar"/></child><property name="content"><!-- ... --></property></object></property></object></child></object>
/// ```
///
/// <picture><source srcset="navigation-view-example-dark.png" media="(prefers-color-scheme: dark)"><img src="navigation-view-example.png" alt="navigation-view-example"></picture>
///
/// ## CSS nodes
///
/// `AdwNavigationView` has a single CSS node with the name `navigation-view`.
///
/// ## Accessibility
///
/// `AdwNavigationView` uses the `GTK_ACCESSIBLE_ROLE_GROUP` role.
public struct NavigationView: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether to animate page transitions. /// Whether to animate page transitions.
/// ///
/// Gesture-based transitions are always animated. /// Gesture-based transitions are always animated.
var animateTransitions: Bool? var animateTransitions: Bool?
/// Whether the view is horizontally homogeneous.
///
/// If the view is horizontally homogeneous, it allocates the same width for
/// all pages.
///
/// If it's not, the page may change width when a different page becomes
/// visible.
var hhomogeneous: Bool?
/// Whether pressing Escape pops the current page. /// Whether pressing Escape pops the current page.
/// ///
/// Applications using `AdwNavigationView` to implement a browser may want to /// Applications using `AdwNavigationView` to implement a browser may want to
/// disable it. /// disable it.
var popOnEscape: Bool? var popOnEscape: Bool?
/// Whether the view is vertically homogeneous.
///
/// If the view is vertically homogeneous, it allocates the same height for
/// all pages.
///
/// If it's not, the view may change height when a different page becomes
/// visible.
var vhomogeneous: Bool?
/// The tag of the currently visible page.
var visiblePageTag: String?
/// Emitted when a push shortcut or a gesture is triggered. /// Emitted when a push shortcut or a gesture is triggered.
/// ///
/// To support the push shortcuts and gestures, the application is expected to /// To support the push shortcuts and gestures, the application is expected to
@ -144,27 +88,27 @@ public struct NavigationView: AdwaitaWidget {
/// not make any irreversible changes in the handler, such as removing the page /// not make any irreversible changes in the handler, such as removing the page
/// from a forward stack. /// from a forward stack.
/// ///
/// Instead, it should be done in the [signal@NavigationView::pushed] handler. /// Instead, it should be done in the `NavigationView::pushed` handler.
var getNextPage: (() -> Void)? var getNextPage: (() -> Void)?
/// Emitted after @page has been popped from the navigation stack. /// Emitted after @page has been popped from the navigation stack.
/// ///
/// See [method@NavigationView.pop]. /// See `NavigationView.pop`.
/// ///
/// When using [method@NavigationView.pop_to_page] or /// When using `NavigationView.pop_to_page` or
/// [method@NavigationView.pop_to_tag], this signal is emitted for each of the /// `NavigationView.pop_to_tag`, this signal is emitted for each of the
/// popped pages. /// popped pages.
var popped: (() -> Void)? var popped: (() -> Void)?
/// Emitted after a page has been pushed to the navigation stack. /// Emitted after a page has been pushed to the navigation stack.
/// ///
/// See [method@NavigationView.push]. /// See `NavigationView.push`.
var pushed: (() -> Void)? var pushed: (() -> Void)?
/// Emitted after the navigation stack has been replaced. /// Emitted after the navigation stack has been replaced.
/// ///
/// See [method@NavigationView.replace]. /// See `NavigationView.replace`.
var replaced: (() -> Void)? var replaced: (() -> Void)?
/// Initialize `NavigationView`. /// Initialize `NavigationView`.
public init() { init() {
} }
/// The view storage. /// The view storage.
@ -177,7 +121,6 @@ public struct NavigationView: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
return storage return storage
} }
@ -214,9 +157,16 @@ public struct NavigationView: AdwaitaWidget {
if let animateTransitions, updateProperties, (storage.previousState as? Self)?.animateTransitions != animateTransitions { if let animateTransitions, updateProperties, (storage.previousState as? Self)?.animateTransitions != animateTransitions {
adw_navigation_view_set_animate_transitions(widget, animateTransitions.cBool) adw_navigation_view_set_animate_transitions(widget, animateTransitions.cBool)
} }
if let hhomogeneous, updateProperties, (storage.previousState as? Self)?.hhomogeneous != hhomogeneous {
adw_navigation_view_set_hhomogeneous(widget, hhomogeneous.cBool)
}
if let popOnEscape, updateProperties, (storage.previousState as? Self)?.popOnEscape != popOnEscape { if let popOnEscape, updateProperties, (storage.previousState as? Self)?.popOnEscape != popOnEscape {
adw_navigation_view_set_pop_on_escape(widget, popOnEscape.cBool) adw_navigation_view_set_pop_on_escape(widget, popOnEscape.cBool)
} }
if let vhomogeneous, updateProperties, (storage.previousState as? Self)?.vhomogeneous != vhomogeneous {
adw_navigation_view_set_vhomogeneous(widget, vhomogeneous.cBool)
}
} }
@ -232,10 +182,18 @@ public struct NavigationView: AdwaitaWidget {
/// ///
/// Gesture-based transitions are always animated. /// Gesture-based transitions are always animated.
public func animateTransitions(_ animateTransitions: Bool? = true) -> Self { public func animateTransitions(_ animateTransitions: Bool? = true) -> Self {
var newSelf = self modify { $0.animateTransitions = animateTransitions }
newSelf.animateTransitions = animateTransitions }
return newSelf /// Whether the view is horizontally homogeneous.
///
/// If the view is horizontally homogeneous, it allocates the same width for
/// all pages.
///
/// If it's not, the page may change width when a different page becomes
/// visible.
public func hhomogeneous(_ hhomogeneous: Bool? = true) -> Self {
modify { $0.hhomogeneous = hhomogeneous }
} }
/// Whether pressing Escape pops the current page. /// Whether pressing Escape pops the current page.
@ -243,10 +201,23 @@ public struct NavigationView: AdwaitaWidget {
/// Applications using `AdwNavigationView` to implement a browser may want to /// Applications using `AdwNavigationView` to implement a browser may want to
/// disable it. /// disable it.
public func popOnEscape(_ popOnEscape: Bool? = true) -> Self { public func popOnEscape(_ popOnEscape: Bool? = true) -> Self {
var newSelf = self modify { $0.popOnEscape = popOnEscape }
newSelf.popOnEscape = popOnEscape }
return newSelf /// Whether the view is vertically homogeneous.
///
/// If the view is vertically homogeneous, it allocates the same height for
/// all pages.
///
/// If it's not, the view may change height when a different page becomes
/// visible.
public func vhomogeneous(_ vhomogeneous: Bool? = true) -> Self {
modify { $0.vhomogeneous = vhomogeneous }
}
/// The tag of the currently visible page.
public func visiblePageTag(_ visiblePageTag: String?) -> Self {
modify { $0.visiblePageTag = visiblePageTag }
} }
/// Emitted when a push shortcut or a gesture is triggered. /// Emitted when a push shortcut or a gesture is triggered.
@ -259,7 +230,7 @@ public struct NavigationView: AdwaitaWidget {
/// not make any irreversible changes in the handler, such as removing the page /// not make any irreversible changes in the handler, such as removing the page
/// from a forward stack. /// from a forward stack.
/// ///
/// Instead, it should be done in the [signal@NavigationView::pushed] handler. /// Instead, it should be done in the `NavigationView::pushed` handler.
public func getNextPage(_ getNextPage: @escaping () -> Void) -> Self { public func getNextPage(_ getNextPage: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.getNextPage = getNextPage newSelf.getNextPage = getNextPage
@ -268,10 +239,10 @@ public struct NavigationView: AdwaitaWidget {
/// Emitted after @page has been popped from the navigation stack. /// Emitted after @page has been popped from the navigation stack.
/// ///
/// See [method@NavigationView.pop]. /// See `NavigationView.pop`.
/// ///
/// When using [method@NavigationView.pop_to_page] or /// When using `NavigationView.pop_to_page` or
/// [method@NavigationView.pop_to_tag], this signal is emitted for each of the /// `NavigationView.pop_to_tag`, this signal is emitted for each of the
/// popped pages. /// popped pages.
public func popped(_ popped: @escaping () -> Void) -> Self { public func popped(_ popped: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
@ -281,7 +252,7 @@ public struct NavigationView: AdwaitaWidget {
/// Emitted after a page has been pushed to the navigation stack. /// Emitted after a page has been pushed to the navigation stack.
/// ///
/// See [method@NavigationView.push]. /// See `NavigationView.push`.
public func pushed(_ pushed: @escaping () -> Void) -> Self { public func pushed(_ pushed: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.pushed = pushed newSelf.pushed = pushed
@ -290,7 +261,7 @@ public struct NavigationView: AdwaitaWidget {
/// Emitted after the navigation stack has been replaced. /// Emitted after the navigation stack has been replaced.
/// ///
/// See [method@NavigationView.replace]. /// See `NavigationView.replace`.
public func replaced(_ replaced: @escaping () -> Void) -> Self { public func replaced(_ replaced: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.replaced = replaced newSelf.replaced = replaced

View File

@ -2,19 +2,18 @@
// Overlay.swift // Overlay.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// `GtkOverlay` is a container which contains a single main child, on top /// Places overlay widgets on top of a single main child.
/// of which it can place overlay widgets. ///
/// ///
/// ![An example GtkOverlay](overlay.png)
/// ///
/// The position of each overlay widget is determined by its /// The position of each overlay widget is determined by its
/// [property@Gtk.Widget:halign] and [property@Gtk.Widget:valign] /// ``halign(_:)`` and ``valign(_:)``
/// properties. E.g. a widget with both alignments set to %GTK_ALIGN_START /// properties. E.g. a widget with both alignments set to %GTK_ALIGN_START
/// will be placed at the top left corner of the `GtkOverlay` container, /// will be placed at the top left corner of the `GtkOverlay` container,
/// whereas an overlay with halign set to %GTK_ALIGN_CENTER and valign set /// whereas an overlay with halign set to %GTK_ALIGN_CENTER and valign set
@ -23,36 +22,33 @@ import LevenshteinTransformations
/// properties of the child to non-zero values. /// properties of the child to non-zero values.
/// ///
/// More complicated placement of overlays is possible by connecting /// More complicated placement of overlays is possible by connecting
/// to the [signal@Gtk.Overlay::get-child-position] signal. /// to the `Gtk.Overlay::get-child-position` signal.
/// ///
/// An overlays minimum and natural sizes are those of its main child. /// An overlays minimum and natural sizes are those of its main child.
/// The sizes of overlay children are not considered when measuring these /// The sizes of overlay children are not considered when measuring these
/// preferred sizes. /// preferred sizes.
/// ///
/// # GtkOverlay as GtkBuildable
/// ///
/// The `GtkOverlay` implementation of the `GtkBuildable` interface
/// supports placing a child as an overlay by specifying overlay as
/// the type attribute of a `<child>` element.
///
/// # CSS nodes
///
/// `GtkOverlay` has a single CSS node with the name overlay. Overlay children
/// whose alignments cause them to be positioned at an edge get the style classes
/// .left, .right, .top, and/or .bottom according to their position.
public struct Overlay: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// The accessible role of the given `GtkAccessible` implementation. /// The accessible role of the given `GtkAccessible` implementation.
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
var accessibleRole: String? var accessibleRole: String?
/// The main child widget. /// The main child widget.
var child: (() -> Body)? var child: Body?
/// Emitted to determine the position and size of any overlay /// Emitted to determine the position and size of any overlay
/// child widgets. /// child widgets.
/// ///
@ -85,8 +81,7 @@ public struct Overlay: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let childStorage = child?.storage(data: data, type: type) {
if let childStorage = child?().storage(data: data, type: type) {
storage.content["child"] = [childStorage] storage.content["child"] = [childStorage]
gtk_overlay_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast()) gtk_overlay_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())
} }
@ -115,7 +110,7 @@ public struct Overlay: AdwaitaWidget {
storage.modify { widget in storage.modify { widget in
if let widget = storage.content["child"]?.first { if let widget = storage.content["child"]?.first {
child?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) child?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let overlayStorage = storage.content["overlay"] { if let overlayStorage = storage.content["overlay"] {
@ -131,6 +126,7 @@ public struct Overlay: AdwaitaWidget {
} }
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -144,18 +140,12 @@ public struct Overlay: AdwaitaWidget {
/// ///
/// The accessible role cannot be changed once set. /// The accessible role cannot be changed once set.
public func accessibleRole(_ accessibleRole: String?) -> Self { public func accessibleRole(_ accessibleRole: String?) -> Self {
var newSelf = self modify { $0.accessibleRole = accessibleRole }
newSelf.accessibleRole = accessibleRole
return newSelf
} }
/// The main child widget. /// The main child widget.
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self { public func child(@ViewBuilder _ child: () -> Body) -> Self {
var newSelf = self modify { $0.child = child() }
newSelf.child = child
return newSelf
} }
/// Emitted to determine the position and size of any overlay /// Emitted to determine the position and size of any overlay

View File

@ -2,7 +2,7 @@
// OverlaySplitView.swift // OverlaySplitView.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
@ -10,115 +10,57 @@ import LevenshteinTransformations
/// A widget presenting sidebar and content side by side or as an overlay. /// A widget presenting sidebar and content side by side or as an overlay.
/// ///
/// <picture><source srcset="overlay-split-view-dark.png" media="(prefers-color-scheme: dark)"><img src="overlay-split-view.png" alt="overlay-split-view"></picture><picture><source srcset="overlay-split-view-collapsed-dark.png" media="(prefers-color-scheme: dark)"><img src="overlay-split-view-collapsed.png" alt="overlay-split-view-collapsed"></picture> ///
/// ///
/// `AdwOverlaySplitView` has two children: sidebar and content, and displays /// `AdwOverlaySplitView` has two children: sidebar and content, and displays
/// them side by side. /// them side by side.
/// ///
/// When [property@OverlaySplitView:collapsed] is set to `TRUE`, the sidebar is /// When ``collapsed(_:)`` is set to `true`, the sidebar is
/// instead shown as an overlay above the content widget. /// instead shown as an overlay above the content widget.
/// ///
/// The sidebar can be hidden or shown using the /// The sidebar can be hidden or shown using the
/// [property@OverlaySplitView:show-sidebar] property. /// ``showSidebar(_:)`` property.
/// ///
/// Sidebar can be displayed before or after the content, this can be controlled /// Sidebar can be displayed before or after the content, this can be controlled
/// with the [property@OverlaySplitView:sidebar-position] property. /// with the ``sidebarPosition(_:)`` property.
/// ///
/// Collapsing the split view automatically hides the sidebar widget, and /// Collapsing the split view automatically hides the sidebar widget, and
/// uncollapsing it shows the sidebar. If this behavior is not desired, the /// uncollapsing it shows the sidebar. If this behavior is not desired, the
/// [property@OverlaySplitView:pin-sidebar] property can be used to override it. /// ``pinSidebar(_:)`` property can be used to override it.
/// ///
/// `AdwOverlaySplitView` supports an edge swipe gesture for showing the sidebar, /// `AdwOverlaySplitView` supports an edge swipe gesture for showing the sidebar,
/// and a swipe from the sidebar for hiding it. Gestures are only supported on /// and a swipe from the sidebar for hiding it. Gestures are only supported on
/// touchscreen, but not touchpad. Gestures can be controlled with the /// touchscreen, but not touchpad. Gestures can be controlled with the
/// [property@OverlaySplitView:enable-show-gesture] and /// ``enableShowGesture(_:)`` and
/// [property@OverlaySplitView:enable-hide-gesture] properties. /// ``enableHideGesture(_:)`` properties.
/// ///
/// See also [class@NavigationSplitView]. /// See also `NavigationSplitView`.
/// ///
/// `AdwOverlaySplitView` is typically used together with an [class@Breakpoint] /// `AdwOverlaySplitView` is typically used together with an `Breakpoint`
/// setting the `collapsed` property to `TRUE` on small widths, as follows: /// setting the `collapsed` property to `true` on small widths, as follows:
/// ///
/// ```xml /// ```xml
/// <object class="AdwWindow"><property name="width-request">360</property><property name="height-request">200</property><property name="default-width">800</property><property name="default-height">800</property><child><object class="AdwBreakpoint"><condition>max-width: 400sp</condition><setter object="split_view" property="collapsed">True</setter></object></child><property name="content"><object class="AdwOverlaySplitView" id="split_view"><property name="sidebar"><!-- ... --></property><property name="content"><!-- ... --></property></object></property></object> /// <object class="AdwWindow"><property name="default-width">800</property><property name="default-height">800</property><child><object class="AdwBreakpoint"><condition>max-width: 400sp</condition><setter object="split_view" property="collapsed">True</setter></object></child><property name="content"><object class="AdwOverlaySplitView" id="split_view"><property name="sidebar"><!-- ... --></property><property name="content"><!-- ... --></property></object></property></object>
/// ``` /// ```
/// ///
/// `AdwOverlaySplitView` is often used for implementing the /// `AdwOverlaySplitView` is often used for implementing the
/// [utility pane](https://developer.gnome.org/hig/patterns/containers/utility-panes.html) /// [utility pane](https://developer.gnome.org/hig/patterns/containers/utility-panes.html)
/// pattern. /// pattern.
/// ///
/// ## Sizing
/// ///
/// When not collapsed, `AdwOverlaySplitView` changes the sidebar width
/// depending on its own width.
///
/// If possible, it tries to allocate a fraction of the total width, controlled
/// with the [property@OverlaySplitView:sidebar-width-fraction] property.
///
/// The sidebar also has minimum and maximum sizes, controlled with the
/// [property@OverlaySplitView:min-sidebar-width] and
/// [property@OverlaySplitView:max-sidebar-width] properties.
///
/// The minimum and maximum sizes are using the length unit specified with the
/// [property@OverlaySplitView:sidebar-width-unit].
///
/// By default, sidebar is using 25% of the total width, with 180sp as the
/// minimum size and 280sp as the maximum size.
///
/// When collapsed, the preferred width fraction is ignored and the sidebar uses
/// [property@OverlaySplitView:max-sidebar-width] when possible.
///
/// ## Header Bar Integration
///
/// When used inside `AdwOverlaySplitView`, [class@HeaderBar] will automatically
/// hide the window buttons in the middle.
///
/// ## `AdwOverlaySplitView` as `GtkBuildable`
///
/// The `AdwOverlaySplitView` implementation of the [iface@Gtk.Buildable]
/// interface supports setting the sidebar widget by specifying sidebar as the
/// type attribute of a `<child>` element, Specifying content child type or
/// omitting it results in setting the content widget.
///
/// ## CSS nodes
///
/// `AdwOverlaySplitView` has a single CSS node with the name
/// `overlay-split-view`.
///
/// It contains two nodes with the name `widget`, containing the sidebar and
/// content children.
///
/// When not collapsed, they have the `.sidebar-view` and `.content-view` style
/// classes respectively.
///
/// ```
/// overlay-split-view
/// widget.sidebar-pane
/// [sidebar child]
/// widget.content-pane
/// [content child]
/// ```
///
/// When collapsed, the one containing the sidebar child has the `.background`
/// style class and the other one has no style classes.
///
/// ```
/// overlay-split-view
/// widget.background
/// [sidebar child]
/// widget
/// [content child]
/// ```
///
/// ## Accessibility
///
/// `AdwOverlaySplitView` uses the `GTK_ACCESSIBLE_ROLE_GROUP` role.
public struct OverlaySplitView: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether the split view is collapsed. /// Whether the split view is collapsed.
/// ///
@ -126,7 +68,7 @@ public struct OverlaySplitView: AdwaitaWidget {
/// content widget, otherwise they are displayed side by side. /// content widget, otherwise they are displayed side by side.
var collapsed: Bool? var collapsed: Bool?
/// The content widget. /// The content widget.
var content: (() -> Body)? var content: Body?
/// Whether the sidebar can be closed with a swipe gesture. /// Whether the sidebar can be closed with a swipe gesture.
/// ///
/// Only touchscreen swipes are supported. /// Only touchscreen swipes are supported.
@ -138,7 +80,7 @@ public struct OverlaySplitView: AdwaitaWidget {
/// The maximum sidebar width. /// The maximum sidebar width.
/// ///
/// Maximum width is affected by /// Maximum width is affected by
/// [property@OverlaySplitView:sidebar-width-unit]. /// ``sidebarWidthUnit(_:)``.
/// ///
/// The sidebar widget can still be allocated with larger width if its own /// The sidebar widget can still be allocated with larger width if its own
/// minimum width exceeds it. /// minimum width exceeds it.
@ -146,7 +88,7 @@ public struct OverlaySplitView: AdwaitaWidget {
/// The minimum sidebar width. /// The minimum sidebar width.
/// ///
/// Minimum width is affected by /// Minimum width is affected by
/// [property@OverlaySplitView:sidebar-width-unit]. /// ``sidebarWidthUnit(_:)``.
/// ///
/// The sidebar widget can still be allocated with larger width if its own /// The sidebar widget can still be allocated with larger width if its own
/// minimum width exceeds it. /// minimum width exceeds it.
@ -154,25 +96,25 @@ public struct OverlaySplitView: AdwaitaWidget {
/// Whether the sidebar widget is pinned. /// Whether the sidebar widget is pinned.
/// ///
/// By default, collapsing @self automatically hides the sidebar widget, and /// By default, collapsing @self automatically hides the sidebar widget, and
/// uncollapsing it shows the sidebar. If set to `TRUE`, sidebar visibility /// uncollapsing it shows the sidebar. If set to `true`, sidebar visibility
/// never changes on its own. /// never changes on its own.
var pinSidebar: Bool? var pinSidebar: Bool?
/// Whether the sidebar widget is shown. /// Whether the sidebar widget is shown.
var showSidebar: Binding<Bool>? var showSidebar: Binding<Bool>?
/// The sidebar widget. /// The sidebar widget.
var sidebar: (() -> Body)? var sidebar: Body?
/// The preferred sidebar width as a fraction of the total width. /// The preferred sidebar width as a fraction of the total width.
/// ///
/// The preferred width is additionally limited by /// The preferred width is additionally limited by
/// [property@OverlaySplitView:min-sidebar-width] and /// ``minSidebarWidth(_:)`` and
/// [property@OverlaySplitView:max-sidebar-width]. /// ``maxSidebarWidth(_:)``.
/// ///
/// The sidebar widget can be allocated with larger width if its own minimum /// The sidebar widget can be allocated with larger width if its own minimum
/// width exceeds the preferred width. /// width exceeds the preferred width.
var sidebarWidthFraction: Double? var sidebarWidthFraction: Double?
/// Initialize `OverlaySplitView`. /// Initialize `OverlaySplitView`.
public init() { init() {
} }
/// The view storage. /// The view storage.
@ -185,12 +127,11 @@ public struct OverlaySplitView: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type) if let contentStorage = content?.storage(data: data, type: type) {
if let contentStorage = content?().storage(data: data, type: type) {
storage.content["content"] = [contentStorage] storage.content["content"] = [contentStorage]
adw_overlay_split_view_set_content(storage.opaquePointer, contentStorage.opaquePointer?.cast()) adw_overlay_split_view_set_content(storage.opaquePointer, contentStorage.opaquePointer?.cast())
} }
if let sidebarStorage = sidebar?().storage(data: data, type: type) { if let sidebarStorage = sidebar?.storage(data: data, type: type) {
storage.content["sidebar"] = [sidebarStorage] storage.content["sidebar"] = [sidebarStorage]
adw_overlay_split_view_set_sidebar(storage.opaquePointer, sidebarStorage.opaquePointer?.cast()) adw_overlay_split_view_set_sidebar(storage.opaquePointer, sidebarStorage.opaquePointer?.cast())
} }
@ -217,7 +158,7 @@ if let showSidebar, newValue != showSidebar.wrappedValue {
adw_overlay_split_view_set_collapsed(widget, collapsed.cBool) adw_overlay_split_view_set_collapsed(widget, collapsed.cBool)
} }
if let widget = storage.content["content"]?.first { if let widget = storage.content["content"]?.first {
content?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) content?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let enableHideGesture, updateProperties, (storage.previousState as? Self)?.enableHideGesture != enableHideGesture { if let enableHideGesture, updateProperties, (storage.previousState as? Self)?.enableHideGesture != enableHideGesture {
adw_overlay_split_view_set_enable_hide_gesture(widget, enableHideGesture.cBool) adw_overlay_split_view_set_enable_hide_gesture(widget, enableHideGesture.cBool)
@ -238,13 +179,14 @@ if let showSidebar, newValue != showSidebar.wrappedValue {
adw_overlay_split_view_set_show_sidebar(storage.opaquePointer, showSidebar.wrappedValue.cBool) adw_overlay_split_view_set_show_sidebar(storage.opaquePointer, showSidebar.wrappedValue.cBool)
} }
if let widget = storage.content["sidebar"]?.first { if let widget = storage.content["sidebar"]?.first {
sidebar?().updateStorage(widget, data: data, updateProperties: updateProperties, type: type) sidebar?.updateStorage(widget, data: data, updateProperties: updateProperties, type: type)
} }
if let sidebarWidthFraction, updateProperties, (storage.previousState as? Self)?.sidebarWidthFraction != sidebarWidthFraction { if let sidebarWidthFraction, updateProperties, (storage.previousState as? Self)?.sidebarWidthFraction != sidebarWidthFraction {
adw_overlay_split_view_set_sidebar_width_fraction(widget, sidebarWidthFraction) adw_overlay_split_view_set_sidebar_width_fraction(widget, sidebarWidthFraction)
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -259,109 +201,79 @@ if let showSidebar, newValue != showSidebar.wrappedValue {
/// When collapsed, the sidebar widget is presented as an overlay above the /// When collapsed, the sidebar widget is presented as an overlay above the
/// content widget, otherwise they are displayed side by side. /// content widget, otherwise they are displayed side by side.
public func collapsed(_ collapsed: Bool? = true) -> Self { public func collapsed(_ collapsed: Bool? = true) -> Self {
var newSelf = self modify { $0.collapsed = collapsed }
newSelf.collapsed = collapsed
return newSelf
} }
/// The content widget. /// The content widget.
public func content(@ViewBuilder _ content: @escaping (() -> Body)) -> Self { public func content(@ViewBuilder _ content: () -> Body) -> Self {
var newSelf = self modify { $0.content = content() }
newSelf.content = content
return newSelf
} }
/// Whether the sidebar can be closed with a swipe gesture. /// Whether the sidebar can be closed with a swipe gesture.
/// ///
/// Only touchscreen swipes are supported. /// Only touchscreen swipes are supported.
public func enableHideGesture(_ enableHideGesture: Bool? = true) -> Self { public func enableHideGesture(_ enableHideGesture: Bool? = true) -> Self {
var newSelf = self modify { $0.enableHideGesture = enableHideGesture }
newSelf.enableHideGesture = enableHideGesture
return newSelf
} }
/// Whether the sidebar can be opened with an edge swipe gesture. /// Whether the sidebar can be opened with an edge swipe gesture.
/// ///
/// Only touchscreen swipes are supported. /// Only touchscreen swipes are supported.
public func enableShowGesture(_ enableShowGesture: Bool? = true) -> Self { public func enableShowGesture(_ enableShowGesture: Bool? = true) -> Self {
var newSelf = self modify { $0.enableShowGesture = enableShowGesture }
newSelf.enableShowGesture = enableShowGesture
return newSelf
} }
/// The maximum sidebar width. /// The maximum sidebar width.
/// ///
/// Maximum width is affected by /// Maximum width is affected by
/// [property@OverlaySplitView:sidebar-width-unit]. /// ``sidebarWidthUnit(_:)``.
/// ///
/// The sidebar widget can still be allocated with larger width if its own /// The sidebar widget can still be allocated with larger width if its own
/// minimum width exceeds it. /// minimum width exceeds it.
public func maxSidebarWidth(_ maxSidebarWidth: Double?) -> Self { public func maxSidebarWidth(_ maxSidebarWidth: Double?) -> Self {
var newSelf = self modify { $0.maxSidebarWidth = maxSidebarWidth }
newSelf.maxSidebarWidth = maxSidebarWidth
return newSelf
} }
/// The minimum sidebar width. /// The minimum sidebar width.
/// ///
/// Minimum width is affected by /// Minimum width is affected by
/// [property@OverlaySplitView:sidebar-width-unit]. /// ``sidebarWidthUnit(_:)``.
/// ///
/// The sidebar widget can still be allocated with larger width if its own /// The sidebar widget can still be allocated with larger width if its own
/// minimum width exceeds it. /// minimum width exceeds it.
public func minSidebarWidth(_ minSidebarWidth: Double?) -> Self { public func minSidebarWidth(_ minSidebarWidth: Double?) -> Self {
var newSelf = self modify { $0.minSidebarWidth = minSidebarWidth }
newSelf.minSidebarWidth = minSidebarWidth
return newSelf
} }
/// Whether the sidebar widget is pinned. /// Whether the sidebar widget is pinned.
/// ///
/// By default, collapsing @self automatically hides the sidebar widget, and /// By default, collapsing @self automatically hides the sidebar widget, and
/// uncollapsing it shows the sidebar. If set to `TRUE`, sidebar visibility /// uncollapsing it shows the sidebar. If set to `true`, sidebar visibility
/// never changes on its own. /// never changes on its own.
public func pinSidebar(_ pinSidebar: Bool? = true) -> Self { public func pinSidebar(_ pinSidebar: Bool? = true) -> Self {
var newSelf = self modify { $0.pinSidebar = pinSidebar }
newSelf.pinSidebar = pinSidebar
return newSelf
} }
/// Whether the sidebar widget is shown. /// Whether the sidebar widget is shown.
public func showSidebar(_ showSidebar: Binding<Bool>?) -> Self { public func showSidebar(_ showSidebar: Binding<Bool>?) -> Self {
var newSelf = self modify { $0.showSidebar = showSidebar }
newSelf.showSidebar = showSidebar
return newSelf
} }
/// The sidebar widget. /// The sidebar widget.
public func sidebar(@ViewBuilder _ sidebar: @escaping (() -> Body)) -> Self { public func sidebar(@ViewBuilder _ sidebar: () -> Body) -> Self {
var newSelf = self modify { $0.sidebar = sidebar() }
newSelf.sidebar = sidebar
return newSelf
} }
/// The preferred sidebar width as a fraction of the total width. /// The preferred sidebar width as a fraction of the total width.
/// ///
/// The preferred width is additionally limited by /// The preferred width is additionally limited by
/// [property@OverlaySplitView:min-sidebar-width] and /// ``minSidebarWidth(_:)`` and
/// [property@OverlaySplitView:max-sidebar-width]. /// ``maxSidebarWidth(_:)``.
/// ///
/// The sidebar widget can be allocated with larger width if its own minimum /// The sidebar widget can be allocated with larger width if its own minimum
/// width exceeds the preferred width. /// width exceeds the preferred width.
public func sidebarWidthFraction(_ sidebarWidthFraction: Double?) -> Self { public func sidebarWidthFraction(_ sidebarWidthFraction: Double?) -> Self {
var newSelf = self modify { $0.sidebarWidthFraction = sidebarWidthFraction }
newSelf.sidebarWidthFraction = sidebarWidthFraction
return newSelf
} }
} }

View File

@ -2,15 +2,15 @@
// PasswordEntryRow.swift // PasswordEntryRow.swift
// Adwaita // Adwaita
// //
// Created by auto-generation on 15.08.24. // Created by auto-generation on 04.02.26.
// //
import CAdw import CAdw
import LevenshteinTransformations import LevenshteinTransformations
/// A [class@EntryRow] tailored for entering secrets. /// A `EntryRow` tailored for entering secrets.
///
/// ///
/// <picture><source srcset="password-entry-row-dark.png" media="(prefers-color-scheme: dark)"><img src="password-entry-row.png" alt="password-entry-row"></picture>
/// ///
/// It does not show its contents in clear text, does not allow to copy it to the /// It does not show its contents in clear text, does not allow to copy it to the
/// clipboard, and shows a warning when Caps Lock is engaged. If the underlying /// clipboard, and shows a warning when Caps Lock is engaged. If the underlying
@ -20,16 +20,20 @@ import LevenshteinTransformations
/// ///
/// It offer a way to reveal the contents in clear text. /// It offer a way to reveal the contents in clear text.
/// ///
/// ## CSS Nodes
/// ///
/// `AdwPasswordEntryRow` has a single CSS node with name `row` that carries
/// `.entry` and `.password` style classes.
public struct PasswordEntryRow: AdwaitaWidget { 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. /// Additional update functions for type extensions.
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = [] var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
/// Additional appear functions for type extensions. /// Additional appear functions for type extensions.
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = [] var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
#endif
/// Whether activating the embedded entry can activate the default widget. /// Whether activating the embedded entry can activate the default widget.
var activatesDefault: Bool? var activatesDefault: Bool?
@ -37,11 +41,13 @@ public struct PasswordEntryRow: AdwaitaWidget {
/// ///
/// Emoji replacement is done with :-delimited names, like `:heart:`. /// Emoji replacement is done with :-delimited names, like `:heart:`.
var enableEmojiCompletion: Bool? var enableEmojiCompletion: Bool?
/// Maximum number of characters for the entry.
var maxLength: Int?
/// Whether to show the apply button. /// Whether to show the apply button.
/// ///
/// When set to `TRUE`, typing text in the entry will reveal an apply button. /// When set to `true`, typing text in the entry will reveal an apply button.
/// Clicking it or pressing the <kbd>Enter</kbd> key will hide the button and /// Clicking it or pressing the <kbd>Enter</kbd> key will hide the button and
/// emit the [signal@EntryRow::apply] signal. /// emit the `EntryRow::apply` signal.
/// ///
/// This is useful if changing the entry contents can trigger an expensive /// This is useful if changing the entry contents can trigger an expensive
/// operation, e.g. network activity, to avoid triggering it after typing every /// operation, e.g. network activity, to avoid triggering it after typing every
@ -52,23 +58,23 @@ public struct PasswordEntryRow: AdwaitaWidget {
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
var title: String? var title: String?
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
var titleSelectable: Bool? var titleSelectable: Bool?
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
var useMarkup: Bool? var useMarkup: Bool?
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
var useUnderline: Bool? var useUnderline: Bool?
/// Emitted when the apply button is pressed. /// Emitted when the apply button is pressed.
/// ///
/// See [property@EntryRow:show-apply-button]. /// See ``showApplyButton(_:)``.
var apply: (() -> Void)? var apply: (() -> Void)?
/// Emitted when the embedded entry is activated. /// Emitted when the embedded entry is activated.
var entryActivated: (() -> Void)? var entryActivated: (() -> Void)?
@ -78,7 +84,7 @@ public struct PasswordEntryRow: AdwaitaWidget {
var prefix: () -> Body = { [] } var prefix: () -> Body = { [] }
/// Initialize `PasswordEntryRow`. /// Initialize `PasswordEntryRow`.
public init() { init() {
} }
/// The view storage. /// The view storage.
@ -91,7 +97,6 @@ public struct PasswordEntryRow: AdwaitaWidget {
for function in appearFunctions { for function in appearFunctions {
function(storage, data) function(storage, data)
} }
update(storage, data: data, updateProperties: true, type: type)
var suffixStorage: [ViewStorage] = [] var suffixStorage: [ViewStorage] = []
for view in suffix() { for view in suffix() {
@ -133,6 +138,9 @@ public struct PasswordEntryRow: AdwaitaWidget {
if let enableEmojiCompletion, updateProperties, (storage.previousState as? Self)?.enableEmojiCompletion != enableEmojiCompletion { if let enableEmojiCompletion, updateProperties, (storage.previousState as? Self)?.enableEmojiCompletion != enableEmojiCompletion {
adw_entry_row_set_enable_emoji_completion(widget?.cast(), enableEmojiCompletion.cBool) adw_entry_row_set_enable_emoji_completion(widget?.cast(), enableEmojiCompletion.cBool)
} }
if let maxLength, updateProperties, (storage.previousState as? Self)?.maxLength != maxLength {
adw_entry_row_set_max_length(widget?.cast(), maxLength.cInt)
}
if let showApplyButton, updateProperties, (storage.previousState as? Self)?.showApplyButton != showApplyButton { if let showApplyButton, updateProperties, (storage.previousState as? Self)?.showApplyButton != showApplyButton {
adw_entry_row_set_show_apply_button(widget?.cast(), showApplyButton.cBool) adw_entry_row_set_show_apply_button(widget?.cast(), showApplyButton.cBool)
} }
@ -150,6 +158,7 @@ public struct PasswordEntryRow: AdwaitaWidget {
} }
} }
for function in updateFunctions { for function in updateFunctions {
function(storage, data, updateProperties) function(storage, data, updateProperties)
@ -161,90 +170,71 @@ public struct PasswordEntryRow: AdwaitaWidget {
/// Whether activating the embedded entry can activate the default widget. /// Whether activating the embedded entry can activate the default widget.
public func activatesDefault(_ activatesDefault: Bool? = true) -> Self { public func activatesDefault(_ activatesDefault: Bool? = true) -> Self {
var newSelf = self modify { $0.activatesDefault = activatesDefault }
newSelf.activatesDefault = activatesDefault
return newSelf
} }
/// Whether to suggest emoji replacements on the entry row. /// Whether to suggest emoji replacements on the entry row.
/// ///
/// Emoji replacement is done with :-delimited names, like `:heart:`. /// Emoji replacement is done with :-delimited names, like `:heart:`.
public func enableEmojiCompletion(_ enableEmojiCompletion: Bool? = true) -> Self { public func enableEmojiCompletion(_ enableEmojiCompletion: Bool? = true) -> Self {
var newSelf = self modify { $0.enableEmojiCompletion = enableEmojiCompletion }
newSelf.enableEmojiCompletion = enableEmojiCompletion }
return newSelf /// Maximum number of characters for the entry.
public func maxLength(_ maxLength: Int?) -> Self {
modify { $0.maxLength = maxLength }
} }
/// Whether to show the apply button. /// Whether to show the apply button.
/// ///
/// When set to `TRUE`, typing text in the entry will reveal an apply button. /// When set to `true`, typing text in the entry will reveal an apply button.
/// Clicking it or pressing the <kbd>Enter</kbd> key will hide the button and /// Clicking it or pressing the <kbd>Enter</kbd> key will hide the button and
/// emit the [signal@EntryRow::apply] signal. /// emit the `EntryRow::apply` signal.
/// ///
/// This is useful if changing the entry contents can trigger an expensive /// This is useful if changing the entry contents can trigger an expensive
/// operation, e.g. network activity, to avoid triggering it after typing every /// operation, e.g. network activity, to avoid triggering it after typing every
/// character. /// character.
public func showApplyButton(_ showApplyButton: Bool? = true) -> Self { public func showApplyButton(_ showApplyButton: Bool? = true) -> Self {
var newSelf = self modify { $0.showApplyButton = showApplyButton }
newSelf.showApplyButton = showApplyButton
return newSelf
} }
/// The length of the text in the entry row. /// The length of the text in the entry row.
public func textLength(_ textLength: UInt?) -> Self { public func textLength(_ textLength: UInt?) -> Self {
var newSelf = self modify { $0.textLength = textLength }
newSelf.textLength = textLength
return newSelf
} }
/// The title of the preference represented by this row. /// The title of the preference represented by this row.
/// ///
/// The title is interpreted as Pango markup unless /// The title is interpreted as Pango markup unless
/// [property@PreferencesRow:use-markup] is set to `FALSE`. /// ``useMarkup(_:)`` is set to `false`.
public func title(_ title: String?) -> Self { public func title(_ title: String?) -> Self {
var newSelf = self modify { $0.title = title }
newSelf.title = title
return newSelf
} }
/// Whether the user can copy the title from the label. /// Whether the user can copy the title from the label.
/// ///
/// See also [property@Gtk.Label:selectable]. /// See also ``selectable(_:)``.
public func titleSelectable(_ titleSelectable: Bool? = true) -> Self { public func titleSelectable(_ titleSelectable: Bool? = true) -> Self {
var newSelf = self modify { $0.titleSelectable = titleSelectable }
newSelf.titleSelectable = titleSelectable
return newSelf
} }
/// Whether to use Pango markup for the title label. /// Whether to use Pango markup for the title label.
/// ///
/// Subclasses may also use it for other labels, such as subtitle. /// Subclasses may also use it for other labels, such as subtitle.
/// ///
/// See also [func@Pango.parse_markup]. /// See also `Pango.parse_markup`.
public func useMarkup(_ useMarkup: Bool? = true) -> Self { public func useMarkup(_ useMarkup: Bool? = true) -> Self {
var newSelf = self modify { $0.useMarkup = useMarkup }
newSelf.useMarkup = useMarkup
return newSelf
} }
/// Whether an embedded underline in the title indicates a mnemonic. /// Whether an embedded underline in the title indicates a mnemonic.
public func useUnderline(_ useUnderline: Bool? = true) -> Self { public func useUnderline(_ useUnderline: Bool? = true) -> Self {
var newSelf = self modify { $0.useUnderline = useUnderline }
newSelf.useUnderline = useUnderline
return newSelf
} }
/// Emitted when the apply button is pressed. /// Emitted when the apply button is pressed.
/// ///
/// See [property@EntryRow:show-apply-button]. /// See ``showApplyButton(_:)``.
public func apply(_ apply: @escaping () -> Void) -> Self { public func apply(_ apply: @escaping () -> Void) -> Self {
var newSelf = self var newSelf = self
newSelf.apply = apply newSelf.apply = apply

Some files were not shown because too many files have changed in this diff Show More