Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d928b464f1 | |||
| 2072c16040 | |||
| c08a9dc3bd | |||
| 7e41c9b5df | |||
| 6acf83dce3 | |||
| 0fc91dc50e | |||
| d0d7d2b6d3 | |||
| 8f6a83dfc3 | |||
| c976c29cd0 | |||
| 6b76a4c8f4 | |||
| 19aa17c0ab | |||
| 54619c69f4 | |||
| 07d6a38edc | |||
| 29194341e2 | |||
| cf60b8103f | |||
| b364557f2f | |||
| adae811e41 | |||
| c29c6e22cb | |||
| 92fe4fb256 | |||
| 4de2d312ab | |||
| a524cde9b0 | |||
| 7eb2bf7bb2 | |||
| 90e8c78163 | |||
| 1418d1333c | |||
| 557ec14232 | |||
| edb6a81812 | |||
| 04c77831b5 | |||
| fd29eccd68 | |||
|
|
f86e968028 | ||
| ac2dbadedb | |||
| 5b9047ea85 | |||
| 571ed60954 | |||
| c8ce2cc2fe | |||
| 037a697c74 | |||
| e430031bbc | |||
| 1bc36e0759 | |||
| d17306f195 | |||
|
|
fea203fabd | ||
| 6e6265aa76 | |||
| 0d4db96f60 | |||
|
|
ebb2455fe1 | ||
| 4eb58b154c | |||
| 87b970d844 | |||
| 0af3864058 | |||
|
|
daa922d33b | ||
| 4e95e4e655 | |||
|
|
d53ba5f4e7 | ||
| 049b5b54f8 | |||
| a04bd9025d | |||
| 7eeec9e0fd | |||
| a996be3f16 | |||
| f209c8387c | |||
| 513a5d36a3 | |||
| befa7d52ea | |||
| 4290dd4137 | |||
| 281bf7cf40 | |||
| a898efcdf8 | |||
| 62b3aa93b2 | |||
| 9ae203fd7b | |||
| 90349fd435 | |||
| f89b44cee6 | |||
| 5613ce13cd | |||
| a0c0136298 | |||
| 90beecaeb9 | |||
| 776b63f46a | |||
| 6a9f05bc18 | |||
| 4b23fe16d1 | |||
| 188007ceb3 | |||
| 6229b85f46 | |||
| 6bf6df0c6f | |||
| d93bc321a2 | |||
| e2da50703c | |||
| 2d12c57236 | |||
| 356eec00a9 | |||
| ced07e4293 | |||
| e7c81dba1d | |||
| 963a02b1e1 | |||
| 016425e329 | |||
| 8c50494c74 | |||
| 4913c0a382 | |||
| c893a8f0c6 |
@ -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;
|
||||
sed -i '' 's/,2px/,10px/g' docs/css/index.*.css
|
||||
- name: Upload
|
||||
uses: wangyucode/sftp-upload-action@v2.0.2
|
||||
uses: wangyucode/sftp-upload-action@v2.0.4
|
||||
with:
|
||||
host: 'volans.uberspace.de'
|
||||
username: 'akforum'
|
||||
|
||||
@ -154,5 +154,5 @@ type_contents_order:
|
||||
- other_method
|
||||
|
||||
excluded:
|
||||
- Sources/Core/View/Generated/
|
||||
- Sources/Adwaita/View/Generated/
|
||||
- .build/
|
||||
@ -1,4 +1,4 @@
|
||||
// swift-tools-version: 6.0
|
||||
// swift-tools-version: 6.1
|
||||
//
|
||||
// Package.swift
|
||||
// Adwaita
|
||||
@ -8,40 +8,44 @@
|
||||
|
||||
import PackageDescription
|
||||
|
||||
/// The dependencies.
|
||||
var dependencies: [Package.Dependency] = [
|
||||
.package(url: "https://git.aparoksha.dev/aparoksha/meta", branch: "main"),
|
||||
.package(url: "https://git.aparoksha.dev/aparoksha/meta-sqlite", branch: "main"),
|
||||
.package(
|
||||
url: "https://git.aparoksha.dev/aparoksha/levenshtein-transformations",
|
||||
branch: "main"
|
||||
),
|
||||
.package(url: "https://github.com/CoreOffice/XMLCoder", from: "0.17.1")
|
||||
]
|
||||
|
||||
#if os(Linux)
|
||||
dependencies.append(.package(url: "https://github.com/stephencelis/CSQLite", from: "3.50.4"))
|
||||
#endif
|
||||
|
||||
/// The Adwaita package.
|
||||
let package = Package(
|
||||
name: "Adwaita",
|
||||
platforms: [.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
|
||||
platforms: [.macOS(.v13), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), .macCatalyst(.v13)],
|
||||
products: [
|
||||
.library(
|
||||
name: "Adwaita",
|
||||
targets: ["Adwaita"]
|
||||
),
|
||||
.library(
|
||||
name: "Core",
|
||||
targets: ["Core"]
|
||||
),
|
||||
.library(
|
||||
name: "CAdw",
|
||||
targets: ["CAdw"]
|
||||
)
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://git.aparoksha.dev/aparoksha/meta", from: "0.1.0"),
|
||||
.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")
|
||||
],
|
||||
traits: [.trait(name: "exposeGeneratedAppearUpdateFunctions")],
|
||||
dependencies: dependencies,
|
||||
targets: [
|
||||
.systemLibrary(
|
||||
name: "CAdw",
|
||||
pkgConfig: "libadwaita-1"
|
||||
),
|
||||
.target(
|
||||
name: "Core",
|
||||
name: "Adwaita",
|
||||
dependencies: [
|
||||
"CAdw",
|
||||
.product(name: "LevenshteinTransformations", package: "levenshtein-transformations"),
|
||||
@ -49,10 +53,6 @@ let package = Package(
|
||||
.product(name: "MetaSQLite", package: "meta-sqlite")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "Adwaita",
|
||||
dependencies: ["Core"]
|
||||
),
|
||||
.executableTarget(
|
||||
name: "Generation",
|
||||
dependencies: [
|
||||
|
||||
@ -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.
|
||||
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.
|
||||
|
||||
#### Directly on System
|
||||
@ -92,7 +92,7 @@ brew install libadwaita
|
||||
|
||||
## 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_.
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@ -33,7 +33,7 @@ public class AdwaitaApp: AppStorage {
|
||||
/// - Parameter id: The identifier.
|
||||
public required init(id: String) {
|
||||
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.
|
||||
@ -100,7 +100,9 @@ public class AdwaitaApp: AppStorage {
|
||||
g_action_map_add_action(.init(pointer), action)
|
||||
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.
|
||||
23
Sources/Adwaita/Model/Enumerations/ColorScheme.swift
Normal file
23
Sources/Adwaita/Model/Enumerations/ColorScheme.swift
Normal 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)
|
||||
}
|
||||
|
||||
}
|
||||
@ -29,7 +29,7 @@ public enum Icon {
|
||||
}
|
||||
|
||||
/// A preinstalled icon.
|
||||
public enum DefaultIcon: String {
|
||||
public enum DefaultIcon: String, CaseIterable {
|
||||
// swiftlint:disable missing_docs identifier_name
|
||||
case acAdapter
|
||||
case accessoriesCalculator
|
||||
@ -40,7 +40,6 @@ public enum Icon {
|
||||
case addressBookNew
|
||||
case airplaneMode
|
||||
case alarm
|
||||
case appRemove
|
||||
case appletsScreenshooter
|
||||
case applicationCertificate
|
||||
case applicationExitRtl
|
||||
@ -288,7 +287,6 @@ public enum Icon {
|
||||
case functionLinear
|
||||
case gestureSwipeLeft
|
||||
case gestureSwipeRight
|
||||
case gnomeDisksStateStandby
|
||||
case gnomePowerManager
|
||||
case goBottom
|
||||
case goDown
|
||||
@ -301,12 +299,6 @@ public enum Icon {
|
||||
case goPrevious
|
||||
case goTop
|
||||
case goUp
|
||||
case goaAccountExchange
|
||||
case goaAccountGoogle
|
||||
case goaAccountLastfm
|
||||
case goaAccountMsn
|
||||
case goaAccountOwncloud
|
||||
case goaAccount
|
||||
case goaPanel
|
||||
case gtk3Demo
|
||||
case gtk3WidgetFactory
|
||||
@ -317,7 +309,6 @@ public enum Icon {
|
||||
case imageLoading
|
||||
case imageMissing
|
||||
case imageXGeneric
|
||||
case info
|
||||
case inodeDirectory
|
||||
case inputDialpad
|
||||
case inputGaming
|
||||
@ -343,13 +334,6 @@ public enum Icon {
|
||||
case langTypedef
|
||||
case langUnion
|
||||
case langVariable
|
||||
case libreofficeBase
|
||||
case libreofficeCalc
|
||||
case libreofficeDraw
|
||||
case libreofficeImpress
|
||||
case libreofficeMain
|
||||
case libreofficeMath
|
||||
case libreofficeWriter
|
||||
case listAdd
|
||||
case listDragHandle
|
||||
case listRemoveAll
|
||||
@ -469,9 +453,6 @@ public enum Icon {
|
||||
case networkWorkgroup
|
||||
case nightLightDisabled
|
||||
case nightLight
|
||||
case nmDeviceWiredSecure
|
||||
case nmDeviceWired
|
||||
case nmDeviceWwan
|
||||
case nonStarred
|
||||
case notificationsDisabled
|
||||
case objectFlipHorizontal
|
||||
@ -480,70 +461,6 @@ public enum Icon {
|
||||
case objectRotateRight
|
||||
case objectSelect
|
||||
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 gtkIconBrowser4 = "org.gtk.IconBrowser4"
|
||||
case gtkPrintEditor4 = "org.gtk.PrintEditor4"
|
||||
@ -554,18 +471,12 @@ public enum Icon {
|
||||
case orientationPortraitInverse
|
||||
case orientationPortraitLeft
|
||||
case orientationPortraitRight
|
||||
case orientationProtrait
|
||||
case orientationPortrait
|
||||
case packageXGeneric
|
||||
case panDown
|
||||
case panEnd
|
||||
case panStart
|
||||
case panUp
|
||||
case panelBottom
|
||||
case panelCenter
|
||||
case panelLeft
|
||||
case panelModified
|
||||
case panelRight
|
||||
case panelTop
|
||||
case pda
|
||||
case phoneAppleIphone
|
||||
case phoneOld
|
||||
@ -629,7 +540,6 @@ public enum Icon {
|
||||
case sidebarShow
|
||||
case softwareUpdateAvailable
|
||||
case softwareUpdateUrgent
|
||||
case speedometer
|
||||
case starNew
|
||||
case starred
|
||||
case startHere
|
||||
@ -652,13 +562,11 @@ public enum Icon {
|
||||
case tablet
|
||||
case taskDue
|
||||
case taskPastDue
|
||||
case temperature
|
||||
case textEditor
|
||||
case textXGeneric
|
||||
case thunderboltAcquiring
|
||||
case thunderbolt
|
||||
case toolsCheckSpelling
|
||||
case totemTv
|
||||
case touchDisabled
|
||||
case touchpadDisabled
|
||||
case tv
|
||||
@ -681,7 +589,7 @@ public enum Icon {
|
||||
case valueDecrease
|
||||
case valueIncrease
|
||||
case videoDisplay
|
||||
case videoJoineDisplays
|
||||
case videoJoinedDisplays
|
||||
case videoSingleDisplay
|
||||
case videoXGeneric
|
||||
case viewAppGrid
|
||||
@ -716,7 +624,6 @@ public enum Icon {
|
||||
case weatherFewCloudsNight
|
||||
case weatherFewClouds
|
||||
case weatherFog
|
||||
case weatherHourly
|
||||
case weatherOvercast
|
||||
case weatherSevereAlert
|
||||
case weatherShowersScattered
|
||||
27
Sources/Adwaita/Model/Enumerations/ScrollbarVisibility.swift
Normal file
27
Sources/Adwaita/Model/Enumerations/ScrollbarVisibility.swift
Normal 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
|
||||
/// Don’t show a scrollbar, but don’t force the size to follow the content.
|
||||
case external
|
||||
|
||||
/// The ScrollbarVisibility value as a GtkPolicyType value.
|
||||
var gtkValue: GtkPolicyType {
|
||||
.init(rawValue)
|
||||
}
|
||||
|
||||
}
|
||||
25
Sources/Adwaita/Model/Enumerations/ToolbarStyle.swift
Normal file
25
Sources/Adwaita/Model/Enumerations/ToolbarStyle.swift
Normal 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)
|
||||
}
|
||||
|
||||
}
|
||||
54
Sources/Adwaita/Model/Enumerations/WrapMode.swift
Normal file
54
Sources/Adwaita/Model/Enumerations/WrapMode.swift
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,8 @@
|
||||
// Created by david-swift on 15.01.24.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
|
||||
extension Bool {
|
||||
|
||||
/// Get the gboolean for C.
|
||||
19
Sources/Adwaita/Model/Extensions/GtkWrapMode.swift
Normal file
19
Sources/Adwaita/Model/Extensions/GtkWrapMode.swift
Normal 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))
|
||||
}
|
||||
|
||||
}
|
||||
@ -78,6 +78,20 @@ public struct Idle {
|
||||
/// An idle handler.
|
||||
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.
|
||||
/// - Parameter closure: The function.
|
||||
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.
|
||||
@ -11,13 +11,15 @@ import CAdw
|
||||
public class SignalData {
|
||||
|
||||
/// 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.
|
||||
var handler: @convention(c) (UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Void {
|
||||
{ _, data in
|
||||
let data = unsafeBitCast(data, to: SignalData.self)
|
||||
data.closure([])
|
||||
_ = data.closure([])
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +31,7 @@ public class SignalData {
|
||||
) -> Void {
|
||||
{ _, arg1, data in
|
||||
let data = unsafeBitCast(data, to: SignalData.self)
|
||||
data.closure([arg1])
|
||||
_ = data.closure([arg1])
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +44,7 @@ public class SignalData {
|
||||
) -> Void {
|
||||
{ _, arg1, arg2, data in
|
||||
let data = unsafeBitCast(data, to: SignalData.self)
|
||||
data.closure([arg1, arg2])
|
||||
_ = data.closure([arg1, arg2])
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,20 +58,49 @@ public class SignalData {
|
||||
) -> Void {
|
||||
{ _, arg1, arg2, arg3, data in
|
||||
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.
|
||||
/// - Parameter closure: The signal's closure.
|
||||
public convenience init(closure: @escaping () -> Void) {
|
||||
self.init { _ in closure() }
|
||||
/// - Parameters:
|
||||
/// - closure: The signal's 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.
|
||||
/// - Parameter closure: The signal's closure.
|
||||
public init(closure: @escaping ([Any]) -> Void) {
|
||||
/// - Parameters:
|
||||
/// - 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.selfDestruction = destroy
|
||||
}
|
||||
|
||||
/// The return type.
|
||||
public enum ReturnType {
|
||||
|
||||
/// Returns a boolean.
|
||||
case bool
|
||||
|
||||
}
|
||||
|
||||
/// Connect the signal data to a signal.
|
||||
@ -77,9 +108,20 @@ public class SignalData {
|
||||
/// - pointer: The pointer to the object which holds the signal.
|
||||
/// - signal: The signal's name.
|
||||
/// - 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
|
||||
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)
|
||||
} else if argCount == 2 {
|
||||
callback = unsafeBitCast(fourParamsHandler, to: GCallback.self)
|
||||
@ -88,12 +130,19 @@ public class SignalData {
|
||||
} else {
|
||||
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(
|
||||
pointer,
|
||||
signal,
|
||||
callback,
|
||||
Unmanaged.passUnretained(self).toOpaque().cast(),
|
||||
nil,
|
||||
destroy,
|
||||
G_CONNECT_AFTER
|
||||
)
|
||||
}
|
||||
@ -48,7 +48,30 @@ extension Storage {
|
||||
pointer: OpaquePointer? = nil,
|
||||
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()
|
||||
}
|
||||
}
|
||||
@ -66,13 +89,42 @@ extension Storage {
|
||||
argCount: Int = 0,
|
||||
pointer: OpaquePointer? = nil,
|
||||
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 {
|
||||
data.closure = handler
|
||||
} else {
|
||||
let data = SignalData(closure: handler)
|
||||
let data = SignalData(closure: handler) { [self] in fields[name + id] = nil }
|
||||
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`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@ -108,6 +108,13 @@ extension AnyView {
|
||||
style("circular", active: active)
|
||||
}
|
||||
|
||||
/// Make a button or similar widget use round appearance.
|
||||
/// - Parameter active: Whether the style is currently applied.
|
||||
/// - Returns: A view.
|
||||
public func round(_ active: Bool = true) -> AnyView {
|
||||
style("round", active: active)
|
||||
}
|
||||
|
||||
/// Make a button or similar widget appear as a pill.
|
||||
/// - Parameter active: Whether the style is currently applied.
|
||||
/// - Returns: A view.
|
||||
@ -271,13 +278,6 @@ extension AnyView {
|
||||
style("frame", active: active)
|
||||
}
|
||||
|
||||
/// Run a function when the view gets an update.
|
||||
/// - Parameter onUpdate: The function.
|
||||
/// - Returns: A view.
|
||||
public func onUpdate(_ onUpdate: @escaping () -> Void) -> AnyView {
|
||||
inspect { _, _ in onUpdate() }
|
||||
}
|
||||
|
||||
/// Bind to the view's focus.
|
||||
/// - Parameter focus: Whether the view is focused.
|
||||
/// - Returns: A view.
|
||||
@ -336,22 +336,58 @@ extension AnyView {
|
||||
}
|
||||
|
||||
/// Add CSS classes to the app as soon as the view appears.
|
||||
/// - Parameter getString: Get the CSS.
|
||||
/// - Parameters:
|
||||
/// - scheme: The color scheme.
|
||||
/// - getString: Get the CSS.
|
||||
/// - Returns: A view.
|
||||
public func css(_ getString: @escaping () -> String) -> AnyView {
|
||||
inspectOnAppear { _ in
|
||||
let provider = gtk_css_provider_new()
|
||||
gtk_css_provider_load_from_string(
|
||||
provider,
|
||||
getString()
|
||||
)
|
||||
let display = gdk_display_get_default()
|
||||
gtk_style_context_add_provider_for_display(
|
||||
display,
|
||||
provider?.opaque(),
|
||||
.init(GTK_STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
)
|
||||
public func css(scheme: ColorScheme? = nil, getString: @escaping () -> String) -> AnyView {
|
||||
wrap { storage, updateProperties in
|
||||
let cssID = "internal-css"
|
||||
let providerID = "internal-css-provider"
|
||||
let previous = storage.fields[cssID] as? String
|
||||
let string = getString()
|
||||
if updateProperties, string != previous {
|
||||
let provider = gtk_css_provider_new()
|
||||
if let scheme {
|
||||
gtui_cssprovider_set_prefers_color_scheme(.init(Int(bitPattern: provider)), scheme.gtkValue)
|
||||
}
|
||||
gtk_css_provider_load_from_string(
|
||||
provider,
|
||||
string
|
||||
)
|
||||
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 }
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
// Created by david-swift on 16.10.24.
|
||||
//
|
||||
|
||||
@_exported import Core
|
||||
import CAdw
|
||||
import Foundation
|
||||
|
||||
extension AnyView {
|
||||
@ -45,6 +45,8 @@ extension AnyView {
|
||||
/// - 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,
|
||||
@ -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.
|
||||
/// - Parameters:
|
||||
/// - 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.
|
||||
/// - Parameters:
|
||||
/// - open: The signal to open the dialog.
|
||||
/// - initialFolder: The URL to the folder open when being opened.
|
||||
/// - extensions: The accepted file extensions.
|
||||
/// - folders: Whether folders are accepted.
|
||||
/// - onOpen: Run this when a file for importing has been chosen.
|
||||
/// - onClose: Run this when the user cancelled the action.
|
||||
public func fileImporter(
|
||||
@ -99,17 +156,37 @@ extension AnyView {
|
||||
initialFolder: URL? = nil,
|
||||
extensions: [String]? = nil,
|
||||
onOpen: @escaping (URL) -> Void,
|
||||
onClose: @escaping () -> Void
|
||||
onClose: @escaping () -> Void = { }
|
||||
) -> AnyView {
|
||||
FileDialog(
|
||||
importer: true,
|
||||
type: .importer(folder: false, extensions: extensions),
|
||||
open: open,
|
||||
child: self,
|
||||
result: onOpen,
|
||||
cancel: onClose,
|
||||
initialFolder: initialFolder,
|
||||
initialName: nil,
|
||||
extensions: extensions
|
||||
initialFolder: initialFolder
|
||||
)
|
||||
}
|
||||
|
||||
/// 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,
|
||||
initialName: String? = nil,
|
||||
onSave: @escaping (URL) -> Void,
|
||||
onClose: @escaping () -> Void
|
||||
onClose: @escaping () -> Void = { }
|
||||
) -> AnyView {
|
||||
FileDialog(
|
||||
importer: false,
|
||||
type: .exporter(initialName: initialName),
|
||||
open: open,
|
||||
child: self,
|
||||
result: onSave,
|
||||
cancel: onClose,
|
||||
initialFolder: initialFolder,
|
||||
initialName: initialName
|
||||
initialFolder: initialFolder
|
||||
)
|
||||
}
|
||||
|
||||
@ -168,82 +244,6 @@ extension AnyView {
|
||||
.maximumSize(maxHeight ?? -1)
|
||||
}
|
||||
|
||||
/// Add padding around a view.
|
||||
/// - Parameters:
|
||||
/// - padding: The size of the padding.
|
||||
/// - edges: The edges which are affected by the padding.
|
||||
/// - Returns: A view.
|
||||
public func padding(_ padding: Int = 10, _ edges: Set<Edge> = .all) -> AnyView {
|
||||
ModifierWrapper(content: self, padding: padding, edges: edges)
|
||||
}
|
||||
|
||||
/// Enable or disable the horizontal expansion.
|
||||
/// - Parameter enabled: Whether it is enabled or disabled.
|
||||
/// - Returns: A view.
|
||||
public func hexpand(_ enabled: Bool = true) -> AnyView {
|
||||
ModifierWrapper(content: self, hexpand: enabled)
|
||||
}
|
||||
|
||||
/// Enable or disable the vertical expansion.
|
||||
/// - Parameter enabled: Whether it is enabled or disabled.
|
||||
/// - Returns: A view.
|
||||
public func vexpand(_ enabled: Bool = true) -> AnyView {
|
||||
ModifierWrapper(content: self, vexpand: enabled)
|
||||
}
|
||||
|
||||
/// Set the horizontal alignment.
|
||||
/// - Parameter align: The alignment.
|
||||
/// - Returns: A view.
|
||||
public func halign(_ align: Alignment) -> AnyView {
|
||||
ModifierWrapper(content: self, halign: align)
|
||||
}
|
||||
|
||||
/// Set the vertical alignment.
|
||||
/// - Parameter align: The alignment.
|
||||
/// - Returns: A view.
|
||||
public func valign(_ align: Alignment) -> AnyView {
|
||||
ModifierWrapper(content: self, valign: align)
|
||||
}
|
||||
|
||||
/// Set the view's minimal width or height.
|
||||
/// - Parameters:
|
||||
/// - minWidth: The minimal width.
|
||||
/// - minHeight: The minimal height.
|
||||
/// - Returns: A view.
|
||||
public func frame(minWidth: Int? = nil, minHeight: Int? = nil) -> AnyView {
|
||||
ModifierWrapper(content: self, minWidth: minWidth, minHeight: minHeight)
|
||||
}
|
||||
|
||||
/// Add a style class to the view.
|
||||
/// - Parameters:
|
||||
/// - style: The style class.
|
||||
/// - active: Whether the style is currently applied.
|
||||
/// - Returns: A view.
|
||||
public func style(_ style: String, active: Bool = true) -> AnyView {
|
||||
ModifierWrapper(content: self, style: style, styleActive: active)
|
||||
}
|
||||
|
||||
/// Make the view insensitive (useful e.g. in overlays).
|
||||
/// - Parameter insensitive: Whether the view is insensitive.
|
||||
/// - Returns: A view.
|
||||
public func insensitive(_ insensitive: Bool = true) -> AnyView {
|
||||
ModifierWrapper(content: self, insensitive: insensitive)
|
||||
}
|
||||
|
||||
/// Set the view's visibility.
|
||||
/// - Parameter visible: Whether the view is visible.
|
||||
/// - Returns: A view.
|
||||
public func visible(_ visible: Bool = true) -> AnyView {
|
||||
ModifierWrapper(content: self, visible: visible)
|
||||
}
|
||||
|
||||
/// Add a tooltip to the widget.
|
||||
/// - Parameter tooltip: The tooltip text.
|
||||
/// - Returns: A view.
|
||||
public func tooltip(_ tooltip: String) -> AnyView {
|
||||
ModifierWrapper(content: self, tooltip: tooltip)
|
||||
}
|
||||
|
||||
/// Present a toast when the signal gets activated.
|
||||
/// - Parameters:
|
||||
/// - title: The title of the toast.
|
||||
@ -267,4 +267,43 @@ extension AnyView {
|
||||
.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()
|
||||
}
|
||||
|
||||
}
|
||||
123
Sources/Adwaita/View/AnyView+wrapModifier.swift
Normal file
123
Sources/Adwaita/View/AnyView+wrapModifier.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
154
Sources/Adwaita/View/BreakpointBin.swift
Normal file
154
Sources/Adwaita/View/BreakpointBin.swift
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -45,8 +45,11 @@ extension Button {
|
||||
/// - window: The application window.
|
||||
/// - active: Whether the keyboard shortcut is active.
|
||||
/// - Returns: The button.
|
||||
public func keyboardShortcut(_ shortcut: String, window: AdwaitaWindow, active: Bool = true) -> AnyView {
|
||||
onUpdate {
|
||||
public func keyboardShortcut(_ shortcut: String, active: Bool = true) -> AnyView {
|
||||
inspect { _, data, _ in
|
||||
guard let window = data.sceneStorage.pointer as? AdwaitaWindow else {
|
||||
return
|
||||
}
|
||||
if active {
|
||||
window.app.addKeyboardShortcut(shortcut, id: shortcut, window: window) { self.clicked?() }
|
||||
} else {
|
||||
@ -63,12 +66,15 @@ extension Button {
|
||||
/// - window: The application.
|
||||
/// - active: Whether the keyboard shortcut is active.
|
||||
/// - Returns: The button.
|
||||
public func keyboardShortcut(_ shortcut: String, app: AdwaitaApp, active: Bool = true) -> AnyView {
|
||||
onUpdate {
|
||||
public func appKeyboardShortcut(_ shortcut: String, active: Bool = true) -> AnyView {
|
||||
inspect { _, data, _ in
|
||||
guard let window = data.sceneStorage.pointer as? AdwaitaWindow else {
|
||||
return
|
||||
}
|
||||
if active {
|
||||
app.addKeyboardShortcut(shortcut, id: shortcut) { self.clicked?() }
|
||||
window.app.addKeyboardShortcut(shortcut, id: shortcut) { self.clicked?() }
|
||||
} else {
|
||||
app.removeKeyboardShortcut(id: shortcut)
|
||||
window.app.removeKeyboardShortcut(id: shortcut)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ import CAdw
|
||||
import Foundation
|
||||
|
||||
/// The about dialog widget.
|
||||
public struct AboutDialog: AdwaitaWidget {
|
||||
struct AboutDialog: AdwaitaWidget {
|
||||
|
||||
/// Whether the dialog is visible.
|
||||
@Binding var visible: Bool
|
||||
@ -42,7 +42,7 @@ public struct AboutDialog: AdwaitaWidget {
|
||||
/// - icon: The icon.
|
||||
/// - website: The website's URL.
|
||||
/// - issues: The link for opening issues.
|
||||
public init(
|
||||
init(
|
||||
visible: Binding<Bool>,
|
||||
child: AnyView,
|
||||
appName: String? = nil,
|
||||
@ -67,10 +67,8 @@ public struct AboutDialog: AdwaitaWidget {
|
||||
/// - 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 = child.storage(data: data, type: type)
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
return storage
|
||||
func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
|
||||
child.storage(data: data, type: type)
|
||||
}
|
||||
|
||||
/// Update the stored content.
|
||||
@ -79,14 +77,14 @@ public struct AboutDialog: AdwaitaWidget {
|
||||
/// - modifiers: Modify views before being updated
|
||||
/// - updateProperties: Whether to update the view's properties.
|
||||
/// - type: The view render data type.
|
||||
public func update<Data>(
|
||||
func update<Data>(
|
||||
_ storage: ViewStorage,
|
||||
data: WidgetData,
|
||||
updateProperties: Bool,
|
||||
type: Data.Type
|
||||
) where Data: ViewRenderData {
|
||||
child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
|
||||
guard updateProperties, (storage.previousState as? Self)?.visible != visible else {
|
||||
guard updateProperties else {
|
||||
return
|
||||
}
|
||||
if visible {
|
||||
@ -119,10 +117,11 @@ public struct AboutDialog: AdwaitaWidget {
|
||||
adw_dialog_set_content_height(dialog?.cast(), -1)
|
||||
} else {
|
||||
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.
|
||||
@ -28,6 +28,8 @@ public struct AlertDialog: AdwaitaWidget {
|
||||
var heading: String
|
||||
/// The body text.
|
||||
var body: String
|
||||
/// The body view.
|
||||
var extraChild: Body?
|
||||
/// The available responses.
|
||||
var responses: [Response] = []
|
||||
/// The child view.
|
||||
@ -40,18 +42,21 @@ public struct AlertDialog: AdwaitaWidget {
|
||||
/// - id: A unique identifier for dialogs on the view.
|
||||
/// - heading: The heading.
|
||||
/// - body: The body text.
|
||||
public init(
|
||||
/// - extraChild: The body view.
|
||||
init(
|
||||
visible: Binding<Bool>,
|
||||
child: AnyView,
|
||||
id: String,
|
||||
heading: String,
|
||||
body: String
|
||||
body: String,
|
||||
extraChild: Body? = nil
|
||||
) {
|
||||
self._visible = visible
|
||||
self.child = child
|
||||
self.id = id
|
||||
self.heading = heading
|
||||
self.body = body
|
||||
self.extraChild = extraChild
|
||||
}
|
||||
|
||||
/// Information about a response.
|
||||
@ -101,9 +106,7 @@ public struct AlertDialog: AdwaitaWidget {
|
||||
data: WidgetData,
|
||||
type: Data.Type
|
||||
) -> ViewStorage where Data: ViewRenderData {
|
||||
let storage = child.storage(data: data, type: type)
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
return storage
|
||||
child.storage(data: data, type: type)
|
||||
}
|
||||
|
||||
/// Update the stored content.
|
||||
@ -120,13 +123,18 @@ public struct AlertDialog: AdwaitaWidget {
|
||||
) where Data: ViewRenderData {
|
||||
storage.fields[Self.visibleID + id] = _visible
|
||||
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 {
|
||||
return
|
||||
}
|
||||
if visible {
|
||||
var present = false
|
||||
if storage.content[Self.dialogID + id]?.first == nil {
|
||||
createDialog(storage: storage)
|
||||
createDialog(storage: storage, data: data)
|
||||
present = true
|
||||
}
|
||||
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] ?? []
|
||||
old.identifiableTransform(
|
||||
to: responses,
|
||||
functions: .init { index, element 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
|
||||
functions: .init { index in
|
||||
adw_alert_dialog_remove_response(pointer?.cast(), responseID(old[safe: index]?.id))
|
||||
} insert: { _, element in
|
||||
adw_alert_dialog_add_response(pointer?.cast(), responseID(element.id), element.title)
|
||||
@ -160,7 +165,9 @@ public struct AlertDialog: AdwaitaWidget {
|
||||
}
|
||||
} else {
|
||||
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.
|
||||
/// - Parameter storage: The wrapped view's storage.
|
||||
func createDialog(storage: ViewStorage) {
|
||||
/// - Parameters:
|
||||
/// - 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 dialog = ViewStorage(pointer?.opaque())
|
||||
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.
|
||||
@ -8,7 +8,7 @@
|
||||
import CAdw
|
||||
|
||||
/// The dialog widget.
|
||||
public struct Dialog: AdwaitaWidget {
|
||||
struct Dialog: AdwaitaWidget {
|
||||
|
||||
/// Whether the dialog is visible.
|
||||
@Binding var visible: Bool
|
||||
@ -39,7 +39,7 @@ public struct Dialog: AdwaitaWidget {
|
||||
/// - title: The title.
|
||||
/// - width: The width.
|
||||
/// - height: The height.
|
||||
public init(
|
||||
init(
|
||||
visible: Binding<Bool>,
|
||||
child: AnyView,
|
||||
id: String,
|
||||
@ -62,11 +62,9 @@ public struct Dialog: AdwaitaWidget {
|
||||
/// - 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 {
|
||||
func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
|
||||
let child = child.storage(data: data, type: type)
|
||||
let storage = ViewStorage(child.opaquePointer, content: [.mainContent: [child]])
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
return storage
|
||||
return .init(child.opaquePointer, content: [.mainContent: [child]])
|
||||
}
|
||||
|
||||
/// Update the stored content.
|
||||
@ -75,7 +73,7 @@ public struct Dialog: AdwaitaWidget {
|
||||
/// - modifiers: Modify views before being updated
|
||||
/// - updateProperties: Whether to update the view's properties.
|
||||
/// - type: The view render data type.
|
||||
public func update<Data>(
|
||||
func update<Data>(
|
||||
_ storage: ViewStorage,
|
||||
data: WidgetData,
|
||||
updateProperties: Bool,
|
||||
@ -111,7 +109,9 @@ public struct Dialog: AdwaitaWidget {
|
||||
}
|
||||
} else {
|
||||
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())
|
||||
storage.content[dialogID + id] = [dialog]
|
||||
let contentStorage = content.storage(data: data, type: type)
|
||||
content.updateStorage(contentStorage, data: data, updateProperties: true, type: type)
|
||||
adw_dialog_set_child(pointer, contentStorage.opaquePointer?.cast())
|
||||
storage.content[contentID + id] = [contentStorage]
|
||||
dialog.connectSignal(name: "closed") {
|
||||
@ -9,67 +9,103 @@ import CAdw
|
||||
import Foundation
|
||||
|
||||
/// A structure representing a file dialog window.
|
||||
public struct FileDialog: AdwaitaWidget {
|
||||
struct FileDialog: AdwaitaWidget {
|
||||
|
||||
/// Whether the dialog is an importer.
|
||||
var importer: Bool
|
||||
/// The dialog type.
|
||||
var type: DialogType
|
||||
/// Whether the dialog should open.
|
||||
var open: Signal
|
||||
/// The dialog's child.
|
||||
var child: AnyView
|
||||
/// The initial folder.
|
||||
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.
|
||||
var result: (URL) -> Void
|
||||
/// The closure to run when the import or export is not successful.
|
||||
var cancel: () -> Void
|
||||
|
||||
// swiftlint:disable function_default_parameter_at_end
|
||||
/// Initialize the file dialog wrapper.
|
||||
/// - Parameters:
|
||||
/// - importer: Whether it is an importer.
|
||||
/// - type: The dialog type.
|
||||
/// - open: The signal.
|
||||
/// - child: The wrapped view.
|
||||
/// - initialFolder: The initial URL.
|
||||
/// - initialName: The initial name.
|
||||
/// - extensions: The file extensions.
|
||||
/// - result: Run when the import or export succeeds.
|
||||
/// - cancel: Run when the import or export is not successful.
|
||||
public init(
|
||||
importer: Bool = true,
|
||||
/// - initialFolder: The initial folder.
|
||||
init(
|
||||
type: DialogType,
|
||||
`open`: Signal,
|
||||
child: AnyView,
|
||||
result: @escaping (URL) -> Void,
|
||||
cancel: @escaping () -> Void,
|
||||
initialFolder: URL? = nil,
|
||||
initialName: String? = nil,
|
||||
extensions: [String]? = nil
|
||||
) {
|
||||
self.importer = importer
|
||||
self.type = type
|
||||
self.open = open
|
||||
self.child = child
|
||||
self.result = result
|
||||
self.cancel = cancel
|
||||
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.
|
||||
/// - 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 {
|
||||
func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
|
||||
let child = child.storage(data: data, type: type)
|
||||
let storage = ViewStorage(child.opaquePointer, content: [.mainContent: [child]])
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
return storage
|
||||
return .init(child.opaquePointer, content: [.mainContent: [child]])
|
||||
}
|
||||
|
||||
/// Update the stored content.
|
||||
@ -78,7 +114,7 @@ public struct FileDialog: AdwaitaWidget {
|
||||
/// - modifiers: Modify views before being updated
|
||||
/// - updateProperties: Whether to update the view's properties.
|
||||
/// - type: The view render data type.
|
||||
public func update<Data>(
|
||||
func update<Data>(
|
||||
_ storage: ViewStorage,
|
||||
data: WidgetData,
|
||||
updateProperties: Bool,
|
||||
@ -89,32 +125,45 @@ public struct FileDialog: AdwaitaWidget {
|
||||
guard let mainStorage = storage.content[.mainContent]?.first else {
|
||||
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 {
|
||||
var unref: [OpaquePointer?] = []
|
||||
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)
|
||||
}
|
||||
if let extensions {
|
||||
if let extensions = self.type.extensions {
|
||||
let filter = gtk_file_filter_new()
|
||||
for name in extensions {
|
||||
gtk_file_filter_add_suffix(filter, name)
|
||||
}
|
||||
gtk_file_dialog_set_default_filter(pointer, filter)
|
||||
unref.append(filter)
|
||||
} else {
|
||||
gtk_file_dialog_set_default_filter(pointer, nil)
|
||||
}
|
||||
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()
|
||||
callbacks.onResult = { (storage.fields["result"] as? (URL) -> Void)?($0) }
|
||||
callbacks.onCancel = { (storage.fields["cancel"] as? () -> Void)?() }
|
||||
let unrefClosure = {
|
||||
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 }
|
||||
storage.fields["callbacks"] = callbacks
|
||||
let ptr = UInt64(Int(bitPattern: pointer))
|
||||
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)
|
||||
} else {
|
||||
gtui_filedialog_save(ptr, unsafeBitCast(callbacks, to: UInt64.self), window)
|
||||
@ -135,8 +184,9 @@ class AdwaitaFileDialog {
|
||||
var reset: () -> Void = { }
|
||||
|
||||
/// Initialize the window callback.
|
||||
init() {
|
||||
}
|
||||
init() { }
|
||||
|
||||
deinit { print("DEINIT fd") }
|
||||
|
||||
/// Run this when a file gets opened.
|
||||
/// - Parameter path: The file path.
|
||||
252
Sources/Adwaita/View/Dialogs/PreferencesDialog.swift
Normal file
252
Sources/Adwaita/View/Dialogs/PreferencesDialog.swift
Normal 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))) }
|
||||
}
|
||||
|
||||
}
|
||||
192
Sources/Adwaita/View/Dialogs/ShortcutsDialog.swift
Normal file
192
Sources/Adwaita/View/Dialogs/ShortcutsDialog.swift
Normal 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))) }
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,14 @@
|
||||
//
|
||||
// ComboRow+.swift
|
||||
// DropDown+.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by david-swift on 20.01.24.
|
||||
// Created by david-swift on 09.04.25.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// A row for selecting an element out of a list of elements.
|
||||
extension ComboRow {
|
||||
extension DropDown {
|
||||
|
||||
/// The identifier for the values.
|
||||
static var values: String { "values" }
|
||||
@ -18,30 +17,40 @@ extension ComboRow {
|
||||
|
||||
/// 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 = 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 {
|
||||
.init(values.firstIndex { $0.id == selection.wrappedValue } ?? 0)
|
||||
.init(values.firstIndex { $0[keyPath: id] == selection.wrappedValue } ?? 0)
|
||||
} set: { index in
|
||||
if let id = values[safe: .init(index)]?.id {
|
||||
if let id = values[safe: .init(index)]?[keyPath: id] {
|
||||
selection.wrappedValue = id
|
||||
}
|
||||
})
|
||||
appearFunctions.append { storage, _ in
|
||||
let list = gtk_string_list_new(nil)
|
||||
storage.fields[Self.stringList] = list
|
||||
adw_combo_row_set_model(storage.opaquePointer?.cast(), list)
|
||||
Self.updateContent(storage: storage, values: values, element: Element.self)
|
||||
storage.fields[Self.stringList] = gtk_drop_down_get_model(storage.opaquePointer)
|
||||
Self.updateContent(storage: storage, values: values, id: id, description: description)
|
||||
}
|
||||
updateFunctions.append { storage, _, _ in
|
||||
Self.updateContent(storage: storage, values: values, element: Element.self)
|
||||
Self.updateContent(storage: storage, values: values, id: id, description: description)
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,23 +58,23 @@ extension ComboRow {
|
||||
/// - Parameters:
|
||||
/// - storage: The view storage.
|
||||
/// - values: The elements.
|
||||
/// - element: The type of the elements.
|
||||
static func updateContent<Element>(
|
||||
/// - id: The keypath to the id.
|
||||
/// - description: The keypath to the description.
|
||||
static func updateContent<Element, Identifier>(
|
||||
storage: ViewStorage,
|
||||
values: [Element],
|
||||
element: Element.Type
|
||||
) where Element: Identifiable, Element: CustomStringConvertible {
|
||||
id: KeyPath<Element, Identifier>,
|
||||
description: KeyPath<Element, String>
|
||||
) where Identifier: Equatable {
|
||||
if let list = storage.fields[Self.stringList] as? OpaquePointer {
|
||||
let old = storage.fields[Self.values] as? [Element] ?? []
|
||||
old.identifiableTransform(
|
||||
old.transform(
|
||||
to: values,
|
||||
functions: .init { index, element in
|
||||
gtk_string_list_remove(list, .init(index))
|
||||
gtk_string_list_append(list, element.description)
|
||||
} delete: { index in
|
||||
id: id,
|
||||
functions: .init { index in
|
||||
gtk_string_list_remove(list, .init(index))
|
||||
} insert: { _, element in
|
||||
gtk_string_list_append(list, element.description)
|
||||
gtk_string_list_append(list, element[keyPath: description])
|
||||
}
|
||||
)
|
||||
storage.fields[Self.values] = values
|
||||
21
Sources/Adwaita/View/Entry+.swift
Normal file
21
Sources/Adwaita/View/Entry+.swift
Normal 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)
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,19 +17,21 @@ extension FlowBox {
|
||||
/// Initialize `FlowBox`.
|
||||
/// - Parameters:
|
||||
/// - elements: The elements.
|
||||
/// - id: The element identifier keypath.
|
||||
/// - selection: The identifier of the selected element. Selection disabled if `nil`.
|
||||
/// - content: The view for an element.
|
||||
public init(
|
||||
_ elements: [Element],
|
||||
selection: Binding<Element.ID>?,
|
||||
id: KeyPath<Element, Identifier>,
|
||||
selection: Binding<Identifier>? = nil,
|
||||
@ViewBuilder content: @escaping (Element) -> Body
|
||||
) {
|
||||
self.init(elements, content: content)
|
||||
let id: (ViewStorage, [Element]) -> Element.ID? = { storage, elements in
|
||||
self.init(elements, id: id, content: content)
|
||||
let getID: (ViewStorage, [Element]) -> Identifier? = { storage, elements in
|
||||
if let child = g_list_nth_data(gtk_flow_box_get_selected_children(storage.opaquePointer), 0) {
|
||||
let element = gtk_flow_box_child_get_child(child.cast())
|
||||
return elements[safe: storage.content[.mainContent]?
|
||||
.firstIndex { $0.opaquePointer?.cast() == element }]?.id
|
||||
.firstIndex { $0.opaquePointer?.cast() == element }]?[keyPath: id]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -37,12 +39,12 @@ extension FlowBox {
|
||||
updateFunctions.append { storage, _, _ in
|
||||
storage.connectSignal(name: "selected_children_changed", id: Self.selectionField) {
|
||||
if let elements = storage.fields[Self.elementsField] as? [Element],
|
||||
let id = id(storage, elements) {
|
||||
let id = getID(storage, elements) {
|
||||
selection.wrappedValue = id
|
||||
}
|
||||
}
|
||||
if selection.wrappedValue != id(storage, elements),
|
||||
let index = elements.firstIndex(where: { $0.id == selection.wrappedValue })?.cInt {
|
||||
if selection.wrappedValue != getID(storage, elements),
|
||||
let index = elements.firstIndex(where: { $0[keyPath: id] == selection.wrappedValue })?.cInt {
|
||||
gtk_flow_box_select_child(
|
||||
storage.opaquePointer,
|
||||
gtk_flow_box_get_child_at_index(storage.opaquePointer, index)
|
||||
@ -57,3 +59,20 @@ extension FlowBox {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FlowBox where Element: Identifiable, Identifier == Element.ID {
|
||||
|
||||
/// Initialize `FlowBox`.
|
||||
/// - Parameters:
|
||||
/// - elements: The elements.
|
||||
/// - selection: The identifier of the selected element. Selection disabled if `nil`.
|
||||
/// - content: The view for an element.
|
||||
public init(
|
||||
_ elements: [Element],
|
||||
selection: Binding<Element.ID>? = nil,
|
||||
@ViewBuilder content: @escaping (Element) -> Body
|
||||
) {
|
||||
self.init(elements, id: \.id, selection: selection, content: content)
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,7 +9,7 @@ import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// A dynamic list but without a list design in the user interface.
|
||||
public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
public struct ForEach<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
|
||||
|
||||
/// The dynamic widget elements.
|
||||
var elements: [Element]
|
||||
@ -17,12 +17,22 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
var content: (Element) -> Body
|
||||
/// Whether the list is horizontal.
|
||||
var horizontal: Bool
|
||||
/// Whether the children should all be the same size.
|
||||
var homogeneous: Bool?
|
||||
/// The path to the identifier.
|
||||
var id: KeyPath<Element, Identifier>
|
||||
|
||||
/// Initialize `ForEach`.
|
||||
public init(_ elements: [Element], horizontal: Bool = false, @ViewBuilder content: @escaping (Element) -> Body) {
|
||||
public init(
|
||||
_ elements: [Element],
|
||||
id: KeyPath<Element, Identifier>,
|
||||
horizontal: Bool = false,
|
||||
@ViewBuilder content: @escaping (Element) -> Body
|
||||
) {
|
||||
self.elements = elements
|
||||
self.content = content
|
||||
self.horizontal = horizontal
|
||||
self.id = id
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -34,11 +44,9 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
data: WidgetData,
|
||||
type: Data.Type
|
||||
) -> ViewStorage where Data: ViewRenderData {
|
||||
let storage = ViewStorage(
|
||||
.init(
|
||||
gtk_box_new(horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, 0)?.opaque()
|
||||
)
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
return storage
|
||||
}
|
||||
|
||||
/// Update the stored content.
|
||||
@ -56,20 +64,12 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
|
||||
let old = storage.fields["element"] as? [Element] ?? []
|
||||
let widget: UnsafeMutablePointer<GtkBox>? = storage.opaquePointer?.cast()
|
||||
old.identifiableTransform(
|
||||
old.transform(
|
||||
to: elements,
|
||||
functions: .init { index, element in
|
||||
let child = content(element).storage(data: data, type: type)
|
||||
gtk_box_remove(widget, contentStorage[safe: index]?.opaquePointer?.cast())
|
||||
gtk_box_insert_child_after(
|
||||
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())
|
||||
id: id,
|
||||
functions: .init { index in
|
||||
let child = contentStorage[safe: index]?.opaquePointer
|
||||
gtk_box_remove(widget, child?.cast())
|
||||
contentStorage.remove(at: index)
|
||||
} insert: { index, element in
|
||||
let child = content(element).storage(data: data, type: type)
|
||||
@ -82,10 +82,16 @@ public struct ForEach<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
}
|
||||
)
|
||||
if updateProperties {
|
||||
gtk_orientable_set_orientation(
|
||||
widget?.opaque(),
|
||||
horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL
|
||||
)
|
||||
if (storage.previousState as? Self)?.horizontal != horizontal {
|
||||
gtk_orientable_set_orientation(
|
||||
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.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
|
||||
}
|
||||
|
||||
}
|
||||
@ -14,4 +14,11 @@ extension ActionRow {
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
64
Sources/Adwaita/View/Forms/ComboRow+.swift
Normal file
64
Sources/Adwaita/View/Forms/ComboRow+.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,11 +15,8 @@ public struct Form: SimpleView {
|
||||
|
||||
/// The view's body.
|
||||
public var view: Body {
|
||||
ModifierWrapper(
|
||||
content: List([Int](content.indices), selection: nil) { index in content[index] },
|
||||
style: "boxed-list",
|
||||
styleActive: true
|
||||
)
|
||||
List([Int](content.indices), selection: nil) { index in content[index] }
|
||||
.style("boxed-list")
|
||||
}
|
||||
|
||||
/// Initialize a `Form`.
|
||||
@ -2,15 +2,15 @@
|
||||
// ActionRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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
|
||||
/// 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
|
||||
/// 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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// The widget to activate when the row is activated.
|
||||
///
|
||||
/// The row can be activated either by clicking on it, calling
|
||||
/// [method@ActionRow.activate], or via mnemonics in the title.
|
||||
/// See the [property@PreferencesRow:use-underline] property to enable
|
||||
/// `ActionRow.activate`, or via mnemonics in the title.
|
||||
/// See the ``useUnderline(_:)`` property to enable
|
||||
/// mnemonics.
|
||||
///
|
||||
/// The target widget will be activated by emitting the
|
||||
/// [signal@Gtk.Widget::mnemonic-activate] signal on it.
|
||||
var activatableWidget: (() -> Body)?
|
||||
/// `Gtk.Widget::mnemonic-activate` signal on it.
|
||||
var activatableWidget: Body?
|
||||
/// The subtitle for this row.
|
||||
///
|
||||
/// The subtitle is interpreted as Pango markup unless
|
||||
/// [property@PreferencesRow:use-markup] is set to `FALSE`.
|
||||
/// ``useMarkup(_:)`` is set to `false`.
|
||||
var subtitle: String?
|
||||
/// The number of lines at the end of which the subtitle label will be
|
||||
/// ellipsized.
|
||||
@ -73,12 +58,12 @@ public struct ActionRow: AdwaitaWidget {
|
||||
var subtitleLines: Int?
|
||||
/// Whether the user can copy the subtitle from the label.
|
||||
///
|
||||
/// See also [property@Gtk.Label:selectable].
|
||||
/// See also ``selectable(_:)``.
|
||||
var subtitleSelectable: Bool?
|
||||
/// The title of the preference represented by this row.
|
||||
///
|
||||
/// The title is interpreted as Pango markup unless
|
||||
/// [property@PreferencesRow:use-markup] is set to `FALSE`.
|
||||
/// ``useMarkup(_:)`` is set to `false`.
|
||||
var title: String?
|
||||
/// 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?
|
||||
/// Whether the user can copy the title from the label.
|
||||
///
|
||||
/// See also [property@Gtk.Label:selectable].
|
||||
/// See also ``selectable(_:)``.
|
||||
var titleSelectable: Bool?
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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?
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
var useUnderline: Bool?
|
||||
@ -117,8 +102,7 @@ public struct ActionRow: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let activatableWidgetStorage = activatableWidget?().storage(data: data, type: type) {
|
||||
if let activatableWidgetStorage = activatableWidget?.storage(data: data, type: type) {
|
||||
storage.content["activatableWidget"] = [activatableWidgetStorage]
|
||||
adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast())
|
||||
}
|
||||
@ -153,7 +137,7 @@ public struct ActionRow: AdwaitaWidget {
|
||||
storage.modify { widget in
|
||||
|
||||
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 {
|
||||
adw_action_row_set_subtitle_lines(widget?.cast(), subtitleLines.cInt)
|
||||
@ -205,6 +189,7 @@ public struct ActionRow: AdwaitaWidget {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -217,28 +202,22 @@ public struct ActionRow: AdwaitaWidget {
|
||||
/// The widget to activate when the row is activated.
|
||||
///
|
||||
/// The row can be activated either by clicking on it, calling
|
||||
/// [method@ActionRow.activate], or via mnemonics in the title.
|
||||
/// See the [property@PreferencesRow:use-underline] property to enable
|
||||
/// `ActionRow.activate`, or via mnemonics in the title.
|
||||
/// See the ``useUnderline(_:)`` property to enable
|
||||
/// mnemonics.
|
||||
///
|
||||
/// The target widget will be activated by emitting the
|
||||
/// [signal@Gtk.Widget::mnemonic-activate] signal on it.
|
||||
public func activatableWidget(@ViewBuilder _ activatableWidget: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activatableWidget = activatableWidget
|
||||
|
||||
return newSelf
|
||||
/// `Gtk.Widget::mnemonic-activate` signal on it.
|
||||
public func activatableWidget(@ViewBuilder _ activatableWidget: () -> Body) -> Self {
|
||||
modify { $0.activatableWidget = activatableWidget() }
|
||||
}
|
||||
|
||||
/// The subtitle for this row.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.subtitle = subtitle
|
||||
|
||||
return newSelf
|
||||
modify { $0.subtitle = subtitle }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
public func subtitleLines(_ subtitleLines: Int?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.subtitleLines = subtitleLines
|
||||
|
||||
return newSelf
|
||||
modify { $0.subtitleLines = subtitleLines }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.subtitleSelectable = subtitleSelectable
|
||||
|
||||
return newSelf
|
||||
modify { $0.subtitleSelectable = subtitleSelectable }
|
||||
}
|
||||
|
||||
/// The title of the preference represented by this row.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.title = title
|
||||
|
||||
return newSelf
|
||||
modify { $0.title = title }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
public func titleLines(_ titleLines: Int?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.titleLines = titleLines
|
||||
|
||||
return newSelf
|
||||
modify { $0.titleLines = titleLines }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.titleSelectable = titleSelectable
|
||||
|
||||
return newSelf
|
||||
modify { $0.titleSelectable = titleSelectable }
|
||||
}
|
||||
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.useMarkup = useMarkup
|
||||
|
||||
return newSelf
|
||||
modify { $0.useMarkup = useMarkup }
|
||||
}
|
||||
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// This signal is emitted after the row has been activated.
|
||||
@ -2,45 +2,44 @@
|
||||
// AspectFrame.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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,
|
||||
/// 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 {
|
||||
|
||||
#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 child widget.
|
||||
var child: (() -> Body)?
|
||||
var child: Body?
|
||||
/// Whether the `GtkAspectFrame` should use the aspect ratio of its child.
|
||||
var obeyChild: Bool?
|
||||
/// The aspect ratio to be used by the `GtkAspectFrame`.
|
||||
///
|
||||
/// This property is only used if
|
||||
/// [property@Gtk.AspectFrame:obey-child] is set to %FALSE.
|
||||
/// ``obeyChild(_:)`` is set to `false`.
|
||||
var ratio: Float
|
||||
/// The horizontal alignment of the child.
|
||||
var xalign: Float?
|
||||
@ -62,8 +61,7 @@ public struct AspectFrame: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let childStorage = child?().storage(data: data, type: type) {
|
||||
if let childStorage = child?.storage(data: data, type: type) {
|
||||
storage.content["child"] = [childStorage]
|
||||
gtk_aspect_frame_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())
|
||||
}
|
||||
@ -81,7 +79,7 @@ public struct AspectFrame: AdwaitaWidget {
|
||||
storage.modify { widget in
|
||||
|
||||
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 {
|
||||
gtk_aspect_frame_set_obey_child(widget, obeyChild.cBool)
|
||||
@ -97,6 +95,7 @@ public struct AspectFrame: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -110,53 +109,35 @@ public struct AspectFrame: AdwaitaWidget {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// The child widget.
|
||||
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.child = child
|
||||
|
||||
return newSelf
|
||||
public func child(@ViewBuilder _ child: () -> Body) -> Self {
|
||||
modify { $0.child = child() }
|
||||
}
|
||||
|
||||
/// Whether the `GtkAspectFrame` should use the aspect ratio of its child.
|
||||
public func obeyChild(_ obeyChild: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.obeyChild = obeyChild
|
||||
|
||||
return newSelf
|
||||
modify { $0.obeyChild = obeyChild }
|
||||
}
|
||||
|
||||
/// The aspect ratio to be used by the `GtkAspectFrame`.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.ratio = ratio
|
||||
|
||||
return newSelf
|
||||
modify { $0.ratio = ratio }
|
||||
}
|
||||
|
||||
/// The horizontal alignment of the child.
|
||||
public func xalign(_ xalign: Float?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.xalign = xalign
|
||||
|
||||
return newSelf
|
||||
modify { $0.xalign = xalign }
|
||||
}
|
||||
|
||||
/// The vertical alignment of the child.
|
||||
public func yalign(_ yalign: Float?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.yalign = yalign
|
||||
|
||||
return newSelf
|
||||
modify { $0.yalign = yalign }
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// Avatar.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,30 +10,35 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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` 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`,
|
||||
/// [property@Avatar:icon-name] or `avatar-default-symbolic` is shown instead of
|
||||
/// If ``showInitials(_:)`` is set to `false`,
|
||||
/// ``iconName(_:)`` or `avatar-default-symbolic` is shown instead of
|
||||
/// 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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// The name of an icon to use as a fallback.
|
||||
///
|
||||
@ -41,14 +46,14 @@ public struct Avatar: AdwaitaWidget {
|
||||
var iconName: String?
|
||||
/// 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
|
||||
/// The size of the avatar.
|
||||
var size: Int
|
||||
/// 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
|
||||
/// `FALSE`.
|
||||
/// It's only used to generate the color if ``showInitials(_:)`` is
|
||||
/// `false`.
|
||||
var text: String?
|
||||
|
||||
/// Initialize `Avatar`.
|
||||
@ -67,7 +72,6 @@ public struct Avatar: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -95,6 +99,7 @@ public struct Avatar: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -108,39 +113,27 @@ public struct Avatar: AdwaitaWidget {
|
||||
///
|
||||
/// If no name is set, `avatar-default-symbolic` will be used.
|
||||
public func iconName(_ iconName: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.iconName = iconName
|
||||
|
||||
return newSelf
|
||||
modify { $0.iconName = iconName }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.showInitials = showInitials
|
||||
|
||||
return newSelf
|
||||
modify { $0.showInitials = showInitials }
|
||||
}
|
||||
|
||||
/// The size of the avatar.
|
||||
public func size(_ size: Int) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.size = size
|
||||
|
||||
return newSelf
|
||||
modify { $0.size = size }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// `FALSE`.
|
||||
/// It's only used to generate the color if ``showInitials(_:)`` is
|
||||
/// `false`.
|
||||
public func text(_ text: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.text = text
|
||||
|
||||
return newSelf
|
||||
modify { $0.text = text }
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// Banner.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,46 +10,54 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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
|
||||
/// up with Pango markup, use [property@Banner:use-markup] to enable it.
|
||||
/// Banners are hidden by default, use ``revealed(_:)`` to show them.
|
||||
///
|
||||
/// 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
|
||||
/// space.
|
||||
///
|
||||
/// Banners can optionally have a button with text on it, set through
|
||||
/// [property@Banner:button-label]. The button can be used with a `GAction`,
|
||||
/// or with the [signal@Banner::button-clicked] signal.
|
||||
/// ``buttonLabel(_:)``. The button can be used with a `GAction`,
|
||||
/// 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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// The label to show on the button.
|
||||
///
|
||||
/// If set to `""` or `NULL`, the button won't be shown.
|
||||
///
|
||||
/// The button can be used with a `GAction`, or with the
|
||||
/// [signal@Banner::button-clicked] signal.
|
||||
/// `Banner::button-clicked` signal.
|
||||
var buttonLabel: String?
|
||||
/// Whether the banner is currently revealed.
|
||||
var revealed: Bool?
|
||||
/// The title for this banner.
|
||||
///
|
||||
/// See also: [property@Banner:use-markup].
|
||||
/// See also: ``useMarkup(_:)``.
|
||||
var title: String
|
||||
/// Whether to use Pango markup for the banner title.
|
||||
///
|
||||
/// See also [func@Pango.parse_markup].
|
||||
/// See also `Pango.parse_markup`.
|
||||
var useMarkup: Bool?
|
||||
/// This signal is emitted after the action button has been clicked.
|
||||
///
|
||||
@ -71,7 +79,6 @@ public struct Banner: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -104,6 +111,7 @@ public struct Banner: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -118,40 +126,28 @@ public struct Banner: AdwaitaWidget {
|
||||
/// If set to `""` or `NULL`, the button won't be shown.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.buttonLabel = buttonLabel
|
||||
|
||||
return newSelf
|
||||
modify { $0.buttonLabel = buttonLabel }
|
||||
}
|
||||
|
||||
/// Whether the banner is currently revealed.
|
||||
public func revealed(_ revealed: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.revealed = revealed
|
||||
|
||||
return newSelf
|
||||
modify { $0.revealed = revealed }
|
||||
}
|
||||
|
||||
/// The title for this banner.
|
||||
///
|
||||
/// See also: [property@Banner:use-markup].
|
||||
/// See also: ``useMarkup(_:)``.
|
||||
public func title(_ title: String) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.title = title
|
||||
|
||||
return newSelf
|
||||
modify { $0.title = 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 {
|
||||
var newSelf = self
|
||||
newSelf.useMarkup = useMarkup
|
||||
|
||||
return newSelf
|
||||
modify { $0.useMarkup = useMarkup }
|
||||
}
|
||||
|
||||
/// This signal is emitted after the action button has been clicked.
|
||||
@ -2,7 +2,7 @@
|
||||
// Bin.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,22 +10,29 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// It is useful for deriving subclasses, since it provides common code needed
|
||||
/// for handling a single child widget.
|
||||
public struct Bin: AdwaitaWidget {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// The child widget of the `AdwBin`.
|
||||
var child: (() -> Body)?
|
||||
var child: Body?
|
||||
|
||||
/// Initialize `Bin`.
|
||||
public init() {
|
||||
@ -41,8 +48,7 @@ public struct Bin: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let childStorage = child?().storage(data: data, type: type) {
|
||||
if let childStorage = child?.storage(data: data, type: type) {
|
||||
storage.content["child"] = [childStorage]
|
||||
adw_bin_set_child(storage.opaquePointer?.cast(), childStorage.opaquePointer?.cast())
|
||||
}
|
||||
@ -60,10 +66,11 @@ public struct Bin: AdwaitaWidget {
|
||||
storage.modify { widget in
|
||||
|
||||
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 {
|
||||
function(storage, data, updateProperties)
|
||||
@ -74,11 +81,8 @@ public struct Bin: AdwaitaWidget {
|
||||
}
|
||||
|
||||
/// The child widget of the `AdwBin`.
|
||||
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.child = child
|
||||
|
||||
return newSelf
|
||||
public func child(@ViewBuilder _ child: () -> Body) -> Self {
|
||||
modify { $0.child = child() }
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,58 +2,59 @@
|
||||
// Box.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// The `GtkBox` widget arranges child widgets into a single row or column.
|
||||
/// Arranges child widgets into a single row or column.
|
||||
///
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// Whether it is a row or column depends on the value of its
|
||||
/// [property@Gtk.Orientable:orientation] property. Within the other
|
||||
/// dimension, all children are allocated the same size. Of course, the
|
||||
/// [property@Gtk.Widget:halign] and [property@Gtk.Widget:valign] properties
|
||||
/// can be used on the children to influence their allocation.
|
||||
/// ``orientation(_:)`` property. Within the other
|
||||
/// dimension, all children are allocated the same size. The
|
||||
/// ``halign(_:)`` and ``valign(_:)``
|
||||
/// properties can be used on the children to influence their allocation.
|
||||
///
|
||||
/// Use repeated calls to [method@Gtk.Box.append] to pack widgets into a
|
||||
/// `GtkBox` from start to end. Use [method@Gtk.Box.remove] to remove widgets
|
||||
/// from the `GtkBox`. [method@Gtk.Box.insert_child_after] can be used to add
|
||||
/// Use repeated calls to `Gtk.Box.append` to pack widgets into a
|
||||
/// `GtkBox` from start to end. Use `Gtk.Box.remove` to remove widgets
|
||||
/// from the `GtkBox`. `Gtk.Box.insert_child_after` can be used to add
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// *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.
|
||||
///
|
||||
/// # 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 {
|
||||
|
||||
#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 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?
|
||||
/// Whether the children should all be the same size.
|
||||
var homogeneous: Bool?
|
||||
@ -65,7 +66,7 @@ public struct Box: AdwaitaWidget {
|
||||
var prepend: () -> Body = { [] }
|
||||
|
||||
/// Initialize `Box`.
|
||||
public init(spacing: Int) {
|
||||
init(spacing: Int) {
|
||||
self.spacing = spacing
|
||||
}
|
||||
|
||||
@ -79,7 +80,6 @@ public struct Box: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
var appendStorage: [ViewStorage] = []
|
||||
for view in append() {
|
||||
@ -140,6 +140,7 @@ public struct Box: AdwaitaWidget {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -153,34 +154,24 @@ public struct Box: AdwaitaWidget {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.baselineChild = baselineChild
|
||||
|
||||
return newSelf
|
||||
modify { $0.baselineChild = baselineChild }
|
||||
}
|
||||
|
||||
/// Whether the children should all be the same size.
|
||||
public func homogeneous(_ homogeneous: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.homogeneous = homogeneous
|
||||
|
||||
return newSelf
|
||||
modify { $0.homogeneous = homogeneous }
|
||||
}
|
||||
|
||||
/// The amount of space between children.
|
||||
public func spacing(_ spacing: Int) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.spacing = spacing
|
||||
|
||||
return newSelf
|
||||
modify { $0.spacing = spacing }
|
||||
}
|
||||
|
||||
/// Set the body for "append".
|
||||
@ -2,54 +2,40 @@
|
||||
// Button.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// The `GtkButton` widget is generally used to trigger a callback function that is
|
||||
/// called when the button is pressed.
|
||||
/// Calls a callback function when the button is clicked.
|
||||
///
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 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
|
||||
/// `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 {
|
||||
|
||||
#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?
|
||||
/// action-name
|
||||
/// The name of the action with which this widget should be associated.
|
||||
var actionName: String?
|
||||
/// Whether the size of the button can be made smaller than the natural
|
||||
/// size of its contents.
|
||||
@ -60,7 +46,7 @@ public struct Button: AdwaitaWidget {
|
||||
/// property has no effect.
|
||||
var canShrink: Bool?
|
||||
/// The child widget.
|
||||
var child: (() -> Body)?
|
||||
var child: Body?
|
||||
/// Whether the button has a frame.
|
||||
var hasFrame: Bool?
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// <kbd>␣</kbd> and <kbd>Enter</kbd> keys.
|
||||
@ -82,7 +68,7 @@ public struct Button: AdwaitaWidget {
|
||||
var clicked: (() -> Void)?
|
||||
|
||||
/// Initialize `Button`.
|
||||
public init() {
|
||||
init() {
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -95,8 +81,7 @@ public struct Button: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let childStorage = child?().storage(data: data, type: type) {
|
||||
if let childStorage = child?.storage(data: data, type: type) {
|
||||
storage.content["child"] = [childStorage]
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
gtk_button_set_has_frame(widget?.cast(), hasFrame.cBool)
|
||||
@ -146,6 +131,7 @@ public struct Button: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -159,18 +145,12 @@ public struct Button: AdwaitaWidget {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// action-name
|
||||
/// The name of the action with which this widget should be associated.
|
||||
public func actionName(_ actionName: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.actionName = actionName
|
||||
|
||||
return newSelf
|
||||
modify { $0.actionName = actionName }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// property has no effect.
|
||||
public func canShrink(_ canShrink: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.canShrink = canShrink
|
||||
|
||||
return newSelf
|
||||
modify { $0.canShrink = canShrink }
|
||||
}
|
||||
|
||||
/// The child widget.
|
||||
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.child = child
|
||||
|
||||
return newSelf
|
||||
public func child(@ViewBuilder _ child: () -> Body) -> Self {
|
||||
modify { $0.child = child() }
|
||||
}
|
||||
|
||||
/// Whether the button has a frame.
|
||||
public func hasFrame(_ hasFrame: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.hasFrame = hasFrame
|
||||
|
||||
return newSelf
|
||||
modify { $0.hasFrame = hasFrame }
|
||||
}
|
||||
|
||||
/// The name of the icon used to automatically populate the button.
|
||||
public func iconName(_ iconName: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.iconName = iconName
|
||||
|
||||
return newSelf
|
||||
modify { $0.iconName = iconName }
|
||||
}
|
||||
|
||||
/// Text of the label inside the button, if the button contains a label widget.
|
||||
public func label(_ label: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.label = label
|
||||
|
||||
return newSelf
|
||||
modify { $0.label = label }
|
||||
}
|
||||
|
||||
/// If set, an underline in the text indicates that the following character is
|
||||
/// to be used as mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// Emitted to animate press then release.
|
||||
///
|
||||
/// 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
|
||||
/// <kbd>␣</kbd> and <kbd>Enter</kbd> keys.
|
||||
@ -2,7 +2,7 @@
|
||||
// ButtonContent.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,12 +10,12 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// It's intended to be used as a direct child of [class@Gtk.Button],
|
||||
/// [class@Gtk.MenuButton] or [class@SplitButton], when they need to have both an
|
||||
/// It's intended to be used as a direct child of `Gtk.Button`,
|
||||
/// `Gtk.MenuButton` or `SplitButton`, when they need to have both an
|
||||
/// icon and a label, as follows:
|
||||
///
|
||||
/// ```xml
|
||||
@ -25,37 +25,26 @@ import LevenshteinTransformations
|
||||
/// `AdwButtonContent` handles style classes and connecting the mnemonic to the
|
||||
/// 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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// Whether the button can be smaller than the natural size of its contents.
|
||||
///
|
||||
/// 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?
|
||||
/// The name of the displayed icon.
|
||||
///
|
||||
@ -67,7 +56,7 @@ public struct ButtonContent: AdwaitaWidget {
|
||||
///
|
||||
/// The mnemonic can be used to activate the parent button.
|
||||
///
|
||||
/// See [property@ButtonContent:label].
|
||||
/// See ``label(_:)``.
|
||||
var useUnderline: Bool?
|
||||
|
||||
/// Initialize `ButtonContent`.
|
||||
@ -84,7 +73,6 @@ public struct ButtonContent: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -112,6 +100,7 @@ public struct ButtonContent: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
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.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.canShrink = canShrink
|
||||
|
||||
return newSelf
|
||||
modify { $0.canShrink = canShrink }
|
||||
}
|
||||
|
||||
/// The name of the displayed icon.
|
||||
///
|
||||
/// If empty, the icon is not shown.
|
||||
public func iconName(_ iconName: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.iconName = iconName
|
||||
|
||||
return newSelf
|
||||
modify { $0.iconName = iconName }
|
||||
}
|
||||
|
||||
/// The displayed label.
|
||||
public func label(_ label: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.label = label
|
||||
|
||||
return newSelf
|
||||
modify { $0.label = label }
|
||||
}
|
||||
|
||||
/// Whether an underline in the text indicates a mnemonic.
|
||||
///
|
||||
/// The mnemonic can be used to activate the parent button.
|
||||
///
|
||||
/// See [property@ButtonContent:label].
|
||||
/// See ``label(_:)``.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// Carousel.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,35 +10,40 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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
|
||||
/// 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`.
|
||||
///
|
||||
/// ## CSS nodes
|
||||
///
|
||||
/// `AdwCarousel` has a single CSS node with name `carousel`.
|
||||
public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
public struct Carousel<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// Whether to allow swiping for more than one page at a time.
|
||||
///
|
||||
/// 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?
|
||||
/// 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?
|
||||
/// 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?
|
||||
/// 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
|
||||
/// after every scroll.
|
||||
///
|
||||
/// ::: note
|
||||
/// An empty carousel is indicated by `(int)index == -1`.
|
||||
/// > [!NOTE]
|
||||
/// > An empty carousel is indicated by `(int)index == -1`.
|
||||
var pageChanged: (() -> Void)?
|
||||
/// The dynamic widget elements.
|
||||
var elements: [Element]
|
||||
/// The dynamic widget content.
|
||||
var content: (Element) -> Body
|
||||
/// The dynamic widget identifier key path.
|
||||
var id: KeyPath<Element, Identifier>
|
||||
|
||||
/// Initialize `Carousel`.
|
||||
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
|
||||
public init(_ elements: [Element], id: KeyPath<Element, Identifier>, @ViewBuilder content: @escaping (Element) -> Body) {
|
||||
self.elements = elements
|
||||
self.content = content
|
||||
self.id = id
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -82,7 +90,6 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -122,15 +129,10 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
|
||||
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
|
||||
let old = storage.fields["element"] as? [Element] ?? []
|
||||
old.identifiableTransform(
|
||||
old.transform(
|
||||
to: elements,
|
||||
functions: .init { index, element in
|
||||
let child = content(element).storage(data: data, type: type)
|
||||
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
|
||||
id: id,
|
||||
functions: .init { index in
|
||||
adw_carousel_remove(widget, adw_carousel_get_nth_page(widget, UInt(index).cInt))
|
||||
contentStorage.remove(at: index)
|
||||
} insert: { index, element in
|
||||
@ -144,6 +146,7 @@ public struct Carousel<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
for (index, element) in elements.enumerated() {
|
||||
content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type)
|
||||
}
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
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.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.allowLongSwipes = allowLongSwipes
|
||||
|
||||
return newSelf
|
||||
modify { $0.allowLongSwipes = allowLongSwipes }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.allowMouseDrag = allowMouseDrag
|
||||
|
||||
return newSelf
|
||||
modify { $0.allowMouseDrag = allowMouseDrag }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.allowScrollWheel = allowScrollWheel
|
||||
|
||||
return newSelf
|
||||
modify { $0.allowScrollWheel = allowScrollWheel }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// navigating it in a certain state.
|
||||
public func interactive(_ interactive: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.interactive = interactive
|
||||
|
||||
return newSelf
|
||||
modify { $0.interactive = interactive }
|
||||
}
|
||||
|
||||
/// The number of pages in a `AdwCarousel`.
|
||||
public func nPages(_ nPages: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.nPages = nPages
|
||||
|
||||
return newSelf
|
||||
modify { $0.nPages = nPages }
|
||||
}
|
||||
|
||||
/// Page reveal duration, in milliseconds.
|
||||
///
|
||||
/// Reveal duration is used when animating adding or removing pages.
|
||||
public func revealDuration(_ revealDuration: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.revealDuration = revealDuration
|
||||
|
||||
return newSelf
|
||||
modify { $0.revealDuration = revealDuration }
|
||||
}
|
||||
|
||||
/// Spacing between pages in pixels.
|
||||
public func spacing(_ spacing: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.spacing = spacing
|
||||
|
||||
return newSelf
|
||||
modify { $0.spacing = spacing }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// after every scroll.
|
||||
///
|
||||
/// ::: note
|
||||
/// An empty carousel is indicated by `(int)index == -1`.
|
||||
/// > [!NOTE]
|
||||
/// > An empty carousel is indicated by `(int)index == -1`.
|
||||
public func pageChanged(_ pageChanged: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,80 +2,66 @@
|
||||
// CenterBox.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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.
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// To add children to `GtkCenterBox`, use [method@Gtk.CenterBox.set_start_widget],
|
||||
/// [method@Gtk.CenterBox.set_center_widget] and
|
||||
/// [method@Gtk.CenterBox.set_end_widget].
|
||||
///
|
||||
/// To add children to `GtkCenterBox`, use `Gtk.CenterBox.set_start_widget`,
|
||||
/// `Gtk.CenterBox.set_center_widget` and
|
||||
/// `Gtk.CenterBox.set_end_widget`.
|
||||
///
|
||||
/// The sizing and positioning of children can be influenced with the
|
||||
/// 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 {
|
||||
|
||||
#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 widget that is placed at the center position.
|
||||
var centerWidget: (() -> Body)?
|
||||
var centerWidget: Body?
|
||||
/// The widget that is placed at the end position.
|
||||
///
|
||||
/// In vertical orientation, the end position is at the bottom.
|
||||
/// In horizontal orientation, the end position is at the trailing
|
||||
/// edge wrt. to the text direction.
|
||||
var endWidget: (() -> Body)?
|
||||
/// edge with respect to the text direction.
|
||||
var endWidget: Body?
|
||||
/// Whether to shrink the center widget after other children.
|
||||
///
|
||||
/// By default, when there's no space to give all three children their
|
||||
/// natural widths, the start and end widgets start shrinking and the
|
||||
/// 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.
|
||||
var shrinkCenterLast: Bool?
|
||||
/// The widget that is placed at the start position.
|
||||
///
|
||||
/// In vertical orientation, the start position is at the top.
|
||||
/// In horizontal orientation, the start position is at the leading
|
||||
/// edge wrt. to the text direction.
|
||||
var startWidget: (() -> Body)?
|
||||
/// edge with respect to the text direction.
|
||||
var startWidget: Body?
|
||||
|
||||
/// Initialize `CenterBox`.
|
||||
public init() {
|
||||
@ -91,16 +77,15 @@ public struct CenterBox: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let centerWidgetStorage = centerWidget?().storage(data: data, type: type) {
|
||||
if let centerWidgetStorage = centerWidget?.storage(data: data, type: type) {
|
||||
storage.content["centerWidget"] = [centerWidgetStorage]
|
||||
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]
|
||||
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]
|
||||
gtk_center_box_set_start_widget(storage.opaquePointer, startWidgetStorage.opaquePointer?.cast())
|
||||
}
|
||||
@ -118,19 +103,20 @@ public struct CenterBox: AdwaitaWidget {
|
||||
storage.modify { widget in
|
||||
|
||||
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 {
|
||||
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 {
|
||||
gtk_center_box_set_shrink_center_last(widget, shrinkCenterLast.cBool)
|
||||
}
|
||||
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 {
|
||||
function(storage, data, updateProperties)
|
||||
@ -144,30 +130,21 @@ public struct CenterBox: AdwaitaWidget {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// The widget that is placed at the center position.
|
||||
public func centerWidget(@ViewBuilder _ centerWidget: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.centerWidget = centerWidget
|
||||
|
||||
return newSelf
|
||||
public func centerWidget(@ViewBuilder _ centerWidget: () -> Body) -> Self {
|
||||
modify { $0.centerWidget = centerWidget() }
|
||||
}
|
||||
|
||||
/// The widget that is placed at the end position.
|
||||
///
|
||||
/// In vertical orientation, the end position is at the bottom.
|
||||
/// In horizontal orientation, the end position is at the trailing
|
||||
/// edge wrt. to the text direction.
|
||||
public func endWidget(@ViewBuilder _ endWidget: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.endWidget = endWidget
|
||||
|
||||
return newSelf
|
||||
/// edge with respect to the text direction.
|
||||
public func endWidget(@ViewBuilder _ endWidget: () -> Body) -> Self {
|
||||
modify { $0.endWidget = endWidget() }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// 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.
|
||||
public func shrinkCenterLast(_ shrinkCenterLast: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.shrinkCenterLast = shrinkCenterLast
|
||||
|
||||
return newSelf
|
||||
modify { $0.shrinkCenterLast = shrinkCenterLast }
|
||||
}
|
||||
|
||||
/// The widget that is placed at the start position.
|
||||
///
|
||||
/// In vertical orientation, the start position is at the top.
|
||||
/// In horizontal orientation, the start position is at the leading
|
||||
/// edge wrt. to the text direction.
|
||||
public func startWidget(@ViewBuilder _ startWidget: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.startWidget = startWidget
|
||||
|
||||
return newSelf
|
||||
/// edge with respect to the text direction.
|
||||
public func startWidget(@ViewBuilder _ startWidget: () -> Body) -> Self {
|
||||
modify { $0.startWidget = startWidget() }
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,89 +2,51 @@
|
||||
// CheckButton.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// A `GtkCheckButton` places a label next to an indicator.
|
||||
/// Places a label next to an indicator.
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 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
|
||||
/// [method@Gtk.CheckButton.set_active], and retrieved using
|
||||
/// [method@Gtk.CheckButton.get_active].
|
||||
/// `Gtk.CheckButton.set_active`, and retrieved using
|
||||
/// `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*.
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 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 {
|
||||
|
||||
#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?
|
||||
/// action-name
|
||||
/// The name of the action with which this widget should be associated.
|
||||
var actionName: String?
|
||||
/// 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.
|
||||
var active: Binding<Bool>?
|
||||
/// The child widget.
|
||||
var child: (() -> Body)?
|
||||
var child: Body?
|
||||
/// If the check button is in an “in between” state.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// <kbd>␣</kbd> and <kbd>Enter</kbd> keys.
|
||||
var activate: (() -> Void)?
|
||||
/// Emitted when the buttons's [property@Gtk.CheckButton:active]
|
||||
/// Emitted when the buttons's ``active(_:)``
|
||||
/// property changes.
|
||||
var toggled: (() -> Void)?
|
||||
|
||||
@ -124,8 +86,7 @@ public struct CheckButton: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let childStorage = child?().storage(data: data, type: type) {
|
||||
if let childStorage = child?.storage(data: data, type: type) {
|
||||
storage.content["child"] = [childStorage]
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
gtk_check_button_set_inconsistent(widget?.cast(), inconsistent.cBool)
|
||||
@ -178,6 +139,7 @@ if let active, newValue != active.wrappedValue {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -191,37 +153,25 @@ if let active, newValue != active.wrappedValue {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// action-name
|
||||
/// The name of the action with which this widget should be associated.
|
||||
public func actionName(_ actionName: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.actionName = actionName
|
||||
|
||||
return newSelf
|
||||
modify { $0.actionName = actionName }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
public func active(_ active: Binding<Bool>?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.active = active
|
||||
|
||||
return newSelf
|
||||
modify { $0.active = active }
|
||||
}
|
||||
|
||||
/// The child widget.
|
||||
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.child = child
|
||||
|
||||
return newSelf
|
||||
public func child(@ViewBuilder _ child: () -> Body) -> Self {
|
||||
modify { $0.child = child() }
|
||||
}
|
||||
|
||||
/// 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,
|
||||
/// not the semantics of the button.
|
||||
public func inconsistent(_ inconsistent: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.inconsistent = inconsistent
|
||||
|
||||
return newSelf
|
||||
modify { $0.inconsistent = inconsistent }
|
||||
}
|
||||
|
||||
/// Text of the label inside the check button, if it contains a label widget.
|
||||
public func label(_ label: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.label = label
|
||||
|
||||
return newSelf
|
||||
modify { $0.label = label }
|
||||
}
|
||||
|
||||
/// If set, an underline in the text indicates that the following
|
||||
/// character is to be used as mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// <kbd>␣</kbd> and <kbd>Enter</kbd> keys.
|
||||
@ -268,7 +209,7 @@ if let active, newValue != active.wrappedValue {
|
||||
return newSelf
|
||||
}
|
||||
|
||||
/// Emitted when the buttons's [property@Gtk.CheckButton:active]
|
||||
/// Emitted when the buttons's ``active(_:)``
|
||||
/// property changes.
|
||||
public func toggled(_ toggled: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
@ -2,7 +2,7 @@
|
||||
// Clamp.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,7 +10,7 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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
|
||||
/// 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.
|
||||
///
|
||||
/// `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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// The child widget of the `AdwClamp`.
|
||||
var child: (() -> Body)?
|
||||
var child: Body?
|
||||
/// The maximum size allocated to the child.
|
||||
///
|
||||
/// 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 {
|
||||
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]
|
||||
adw_clamp_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())
|
||||
}
|
||||
@ -88,7 +94,7 @@ public struct Clamp: AdwaitaWidget {
|
||||
storage.modify { widget in
|
||||
|
||||
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 {
|
||||
adw_clamp_set_maximum_size(widget, maximumSize.cInt)
|
||||
@ -98,6 +104,7 @@ public struct Clamp: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -108,21 +115,15 @@ public struct Clamp: AdwaitaWidget {
|
||||
}
|
||||
|
||||
/// The child widget of the `AdwClamp`.
|
||||
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.child = child
|
||||
|
||||
return newSelf
|
||||
public func child(@ViewBuilder _ child: () -> Body) -> Self {
|
||||
modify { $0.child = child() }
|
||||
}
|
||||
|
||||
/// The maximum size allocated to the child.
|
||||
///
|
||||
/// It is the width if the clamp is horizontal, or the height if it is vertical.
|
||||
public func maximumSize(_ maximumSize: Int?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.maximumSize = maximumSize
|
||||
|
||||
return newSelf
|
||||
modify { $0.maximumSize = maximumSize }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// size makes transitions to and from the maximum size smoother when resizing.
|
||||
public func tighteningThreshold(_ tighteningThreshold: Int?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.tighteningThreshold = tighteningThreshold
|
||||
|
||||
return newSelf
|
||||
modify { $0.tighteningThreshold = tighteningThreshold }
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,15 +2,15 @@
|
||||
// ComboRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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
|
||||
/// 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>
|
||||
/// ```
|
||||
///
|
||||
/// 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
|
||||
/// 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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// The widget to activate when the row is activated.
|
||||
///
|
||||
/// The row can be activated either by clicking on it, calling
|
||||
/// [method@ActionRow.activate], or via mnemonics in the title.
|
||||
/// See the [property@PreferencesRow:use-underline] property to enable
|
||||
/// `ActionRow.activate`, or via mnemonics in the title.
|
||||
/// See the ``useUnderline(_:)`` property to enable
|
||||
/// mnemonics.
|
||||
///
|
||||
/// The target widget will be activated by emitting the
|
||||
/// [signal@Gtk.Widget::mnemonic-activate] signal on it.
|
||||
var activatableWidget: (() -> Body)?
|
||||
/// `Gtk.Widget::mnemonic-activate` signal on it.
|
||||
var activatableWidget: Body?
|
||||
/// 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.
|
||||
///
|
||||
/// Search requires [property@ComboRow:expression] to be set.
|
||||
/// 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
|
||||
/// [const@Gtk.INVALID_LIST_POSITION]
|
||||
/// `Gtk.INVALID_LIST_POSITION`
|
||||
var selected: Binding<UInt>?
|
||||
/// The subtitle for this row.
|
||||
///
|
||||
/// The subtitle is interpreted as Pango markup unless
|
||||
/// [property@PreferencesRow:use-markup] is set to `FALSE`.
|
||||
/// ``useMarkup(_:)`` is set to `false`.
|
||||
var subtitle: String?
|
||||
/// The number of lines at the end of which the subtitle label will be
|
||||
/// ellipsized.
|
||||
@ -82,12 +78,12 @@ public struct ComboRow: AdwaitaWidget {
|
||||
var subtitleLines: Int?
|
||||
/// Whether the user can copy the subtitle from the label.
|
||||
///
|
||||
/// See also [property@Gtk.Label:selectable].
|
||||
/// See also ``selectable(_:)``.
|
||||
var subtitleSelectable: Bool?
|
||||
/// The title of the preference represented by this row.
|
||||
///
|
||||
/// The title is interpreted as Pango markup unless
|
||||
/// [property@PreferencesRow:use-markup] is set to `FALSE`.
|
||||
/// ``useMarkup(_:)`` is set to `false`.
|
||||
var title: String?
|
||||
/// 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?
|
||||
/// Whether the user can copy the title from the label.
|
||||
///
|
||||
/// See also [property@Gtk.Label:selectable].
|
||||
/// See also ``selectable(_:)``.
|
||||
var titleSelectable: Bool?
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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?
|
||||
/// 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
|
||||
/// 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
|
||||
/// [property@PreferencesRow:use-markup] is set to `TRUE`.
|
||||
/// ``useMarkup(_:)`` is set to `true`.
|
||||
var useSubtitle: Bool?
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
var useUnderline: Bool?
|
||||
@ -123,7 +119,7 @@ public struct ComboRow: AdwaitaWidget {
|
||||
var prefix: () -> Body = { [] }
|
||||
|
||||
/// Initialize `ComboRow`.
|
||||
public init() {
|
||||
init() {
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -136,8 +132,7 @@ public struct ComboRow: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let activatableWidgetStorage = activatableWidget?().storage(data: data, type: type) {
|
||||
if let activatableWidgetStorage = activatableWidget?.storage(data: data, type: type) {
|
||||
storage.content["activatableWidget"] = [activatableWidgetStorage]
|
||||
adw_action_row_set_activatable_widget(storage.opaquePointer?.cast(), activatableWidgetStorage.opaquePointer?.cast())
|
||||
}
|
||||
@ -178,7 +173,7 @@ if let selected, newValue != selected.wrappedValue {
|
||||
}
|
||||
}
|
||||
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 {
|
||||
adw_combo_row_set_enable_search(widget?.cast(), enableSearch.cBool)
|
||||
@ -215,6 +210,7 @@ if let selected, newValue != selected.wrappedValue {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -227,52 +223,40 @@ if let selected, newValue != selected.wrappedValue {
|
||||
/// The widget to activate when the row is activated.
|
||||
///
|
||||
/// The row can be activated either by clicking on it, calling
|
||||
/// [method@ActionRow.activate], or via mnemonics in the title.
|
||||
/// See the [property@PreferencesRow:use-underline] property to enable
|
||||
/// `ActionRow.activate`, or via mnemonics in the title.
|
||||
/// See the ``useUnderline(_:)`` property to enable
|
||||
/// mnemonics.
|
||||
///
|
||||
/// The target widget will be activated by emitting the
|
||||
/// [signal@Gtk.Widget::mnemonic-activate] signal on it.
|
||||
public func activatableWidget(@ViewBuilder _ activatableWidget: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activatableWidget = activatableWidget
|
||||
|
||||
return newSelf
|
||||
/// `Gtk.Widget::mnemonic-activate` signal on it.
|
||||
public func activatableWidget(@ViewBuilder _ activatableWidget: () -> Body) -> Self {
|
||||
modify { $0.activatableWidget = activatableWidget() }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// Search requires [property@ComboRow:expression] to be set.
|
||||
/// Search requires ``expression(_:)`` to be set.
|
||||
public func enableSearch(_ enableSearch: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.enableSearch = enableSearch
|
||||
|
||||
return newSelf
|
||||
modify { $0.enableSearch = enableSearch }
|
||||
}
|
||||
|
||||
/// The position of the selected item.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.selected = selected
|
||||
|
||||
return newSelf
|
||||
modify { $0.selected = selected }
|
||||
}
|
||||
|
||||
/// The subtitle for this row.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.subtitle = subtitle
|
||||
|
||||
return newSelf
|
||||
modify { $0.subtitle = subtitle }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
public func subtitleLines(_ subtitleLines: Int?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.subtitleLines = subtitleLines
|
||||
|
||||
return newSelf
|
||||
modify { $0.subtitleLines = subtitleLines }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.subtitleSelectable = subtitleSelectable
|
||||
|
||||
return newSelf
|
||||
modify { $0.subtitleSelectable = subtitleSelectable }
|
||||
}
|
||||
|
||||
/// The title of the preference represented by this row.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.title = title
|
||||
|
||||
return newSelf
|
||||
modify { $0.title = title }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
public func titleLines(_ titleLines: Int?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.titleLines = titleLines
|
||||
|
||||
return newSelf
|
||||
modify { $0.titleLines = titleLines }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.titleSelectable = titleSelectable
|
||||
|
||||
return newSelf
|
||||
modify { $0.titleSelectable = titleSelectable }
|
||||
}
|
||||
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.useMarkup = useMarkup
|
||||
|
||||
return newSelf
|
||||
modify { $0.useMarkup = useMarkup }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// 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
|
||||
/// [property@PreferencesRow:use-markup] is set to `TRUE`.
|
||||
/// ``useMarkup(_:)`` is set to `true`.
|
||||
public func useSubtitle(_ useSubtitle: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useSubtitle = useSubtitle
|
||||
|
||||
return newSelf
|
||||
modify { $0.useSubtitle = useSubtitle }
|
||||
}
|
||||
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// This signal is emitted after the row has been activated.
|
||||
182
Sources/Adwaita/View/Generated/DropDown.swift
Normal file
182
Sources/Adwaita/View/Generated/DropDown.swift
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
779
Sources/Adwaita/View/Generated/Entry.swift
Normal file
779
Sources/Adwaita/View/Generated/Entry.swift
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,49 +2,44 @@
|
||||
// EntryRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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
|
||||
/// indicating that it's editable and can receive additional widgets before or
|
||||
/// 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
|
||||
/// changing its contents can result in an expensive operation, such as network
|
||||
/// activity.
|
||||
///
|
||||
/// `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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// Whether activating the embedded entry can activate the default widget.
|
||||
var activatesDefault: Bool?
|
||||
@ -52,11 +47,13 @@ public struct EntryRow: AdwaitaWidget {
|
||||
///
|
||||
/// Emoji replacement is done with :-delimited names, like `:heart:`.
|
||||
var enableEmojiCompletion: Bool?
|
||||
/// Maximum number of characters for the entry.
|
||||
var maxLength: Int?
|
||||
/// 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
|
||||
/// emit the [signal@EntryRow::apply] signal.
|
||||
/// emit the `EntryRow::apply` signal.
|
||||
///
|
||||
/// This is useful if changing the entry contents can trigger an expensive
|
||||
/// 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 is interpreted as Pango markup unless
|
||||
/// [property@PreferencesRow:use-markup] is set to `FALSE`.
|
||||
/// ``useMarkup(_:)`` is set to `false`.
|
||||
var title: String?
|
||||
/// Whether the user can copy the title from the label.
|
||||
///
|
||||
/// See also [property@Gtk.Label:selectable].
|
||||
/// See also ``selectable(_:)``.
|
||||
var titleSelectable: Bool?
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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?
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
var useUnderline: Bool?
|
||||
/// Emitted when the apply button is pressed.
|
||||
///
|
||||
/// See [property@EntryRow:show-apply-button].
|
||||
/// See ``showApplyButton(_:)``.
|
||||
var apply: (() -> Void)?
|
||||
/// Emitted when the embedded entry is activated.
|
||||
var entryActivated: (() -> Void)?
|
||||
@ -93,7 +90,7 @@ public struct EntryRow: AdwaitaWidget {
|
||||
var prefix: () -> Body = { [] }
|
||||
|
||||
/// Initialize `EntryRow`.
|
||||
public init() {
|
||||
init() {
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -106,7 +103,6 @@ public struct EntryRow: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
var suffixStorage: [ViewStorage] = []
|
||||
for view in suffix() {
|
||||
@ -148,6 +144,9 @@ public struct EntryRow: AdwaitaWidget {
|
||||
if let enableEmojiCompletion, updateProperties, (storage.previousState as? Self)?.enableEmojiCompletion != enableEmojiCompletion {
|
||||
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 {
|
||||
adw_entry_row_set_show_apply_button(widget?.cast(), showApplyButton.cBool)
|
||||
}
|
||||
@ -189,6 +188,7 @@ public struct EntryRow: AdwaitaWidget {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -200,90 +200,71 @@ public struct EntryRow: AdwaitaWidget {
|
||||
|
||||
/// Whether activating the embedded entry can activate the default widget.
|
||||
public func activatesDefault(_ activatesDefault: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activatesDefault = activatesDefault
|
||||
|
||||
return newSelf
|
||||
modify { $0.activatesDefault = activatesDefault }
|
||||
}
|
||||
|
||||
/// Whether to suggest emoji replacements on the entry row.
|
||||
///
|
||||
/// Emoji replacement is done with :-delimited names, like `:heart:`.
|
||||
public func enableEmojiCompletion(_ enableEmojiCompletion: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.enableEmojiCompletion = enableEmojiCompletion
|
||||
|
||||
return newSelf
|
||||
modify { $0.enableEmojiCompletion = enableEmojiCompletion }
|
||||
}
|
||||
|
||||
/// Maximum number of characters for the entry.
|
||||
public func maxLength(_ maxLength: Int?) -> Self {
|
||||
modify { $0.maxLength = maxLength }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// emit the [signal@EntryRow::apply] signal.
|
||||
/// emit the `EntryRow::apply` signal.
|
||||
///
|
||||
/// This is useful if changing the entry contents can trigger an expensive
|
||||
/// operation, e.g. network activity, to avoid triggering it after typing every
|
||||
/// character.
|
||||
public func showApplyButton(_ showApplyButton: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.showApplyButton = showApplyButton
|
||||
|
||||
return newSelf
|
||||
modify { $0.showApplyButton = showApplyButton }
|
||||
}
|
||||
|
||||
/// The length of the text in the entry row.
|
||||
public func textLength(_ textLength: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.textLength = textLength
|
||||
|
||||
return newSelf
|
||||
modify { $0.textLength = textLength }
|
||||
}
|
||||
|
||||
/// The title of the preference represented by this row.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.title = title
|
||||
|
||||
return newSelf
|
||||
modify { $0.title = title }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.titleSelectable = titleSelectable
|
||||
|
||||
return newSelf
|
||||
modify { $0.titleSelectable = titleSelectable }
|
||||
}
|
||||
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.useMarkup = useMarkup
|
||||
|
||||
return newSelf
|
||||
modify { $0.useMarkup = useMarkup }
|
||||
}
|
||||
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// Emitted when the apply button is pressed.
|
||||
///
|
||||
/// See [property@EntryRow:show-apply-button].
|
||||
/// See ``showApplyButton(_:)``.
|
||||
public func apply(_ apply: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.apply = apply
|
||||
@ -2,43 +2,34 @@
|
||||
// ExpanderRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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
|
||||
/// it. It also allows the user to enable the expansion of the row, allowing to
|
||||
/// 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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// Whether expansion is enabled.
|
||||
var enableExpansion: Binding<Bool>?
|
||||
@ -49,7 +40,7 @@ public struct ExpanderRow: AdwaitaWidget {
|
||||
/// The subtitle for this row.
|
||||
///
|
||||
/// The subtitle is interpreted as Pango markup unless
|
||||
/// [property@PreferencesRow:use-markup] is set to `FALSE`.
|
||||
/// ``useMarkup(_:)`` is set to `false`.
|
||||
var subtitle: String?
|
||||
/// The number of lines at the end of which the subtitle label will be
|
||||
/// ellipsized.
|
||||
@ -59,7 +50,7 @@ public struct ExpanderRow: AdwaitaWidget {
|
||||
/// The title of the preference represented by this row.
|
||||
///
|
||||
/// The title is interpreted as Pango markup unless
|
||||
/// [property@PreferencesRow:use-markup] is set to `FALSE`.
|
||||
/// ``useMarkup(_:)`` is set to `false`.
|
||||
var title: String?
|
||||
/// 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?
|
||||
/// Whether the user can copy the title from the label.
|
||||
///
|
||||
/// See also [property@Gtk.Label:selectable].
|
||||
/// See also ``selectable(_:)``.
|
||||
var titleSelectable: Bool?
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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?
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
var useUnderline: Bool?
|
||||
@ -98,7 +89,6 @@ public struct ExpanderRow: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
var rowsStorage: [ViewStorage] = []
|
||||
for view in rows() {
|
||||
@ -210,6 +200,7 @@ if let expanded, newValue != expanded.wrappedValue {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -221,37 +212,25 @@ if let expanded, newValue != expanded.wrappedValue {
|
||||
|
||||
/// Whether expansion is enabled.
|
||||
public func enableExpansion(_ enableExpansion: Binding<Bool>?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.enableExpansion = enableExpansion
|
||||
|
||||
return newSelf
|
||||
modify { $0.enableExpansion = enableExpansion }
|
||||
}
|
||||
|
||||
/// Whether the row is expanded.
|
||||
public func expanded(_ expanded: Binding<Bool>?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.expanded = expanded
|
||||
|
||||
return newSelf
|
||||
modify { $0.expanded = expanded }
|
||||
}
|
||||
|
||||
/// Whether the switch enabling the expansion is visible.
|
||||
public func showEnableSwitch(_ showEnableSwitch: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.showEnableSwitch = showEnableSwitch
|
||||
|
||||
return newSelf
|
||||
modify { $0.showEnableSwitch = showEnableSwitch }
|
||||
}
|
||||
|
||||
/// The subtitle for this row.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.subtitle = subtitle
|
||||
|
||||
return newSelf
|
||||
modify { $0.subtitle = subtitle }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
public func subtitleLines(_ subtitleLines: Int?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.subtitleLines = subtitleLines
|
||||
|
||||
return newSelf
|
||||
modify { $0.subtitleLines = subtitleLines }
|
||||
}
|
||||
|
||||
/// The title of the preference represented by this row.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.title = title
|
||||
|
||||
return newSelf
|
||||
modify { $0.title = title }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
public func titleLines(_ titleLines: Int?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.titleLines = titleLines
|
||||
|
||||
return newSelf
|
||||
modify { $0.titleLines = titleLines }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.titleSelectable = titleSelectable
|
||||
|
||||
return newSelf
|
||||
modify { $0.titleSelectable = titleSelectable }
|
||||
}
|
||||
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.useMarkup = useMarkup
|
||||
|
||||
return newSelf
|
||||
modify { $0.useMarkup = useMarkup }
|
||||
}
|
||||
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// Set the body for "rows".
|
||||
@ -2,13 +2,13 @@
|
||||
// Fixed.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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.
|
||||
///
|
||||
@ -47,10 +47,17 @@ import LevenshteinTransformations
|
||||
/// widget. But you should be aware of the tradeoffs.
|
||||
public struct Fixed: AdwaitaWidget {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// The accessible role of the given `GtkAccessible` implementation.
|
||||
///
|
||||
@ -71,7 +78,6 @@ public struct Fixed: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -87,6 +93,7 @@ public struct Fixed: AdwaitaWidget {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -100,10 +107,7 @@ public struct Fixed: AdwaitaWidget {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,13 +2,15 @@
|
||||
// FlowBox.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// and the widget.
|
||||
///
|
||||
/// Also see [class@Gtk.ListBox].
|
||||
/// Also see `Gtk.ListBox`.
|
||||
///
|
||||
/// # CSS nodes
|
||||
///
|
||||
/// ```
|
||||
/// flowbox
|
||||
/// ├── flowboxchild
|
||||
/// │ ╰── <child>├── flowboxchild
|
||||
/// │ ╰── <child>┊
|
||||
/// ╰── [rubberband]
|
||||
/// ```
|
||||
///
|
||||
/// `GtkFlowBox` uses a single CSS node with name flowbox. `GtkFlowBoxChild`
|
||||
/// uses a single CSS node with name flowboxchild. For rubberband selection,
|
||||
/// a subnode with name rubberband is used.
|
||||
///
|
||||
/// # Accessibility
|
||||
///
|
||||
/// `GtkFlowBox` uses the %GTK_ACCESSIBLE_ROLE_GRID role, and `GtkFlowBoxChild`
|
||||
/// uses the %GTK_ACCESSIBLE_ROLE_GRID_CELL role.
|
||||
public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
public struct FlowBox<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// accept-unpaired-release
|
||||
/// Whether to accept unpaired release events.
|
||||
var acceptUnpairedRelease: Bool?
|
||||
/// The accessible role of the given `GtkAccessible` implementation.
|
||||
///
|
||||
@ -117,8 +109,8 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
var selectAll: (() -> Void)?
|
||||
/// Emitted when the set of selected children changes.
|
||||
///
|
||||
/// Use [method@Gtk.FlowBox.selected_foreach] or
|
||||
/// [method@Gtk.FlowBox.get_selected_children] to obtain the
|
||||
/// Use `Gtk.FlowBox.selected_foreach` or
|
||||
/// `Gtk.FlowBox.get_selected_children` to obtain the
|
||||
/// selected children.
|
||||
var selectedChildrenChanged: (() -> Void)?
|
||||
/// Emitted to toggle the selection of the child that has the focus.
|
||||
@ -138,11 +130,14 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
var elements: [Element]
|
||||
/// The dynamic widget content.
|
||||
var content: (Element) -> Body
|
||||
/// The dynamic widget identifier key path.
|
||||
var id: KeyPath<Element, Identifier>
|
||||
|
||||
/// Initialize `FlowBox`.
|
||||
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.content = content
|
||||
self.id = id
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -155,7 +150,6 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -225,15 +219,10 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
|
||||
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
|
||||
let old = storage.fields["element"] as? [Element] ?? []
|
||||
old.identifiableTransform(
|
||||
old.transform(
|
||||
to: elements,
|
||||
functions: .init { index, element in
|
||||
let child = content(element).storage(data: data, type: type)
|
||||
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
|
||||
id: id,
|
||||
functions: .init { index in
|
||||
gtk_flow_box_remove(widget, gtk_flow_box_get_child_at_index(widget, index.cInt)?.cast())
|
||||
contentStorage.remove(at: index)
|
||||
} insert: { index, element in
|
||||
@ -247,6 +236,7 @@ public struct FlowBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
for (index, element) in elements.enumerated() {
|
||||
content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type)
|
||||
}
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
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 {
|
||||
var newSelf = self
|
||||
newSelf.acceptUnpairedRelease = acceptUnpairedRelease
|
||||
|
||||
return newSelf
|
||||
modify { $0.acceptUnpairedRelease = acceptUnpairedRelease }
|
||||
}
|
||||
|
||||
/// The accessible role of the given `GtkAccessible` implementation.
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// Determines whether children can be activated with a single
|
||||
/// click, or require a double-click.
|
||||
public func activateOnSingleClick(_ activateOnSingleClick: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activateOnSingleClick = activateOnSingleClick
|
||||
|
||||
return newSelf
|
||||
modify { $0.activateOnSingleClick = activateOnSingleClick }
|
||||
}
|
||||
|
||||
/// The amount of horizontal space between two children.
|
||||
public func columnSpacing(_ columnSpacing: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.columnSpacing = columnSpacing
|
||||
|
||||
return newSelf
|
||||
modify { $0.columnSpacing = columnSpacing }
|
||||
}
|
||||
|
||||
/// Determines whether all children should be allocated the
|
||||
/// same size.
|
||||
public func homogeneous(_ homogeneous: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.homogeneous = homogeneous
|
||||
|
||||
return newSelf
|
||||
modify { $0.homogeneous = homogeneous }
|
||||
}
|
||||
|
||||
/// The maximum amount of children to request space for consecutively
|
||||
/// in the given orientation.
|
||||
public func maxChildrenPerLine(_ maxChildrenPerLine: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.maxChildrenPerLine = maxChildrenPerLine
|
||||
|
||||
return newSelf
|
||||
modify { $0.maxChildrenPerLine = maxChildrenPerLine }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// for the overall minimum width of the box.
|
||||
public func minChildrenPerLine(_ minChildrenPerLine: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.minChildrenPerLine = minChildrenPerLine
|
||||
|
||||
return newSelf
|
||||
modify { $0.minChildrenPerLine = minChildrenPerLine }
|
||||
}
|
||||
|
||||
/// The amount of vertical space between two children.
|
||||
public func rowSpacing(_ rowSpacing: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.rowSpacing = rowSpacing
|
||||
|
||||
return newSelf
|
||||
modify { $0.rowSpacing = rowSpacing }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// Use [method@Gtk.FlowBox.selected_foreach] or
|
||||
/// [method@Gtk.FlowBox.get_selected_children] to obtain the
|
||||
/// Use `Gtk.FlowBox.selected_foreach` or
|
||||
/// `Gtk.FlowBox.get_selected_children` to obtain the
|
||||
/// selected children.
|
||||
public func selectedChildrenChanged(_ selectedChildrenChanged: @escaping () -> Void) -> 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
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// HeaderBar.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,99 +10,31 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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
|
||||
/// 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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// The decoration layout for buttons.
|
||||
///
|
||||
/// 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
|
||||
/// 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.
|
||||
///
|
||||
/// 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?
|
||||
/// 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
|
||||
/// [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
|
||||
/// closed).
|
||||
var showEndTitleButtons: Bool?
|
||||
/// 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
|
||||
/// [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
|
||||
/// closed).
|
||||
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
|
||||
/// is contained in.
|
||||
///
|
||||
/// To use a different title, use [class@WindowTitle]:
|
||||
/// To use a different title, use `WindowTitle`:
|
||||
///
|
||||
/// ```xml
|
||||
/// <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".
|
||||
var start: () -> Body = { [] }
|
||||
/// The body for the widget "end".
|
||||
@ -167,8 +99,7 @@ public struct HeaderBar: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let titleWidgetStorage = titleWidget?().storage(data: data, type: type) {
|
||||
if let titleWidgetStorage = titleWidget?.storage(data: data, type: type) {
|
||||
storage.content["titleWidget"] = [titleWidgetStorage]
|
||||
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)
|
||||
}
|
||||
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"] {
|
||||
@ -241,6 +172,7 @@ public struct HeaderBar: AdwaitaWidget {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -253,7 +185,7 @@ public struct HeaderBar: AdwaitaWidget {
|
||||
/// The decoration layout for buttons.
|
||||
///
|
||||
/// 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
|
||||
/// 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,
|
||||
/// and minimize, maximize and close buttons at the end.
|
||||
public func decorationLayout(_ decorationLayout: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.decorationLayout = decorationLayout
|
||||
|
||||
return newSelf
|
||||
modify { $0.decorationLayout = decorationLayout }
|
||||
}
|
||||
|
||||
/// Whether the header bar can show the back button.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.showBackButton = showBackButton
|
||||
|
||||
return newSelf
|
||||
modify { $0.showBackButton = showBackButton }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// [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
|
||||
/// closed).
|
||||
public func showEndTitleButtons(_ showEndTitleButtons: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.showEndTitleButtons = showEndTitleButtons
|
||||
|
||||
return newSelf
|
||||
modify { $0.showEndTitleButtons = showEndTitleButtons }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// [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
|
||||
/// closed).
|
||||
public func showStartTitleButtons(_ showStartTitleButtons: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.showStartTitleButtons = showStartTitleButtons
|
||||
|
||||
return newSelf
|
||||
modify { $0.showStartTitleButtons = showStartTitleButtons }
|
||||
}
|
||||
|
||||
/// Whether the title widget should be shown.
|
||||
public func showTitle(_ showTitle: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.showTitle = showTitle
|
||||
|
||||
return newSelf
|
||||
modify { $0.showTitle = showTitle }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// is contained in.
|
||||
///
|
||||
/// To use a different title, use [class@WindowTitle]:
|
||||
/// To use a different title, use `WindowTitle`:
|
||||
///
|
||||
/// ```xml
|
||||
/// <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 {
|
||||
var newSelf = self
|
||||
newSelf.titleWidget = titleWidget
|
||||
|
||||
return newSelf
|
||||
public func titleWidget(@ViewBuilder _ titleWidget: () -> Body) -> Self {
|
||||
modify { $0.titleWidget = titleWidget() }
|
||||
}
|
||||
|
||||
/// Set the body for "start".
|
||||
168
Sources/Adwaita/View/Generated/Image.swift
Normal file
168
Sources/Adwaita/View/Generated/Image.swift
Normal 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 isn’t 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 }
|
||||
}
|
||||
|
||||
}
|
||||
331
Sources/Adwaita/View/Generated/Label.swift
Normal file
331
Sources/Adwaita/View/Generated/Label.swift
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,21 +2,21 @@
|
||||
// LevelBar.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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
|
||||
/// showing the charge level of a battery.
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 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
|
||||
/// offsets by default on the level bar: %GTK_LEVEL_BAR_OFFSET_LOW,
|
||||
/// %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
|
||||
/// 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 it’s 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, it’s 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 {
|
||||
|
||||
#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.
|
||||
///
|
||||
@ -129,7 +58,7 @@ public struct LevelBar: AdwaitaWidget {
|
||||
var value: Double?
|
||||
/// 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.
|
||||
///
|
||||
/// The signal supports detailed connections; you can connect to the
|
||||
@ -151,7 +80,6 @@ public struct LevelBar: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -184,6 +112,7 @@ public struct LevelBar: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -197,10 +126,7 @@ public struct LevelBar: AdwaitaWidget {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// Inverted level bars grow in the opposite direction.
|
||||
public func inverted(_ inverted: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.inverted = inverted
|
||||
|
||||
return newSelf
|
||||
modify { $0.inverted = inverted }
|
||||
}
|
||||
|
||||
/// Determines the maximum value of the interval that can be displayed by the bar.
|
||||
public func maxValue(_ maxValue: Double?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.maxValue = maxValue
|
||||
|
||||
return newSelf
|
||||
modify { $0.maxValue = maxValue }
|
||||
}
|
||||
|
||||
/// Determines the minimum value of the interval that can be displayed by the bar.
|
||||
public func minValue(_ minValue: Double?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.minValue = minValue
|
||||
|
||||
return newSelf
|
||||
modify { $0.minValue = minValue }
|
||||
}
|
||||
|
||||
/// Determines the currently filled value of the level bar.
|
||||
public func value(_ value: Double?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.value = value
|
||||
|
||||
return newSelf
|
||||
modify { $0.value = 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.
|
||||
///
|
||||
/// The signal supports detailed connections; you can connect to the
|
||||
@ -2,50 +2,50 @@
|
||||
// LinkButton.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// A `GtkLinkButton` is a button with a hyperlink.
|
||||
/// A button with a hyperlink.
|
||||
///
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// It is useful to show quick links to resources.
|
||||
///
|
||||
/// A link button is created by calling either [ctor@Gtk.LinkButton.new] or
|
||||
/// [ctor@Gtk.LinkButton.new_with_label]. If using the former, the URI you
|
||||
/// A link button is created by calling either `Gtk.LinkButton.new` or
|
||||
/// `Gtk.LinkButton.new_with_label`. If using the former, the URI you
|
||||
/// pass to the constructor is used as a label for the widget.
|
||||
///
|
||||
/// 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
|
||||
/// [signal@Gtk.LinkButton::activate-link] signal and returning %TRUE from
|
||||
/// `Gtk.LinkButton::activate-link` signal and returning `true` from
|
||||
/// 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 {
|
||||
|
||||
#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?
|
||||
/// action-name
|
||||
/// The name of the action with which this widget should be associated.
|
||||
var actionName: String?
|
||||
/// Whether the size of the button can be made smaller than the natural
|
||||
/// size of its contents.
|
||||
@ -56,7 +56,7 @@ public struct LinkButton: AdwaitaWidget {
|
||||
/// property has no effect.
|
||||
var canShrink: Bool?
|
||||
/// The child widget.
|
||||
var child: (() -> Body)?
|
||||
var child: Body?
|
||||
/// Whether the button has a frame.
|
||||
var hasFrame: Bool?
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// <kbd>␣</kbd> and <kbd>Enter</kbd> keys.
|
||||
@ -98,8 +98,7 @@ public struct LinkButton: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let childStorage = child?().storage(data: data, type: type) {
|
||||
if let childStorage = child?.storage(data: data, type: type) {
|
||||
storage.content["child"] = [childStorage]
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
gtk_button_set_has_frame(widget?.cast(), hasFrame.cBool)
|
||||
@ -155,6 +154,7 @@ public struct LinkButton: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -168,18 +168,12 @@ public struct LinkButton: AdwaitaWidget {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// action-name
|
||||
/// The name of the action with which this widget should be associated.
|
||||
public func actionName(_ actionName: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.actionName = actionName
|
||||
|
||||
return newSelf
|
||||
modify { $0.actionName = actionName }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// property has no effect.
|
||||
public func canShrink(_ canShrink: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.canShrink = canShrink
|
||||
|
||||
return newSelf
|
||||
modify { $0.canShrink = canShrink }
|
||||
}
|
||||
|
||||
/// The child widget.
|
||||
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.child = child
|
||||
|
||||
return newSelf
|
||||
public func child(@ViewBuilder _ child: () -> Body) -> Self {
|
||||
modify { $0.child = child() }
|
||||
}
|
||||
|
||||
/// Whether the button has a frame.
|
||||
public func hasFrame(_ hasFrame: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.hasFrame = hasFrame
|
||||
|
||||
return newSelf
|
||||
modify { $0.hasFrame = hasFrame }
|
||||
}
|
||||
|
||||
/// The name of the icon used to automatically populate the button.
|
||||
public func iconName(_ iconName: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.iconName = iconName
|
||||
|
||||
return newSelf
|
||||
modify { $0.iconName = iconName }
|
||||
}
|
||||
|
||||
/// Text of the label inside the button, if the button contains a label widget.
|
||||
public func label(_ label: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.label = label
|
||||
|
||||
return newSelf
|
||||
modify { $0.label = label }
|
||||
}
|
||||
|
||||
/// The URI bound to this button.
|
||||
public func uri(_ uri: String) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.uri = uri
|
||||
|
||||
return newSelf
|
||||
modify { $0.uri = uri }
|
||||
}
|
||||
|
||||
/// If set, an underline in the text indicates that the following character is
|
||||
/// to be used as mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// The 'visited' state of this button.
|
||||
///
|
||||
/// A visited link is drawn in a different color.
|
||||
public func visited(_ visited: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.visited = visited
|
||||
|
||||
return newSelf
|
||||
modify { $0.visited = visited }
|
||||
}
|
||||
|
||||
/// Emitted to animate press then release.
|
||||
///
|
||||
/// 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
|
||||
/// <kbd>␣</kbd> and <kbd>Enter</kbd> keys.
|
||||
@ -2,13 +2,15 @@
|
||||
// ListBox.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// `GtkListBox` is a vertical list.
|
||||
/// Shows a vertical list.
|
||||
///
|
||||
///
|
||||
///
|
||||
/// A `GtkListBox` only contains `GtkListBoxRow` children. These rows can
|
||||
/// by dynamically sorted and filtered, and headers can be added dynamically
|
||||
@ -21,52 +23,30 @@ import LevenshteinTransformations
|
||||
/// button in it).
|
||||
///
|
||||
/// Although a `GtkListBox` must have only `GtkListBoxRow` children, you can
|
||||
/// add any kind of widget to it via [method@Gtk.ListBox.prepend],
|
||||
/// [method@Gtk.ListBox.append] and [method@Gtk.ListBox.insert] and a
|
||||
/// add any kind of widget to it via `Gtk.ListBox.prepend`,
|
||||
/// `Gtk.ListBox.append` and `Gtk.ListBox.insert` and a
|
||||
/// `GtkListBoxRow` widget will automatically be inserted between the list
|
||||
/// and the widget.
|
||||
///
|
||||
/// `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
|
||||
/// as selected when the user tries to select it.
|
||||
///
|
||||
/// # GtkListBox as GtkBuildable
|
||||
///
|
||||
/// The `GtkListBox` implementation of the `GtkBuildable` interface supports
|
||||
/// 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 {
|
||||
public struct ListBox<Element, Identifier>: AdwaitaWidget where Identifier: Equatable {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// Whether to accept unpaired release events.
|
||||
var acceptUnpairedRelease: Bool?
|
||||
@ -79,9 +59,19 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
var activateOnSingleClick: Bool?
|
||||
/// Whether to show separators between rows.
|
||||
var showSeparators: Bool?
|
||||
/// activateCursorRow
|
||||
/// Emitted when the cursor row is activated.
|
||||
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)?
|
||||
/// Emitted when a row has been activated by the user.
|
||||
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
|
||||
/// 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)?
|
||||
/// Emitted to select all children of the box, if the selection
|
||||
/// mode permits it.
|
||||
@ -101,7 +91,9 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
var selectAll: (() -> Void)?
|
||||
/// Emitted when the set of selected rows changes.
|
||||
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)?
|
||||
/// Emitted to unselect all children of the box, if the selection
|
||||
/// mode permits it.
|
||||
@ -115,11 +107,14 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
var elements: [Element]
|
||||
/// The dynamic widget content.
|
||||
var content: (Element) -> Body
|
||||
/// The dynamic widget identifier key path.
|
||||
var id: KeyPath<Element, Identifier>
|
||||
|
||||
/// Initialize `ListBox`.
|
||||
public init(_ elements: [Element], @ViewBuilder content: @escaping (Element) -> Body) {
|
||||
public init(_ elements: [Element], id: KeyPath<Element, Identifier>, @ViewBuilder content: @escaping (Element) -> Body) {
|
||||
self.elements = elements
|
||||
self.content = content
|
||||
self.id = id
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -132,7 +127,6 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -195,15 +189,10 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
|
||||
var contentStorage: [ViewStorage] = storage.content[.mainContent] ?? []
|
||||
let old = storage.fields["element"] as? [Element] ?? []
|
||||
old.identifiableTransform(
|
||||
old.transform(
|
||||
to: elements,
|
||||
functions: .init { index, element in
|
||||
let child = content(element).storage(data: data, type: type)
|
||||
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
|
||||
id: id,
|
||||
functions: .init { index in
|
||||
gtk_list_box_remove(widget, gtk_list_box_get_row_at_index(widget, index.cInt)?.cast())
|
||||
contentStorage.remove(at: index)
|
||||
} insert: { index, element in
|
||||
@ -217,6 +206,7 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
for (index, element) in elements.enumerated() {
|
||||
content(element).updateStorage(contentStorage[index], data: data, updateProperties: updateProperties, type: type)
|
||||
}
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -228,47 +218,45 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
|
||||
/// Whether to accept unpaired release events.
|
||||
public func acceptUnpairedRelease(_ acceptUnpairedRelease: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.acceptUnpairedRelease = acceptUnpairedRelease
|
||||
|
||||
return newSelf
|
||||
modify { $0.acceptUnpairedRelease = acceptUnpairedRelease }
|
||||
}
|
||||
|
||||
/// The accessible role of the given `GtkAccessible` implementation.
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// Determines whether children can be activated with a single
|
||||
/// click, or require a double-click.
|
||||
public func activateOnSingleClick(_ activateOnSingleClick: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activateOnSingleClick = activateOnSingleClick
|
||||
|
||||
return newSelf
|
||||
modify { $0.activateOnSingleClick = activateOnSingleClick }
|
||||
}
|
||||
|
||||
/// Whether to show separators between rows.
|
||||
public func showSeparators(_ showSeparators: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.showSeparators = showSeparators
|
||||
|
||||
return newSelf
|
||||
modify { $0.showSeparators = showSeparators }
|
||||
}
|
||||
|
||||
/// activateCursorRow
|
||||
/// Emitted when the cursor row is activated.
|
||||
public func activateCursorRow(_ activateCursorRow: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activateCursorRow = activateCursorRow
|
||||
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 {
|
||||
var newSelf = self
|
||||
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
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.rowSelected = rowSelected
|
||||
@ -313,7 +301,9 @@ public struct ListBox<Element>: AdwaitaWidget where Element: Identifiable {
|
||||
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 {
|
||||
var newSelf = self
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,30 +2,30 @@
|
||||
// Menu.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// The `GtkMenuButton` widget is used to display a popup when clicked.
|
||||
/// Displays a popup when clicked.
|
||||
///
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// This popup can be provided either as a `GtkPopover` or as an abstract
|
||||
/// `GMenuModel`.
|
||||
///
|
||||
/// The `GtkMenuButton` widget can show either an icon (set with the
|
||||
/// [property@Gtk.MenuButton:icon-name] property) or a label (set with the
|
||||
/// [property@Gtk.MenuButton:label] property). If neither is explicitly set,
|
||||
/// a [class@Gtk.Image] is automatically created, using an arrow image oriented
|
||||
/// according to [property@Gtk.MenuButton:direction] or the generic
|
||||
/// ``iconName(_:)`` property) or a label (set with the
|
||||
/// ``label(_:)`` property). If neither is explicitly set,
|
||||
/// a `Gtk.Image` is automatically created, using an arrow image oriented
|
||||
/// according to ``direction(_:)`` or the generic
|
||||
/// “open-menu-symbolic” icon if the direction is not set.
|
||||
///
|
||||
/// 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
|
||||
/// 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
|
||||
@ -41,40 +41,20 @@ import LevenshteinTransformations
|
||||
/// | **left** |  |  |  |
|
||||
/// | **right** |  |  |  |
|
||||
///
|
||||
/// # 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 {
|
||||
|
||||
#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.
|
||||
///
|
||||
@ -88,7 +68,7 @@ public struct Menu: AdwaitaWidget {
|
||||
/// size of its contents.
|
||||
var canShrink: Bool?
|
||||
/// The child widget.
|
||||
var child: (() -> Body)?
|
||||
var child: Body?
|
||||
/// Whether the button has a frame.
|
||||
var hasFrame: Bool?
|
||||
/// The name of the icon used to automatically populate the button.
|
||||
@ -97,9 +77,9 @@ public struct Menu: AdwaitaWidget {
|
||||
var label: String?
|
||||
/// The `GMenuModel` from which the popup will be created.
|
||||
///
|
||||
/// See [method@Gtk.MenuButton.set_menu_model] for the interaction
|
||||
/// with the [property@Gtk.MenuButton:popover] property.
|
||||
var menuModel: (() -> Body)?
|
||||
/// See `Gtk.MenuButton.set_menu_model` for the interaction
|
||||
/// with the ``popover(_:)`` property.
|
||||
var menuModel: Body?
|
||||
/// Whether the menu button acts as a primary menu.
|
||||
///
|
||||
/// Primary menus can be opened using the <kbd>F10</kbd> key
|
||||
@ -113,7 +93,7 @@ public struct Menu: AdwaitaWidget {
|
||||
var activate: (() -> Void)?
|
||||
|
||||
/// Initialize `Menu`.
|
||||
public init() {
|
||||
init() {
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -126,13 +106,12 @@ public struct Menu: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let childStorage = child?().storage(data: data, type: type) {
|
||||
if let childStorage = child?.storage(data: data, type: type) {
|
||||
storage.content["child"] = [childStorage]
|
||||
gtk_menu_button_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())
|
||||
}
|
||||
if let menu = menuModel?() {
|
||||
let childStorage = MenuCollection { menu }.getMenu(data: data)
|
||||
if let menuModel {
|
||||
let childStorage = MenuCollection { menuModel }.getMenu(data: data)
|
||||
storage.content["menuModel"] = [childStorage]
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
if let menu = storage.content["menuModel"]?.first {
|
||||
MenuCollection { menuModel?() ?? [] }
|
||||
MenuCollection { menuModel ?? [] }
|
||||
.updateStorage(menu, data: data.noModifiers, updateProperties: updateProperties, type: MenuContext.self)
|
||||
}
|
||||
if let primary, updateProperties, (storage.previousState as? Self)?.primary != primary {
|
||||
@ -193,6 +172,7 @@ if let active, newValue != active.wrappedValue {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -206,96 +186,63 @@ if let active, newValue != active.wrappedValue {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// Whether the menu button is active.
|
||||
public func active(_ active: Binding<Bool>?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.active = active
|
||||
|
||||
return newSelf
|
||||
modify { $0.active = active }
|
||||
}
|
||||
|
||||
/// Whether to show a dropdown arrow even when using an icon or a custom child.
|
||||
public func alwaysShowArrow(_ alwaysShowArrow: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.alwaysShowArrow = alwaysShowArrow
|
||||
|
||||
return newSelf
|
||||
modify { $0.alwaysShowArrow = alwaysShowArrow }
|
||||
}
|
||||
|
||||
/// Whether the size of the button can be made smaller than the natural
|
||||
/// size of its contents.
|
||||
public func canShrink(_ canShrink: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.canShrink = canShrink
|
||||
|
||||
return newSelf
|
||||
modify { $0.canShrink = canShrink }
|
||||
}
|
||||
|
||||
/// The child widget.
|
||||
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.child = child
|
||||
|
||||
return newSelf
|
||||
public func child(@ViewBuilder _ child: () -> Body) -> Self {
|
||||
modify { $0.child = child() }
|
||||
}
|
||||
|
||||
/// Whether the button has a frame.
|
||||
public func hasFrame(_ hasFrame: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.hasFrame = hasFrame
|
||||
|
||||
return newSelf
|
||||
modify { $0.hasFrame = hasFrame }
|
||||
}
|
||||
|
||||
/// The name of the icon used to automatically populate the button.
|
||||
public func iconName(_ iconName: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.iconName = iconName
|
||||
|
||||
return newSelf
|
||||
modify { $0.iconName = iconName }
|
||||
}
|
||||
|
||||
/// The label for the button.
|
||||
public func label(_ label: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.label = label
|
||||
|
||||
return newSelf
|
||||
modify { $0.label = label }
|
||||
}
|
||||
|
||||
/// The `GMenuModel` from which the popup will be created.
|
||||
///
|
||||
/// See [method@Gtk.MenuButton.set_menu_model] for the interaction
|
||||
/// with the [property@Gtk.MenuButton:popover] property.
|
||||
public func menuModel(@ViewBuilder _ menuModel: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.menuModel = menuModel
|
||||
|
||||
return newSelf
|
||||
/// See `Gtk.MenuButton.set_menu_model` for the interaction
|
||||
/// with the ``popover(_:)`` property.
|
||||
public func menuModel(@ViewBuilder _ menuModel: () -> Body) -> Self {
|
||||
modify { $0.menuModel = menuModel() }
|
||||
}
|
||||
|
||||
/// Whether the menu button acts as a primary menu.
|
||||
///
|
||||
/// Primary menus can be opened using the <kbd>F10</kbd> key
|
||||
public func primary(_ primary: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.primary = primary
|
||||
|
||||
return newSelf
|
||||
modify { $0.primary = primary }
|
||||
}
|
||||
|
||||
/// If set an underscore in the text indicates a mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// Emitted to when the menu button is activated.
|
||||
@ -2,7 +2,7 @@
|
||||
// NavigationView.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,130 +10,74 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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
|
||||
/// [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
|
||||
/// [method@NavigationView.push] and [method@NavigationView.pop]. The whole
|
||||
/// navigation stack can also be replaced using [method@NavigationView.replace].
|
||||
/// `NavigationView.push` and `NavigationView.pop`. The whole
|
||||
/// navigation stack can also be replaced using `NavigationView.replace`.
|
||||
///
|
||||
/// `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
|
||||
/// 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
|
||||
/// [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
|
||||
/// navigation between them.
|
||||
///
|
||||
/// Dynamic pages are automatically destroyed once they are popped off the
|
||||
/// navigation stack. To add a page like this, push it using the
|
||||
/// [method@NavigationView.push] method without calling
|
||||
/// [method@NavigationView.add] first.
|
||||
/// `NavigationView.push` method without calling
|
||||
/// `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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// Whether to animate page transitions.
|
||||
///
|
||||
/// Gesture-based transitions are always animated.
|
||||
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.
|
||||
///
|
||||
/// Applications using `AdwNavigationView` to implement a browser may want to
|
||||
/// disable it.
|
||||
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.
|
||||
///
|
||||
/// 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
|
||||
/// 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)?
|
||||
/// 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
|
||||
/// [method@NavigationView.pop_to_tag], this signal is emitted for each of the
|
||||
/// When using `NavigationView.pop_to_page` or
|
||||
/// `NavigationView.pop_to_tag`, this signal is emitted for each of the
|
||||
/// popped pages.
|
||||
var popped: (() -> Void)?
|
||||
/// Emitted after a page has been pushed to the navigation stack.
|
||||
///
|
||||
/// See [method@NavigationView.push].
|
||||
/// See `NavigationView.push`.
|
||||
var pushed: (() -> Void)?
|
||||
/// Emitted after the navigation stack has been replaced.
|
||||
///
|
||||
/// See [method@NavigationView.replace].
|
||||
/// See `NavigationView.replace`.
|
||||
var replaced: (() -> Void)?
|
||||
|
||||
/// Initialize `NavigationView`.
|
||||
public init() {
|
||||
init() {
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -177,7 +121,6 @@ public struct NavigationView: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
return storage
|
||||
}
|
||||
@ -214,9 +157,16 @@ public struct NavigationView: AdwaitaWidget {
|
||||
if let animateTransitions, updateProperties, (storage.previousState as? Self)?.animateTransitions != animateTransitions {
|
||||
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 {
|
||||
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.
|
||||
public func animateTransitions(_ animateTransitions: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.animateTransitions = animateTransitions
|
||||
|
||||
return newSelf
|
||||
modify { $0.animateTransitions = animateTransitions }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
@ -243,10 +201,23 @@ public struct NavigationView: AdwaitaWidget {
|
||||
/// Applications using `AdwNavigationView` to implement a browser may want to
|
||||
/// disable it.
|
||||
public func popOnEscape(_ popOnEscape: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.popOnEscape = popOnEscape
|
||||
|
||||
return newSelf
|
||||
modify { $0.popOnEscape = popOnEscape }
|
||||
}
|
||||
|
||||
/// 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.
|
||||
@ -259,7 +230,7 @@ public struct NavigationView: AdwaitaWidget {
|
||||
/// not make any irreversible changes in the handler, such as removing the page
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.getNextPage = getNextPage
|
||||
@ -268,10 +239,10 @@ public struct NavigationView: AdwaitaWidget {
|
||||
|
||||
/// 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
|
||||
/// [method@NavigationView.pop_to_tag], this signal is emitted for each of the
|
||||
/// When using `NavigationView.pop_to_page` or
|
||||
/// `NavigationView.pop_to_tag`, this signal is emitted for each of the
|
||||
/// popped pages.
|
||||
public func popped(_ popped: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
@ -281,7 +252,7 @@ public struct NavigationView: AdwaitaWidget {
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.pushed = pushed
|
||||
@ -290,7 +261,7 @@ public struct NavigationView: AdwaitaWidget {
|
||||
|
||||
/// Emitted after the navigation stack has been replaced.
|
||||
///
|
||||
/// See [method@NavigationView.replace].
|
||||
/// See `NavigationView.replace`.
|
||||
public func replaced(_ replaced: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.replaced = replaced
|
||||
@ -2,19 +2,18 @@
|
||||
// Overlay.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
import LevenshteinTransformations
|
||||
|
||||
/// `GtkOverlay` is a container which contains a single main child, on top
|
||||
/// of which it can place “overlay” widgets.
|
||||
/// Places “overlay” widgets on top of a single main child.
|
||||
///
|
||||
///
|
||||
/// 
|
||||
///
|
||||
/// 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
|
||||
/// 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
|
||||
@ -23,36 +22,33 @@ import LevenshteinTransformations
|
||||
/// properties of the child to non-zero values.
|
||||
///
|
||||
/// 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 overlay’s minimum and natural sizes are those of its main child.
|
||||
/// The sizes of overlay children are not considered when measuring these
|
||||
/// 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 {
|
||||
|
||||
#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 main child widget.
|
||||
var child: (() -> Body)?
|
||||
var child: Body?
|
||||
/// Emitted to determine the position and size of any overlay
|
||||
/// child widgets.
|
||||
///
|
||||
@ -85,8 +81,7 @@ public struct Overlay: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let childStorage = child?().storage(data: data, type: type) {
|
||||
if let childStorage = child?.storage(data: data, type: type) {
|
||||
storage.content["child"] = [childStorage]
|
||||
gtk_overlay_set_child(storage.opaquePointer, childStorage.opaquePointer?.cast())
|
||||
}
|
||||
@ -115,7 +110,7 @@ public struct Overlay: AdwaitaWidget {
|
||||
storage.modify { widget in
|
||||
|
||||
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"] {
|
||||
@ -131,6 +126,7 @@ public struct Overlay: AdwaitaWidget {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -144,18 +140,12 @@ public struct Overlay: AdwaitaWidget {
|
||||
///
|
||||
/// The accessible role cannot be changed once set.
|
||||
public func accessibleRole(_ accessibleRole: String?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.accessibleRole = accessibleRole
|
||||
|
||||
return newSelf
|
||||
modify { $0.accessibleRole = accessibleRole }
|
||||
}
|
||||
|
||||
/// The main child widget.
|
||||
public func child(@ViewBuilder _ child: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.child = child
|
||||
|
||||
return newSelf
|
||||
public func child(@ViewBuilder _ child: () -> Body) -> Self {
|
||||
modify { $0.child = child() }
|
||||
}
|
||||
|
||||
/// Emitted to determine the position and size of any overlay
|
||||
@ -2,7 +2,7 @@
|
||||
// OverlaySplitView.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
@ -10,115 +10,57 @@ import LevenshteinTransformations
|
||||
|
||||
/// 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
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
/// with the [property@OverlaySplitView:sidebar-position] property.
|
||||
/// with the ``sidebarPosition(_:)`` property.
|
||||
///
|
||||
/// Collapsing the split view automatically hides the sidebar widget, and
|
||||
/// 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,
|
||||
/// and a swipe from the sidebar for hiding it. Gestures are only supported on
|
||||
/// touchscreen, but not touchpad. Gestures can be controlled with the
|
||||
/// [property@OverlaySplitView:enable-show-gesture] and
|
||||
/// [property@OverlaySplitView:enable-hide-gesture] properties.
|
||||
/// ``enableShowGesture(_:)`` and
|
||||
/// ``enableHideGesture(_:)`` properties.
|
||||
///
|
||||
/// See also [class@NavigationSplitView].
|
||||
/// See also `NavigationSplitView`.
|
||||
///
|
||||
/// `AdwOverlaySplitView` is typically used together with an [class@Breakpoint]
|
||||
/// setting the `collapsed` property to `TRUE` on small widths, as follows:
|
||||
/// `AdwOverlaySplitView` is typically used together with an `Breakpoint`
|
||||
/// setting the `collapsed` property to `true` on small widths, as follows:
|
||||
///
|
||||
/// ```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
|
||||
/// [utility pane](https://developer.gnome.org/hig/patterns/containers/utility-panes.html)
|
||||
/// 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 {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// Whether the split view is collapsed.
|
||||
///
|
||||
@ -126,7 +68,7 @@ public struct OverlaySplitView: AdwaitaWidget {
|
||||
/// content widget, otherwise they are displayed side by side.
|
||||
var collapsed: Bool?
|
||||
/// The content widget.
|
||||
var content: (() -> Body)?
|
||||
var content: Body?
|
||||
/// Whether the sidebar can be closed with a swipe gesture.
|
||||
///
|
||||
/// Only touchscreen swipes are supported.
|
||||
@ -138,7 +80,7 @@ public struct OverlaySplitView: AdwaitaWidget {
|
||||
/// The maximum sidebar width.
|
||||
///
|
||||
/// Maximum width is affected by
|
||||
/// [property@OverlaySplitView:sidebar-width-unit].
|
||||
/// ``sidebarWidthUnit(_:)``.
|
||||
///
|
||||
/// The sidebar widget can still be allocated with larger width if its own
|
||||
/// minimum width exceeds it.
|
||||
@ -146,7 +88,7 @@ public struct OverlaySplitView: AdwaitaWidget {
|
||||
/// The minimum sidebar width.
|
||||
///
|
||||
/// Minimum width is affected by
|
||||
/// [property@OverlaySplitView:sidebar-width-unit].
|
||||
/// ``sidebarWidthUnit(_:)``.
|
||||
///
|
||||
/// The sidebar widget can still be allocated with larger width if its own
|
||||
/// minimum width exceeds it.
|
||||
@ -154,25 +96,25 @@ public struct OverlaySplitView: AdwaitaWidget {
|
||||
/// Whether the sidebar widget is pinned.
|
||||
///
|
||||
/// 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.
|
||||
var pinSidebar: Bool?
|
||||
/// Whether the sidebar widget is shown.
|
||||
var showSidebar: Binding<Bool>?
|
||||
/// The sidebar widget.
|
||||
var sidebar: (() -> Body)?
|
||||
var sidebar: Body?
|
||||
/// The preferred sidebar width as a fraction of the total width.
|
||||
///
|
||||
/// The preferred width is additionally limited by
|
||||
/// [property@OverlaySplitView:min-sidebar-width] and
|
||||
/// [property@OverlaySplitView:max-sidebar-width].
|
||||
/// ``minSidebarWidth(_:)`` and
|
||||
/// ``maxSidebarWidth(_:)``.
|
||||
///
|
||||
/// The sidebar widget can be allocated with larger width if its own minimum
|
||||
/// width exceeds the preferred width.
|
||||
var sidebarWidthFraction: Double?
|
||||
|
||||
/// Initialize `OverlaySplitView`.
|
||||
public init() {
|
||||
init() {
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -185,12 +127,11 @@ public struct OverlaySplitView: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
if let contentStorage = content?().storage(data: data, type: type) {
|
||||
if let contentStorage = content?.storage(data: data, type: type) {
|
||||
storage.content["content"] = [contentStorage]
|
||||
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]
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
adw_overlay_split_view_set_sidebar_width_fraction(widget, sidebarWidthFraction)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
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
|
||||
/// content widget, otherwise they are displayed side by side.
|
||||
public func collapsed(_ collapsed: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.collapsed = collapsed
|
||||
|
||||
return newSelf
|
||||
modify { $0.collapsed = collapsed }
|
||||
}
|
||||
|
||||
/// The content widget.
|
||||
public func content(@ViewBuilder _ content: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.content = content
|
||||
|
||||
return newSelf
|
||||
public func content(@ViewBuilder _ content: () -> Body) -> Self {
|
||||
modify { $0.content = content() }
|
||||
}
|
||||
|
||||
/// Whether the sidebar can be closed with a swipe gesture.
|
||||
///
|
||||
/// Only touchscreen swipes are supported.
|
||||
public func enableHideGesture(_ enableHideGesture: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.enableHideGesture = enableHideGesture
|
||||
|
||||
return newSelf
|
||||
modify { $0.enableHideGesture = enableHideGesture }
|
||||
}
|
||||
|
||||
/// Whether the sidebar can be opened with an edge swipe gesture.
|
||||
///
|
||||
/// Only touchscreen swipes are supported.
|
||||
public func enableShowGesture(_ enableShowGesture: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.enableShowGesture = enableShowGesture
|
||||
|
||||
return newSelf
|
||||
modify { $0.enableShowGesture = enableShowGesture }
|
||||
}
|
||||
|
||||
/// The maximum sidebar width.
|
||||
///
|
||||
/// Maximum width is affected by
|
||||
/// [property@OverlaySplitView:sidebar-width-unit].
|
||||
/// ``sidebarWidthUnit(_:)``.
|
||||
///
|
||||
/// The sidebar widget can still be allocated with larger width if its own
|
||||
/// minimum width exceeds it.
|
||||
public func maxSidebarWidth(_ maxSidebarWidth: Double?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.maxSidebarWidth = maxSidebarWidth
|
||||
|
||||
return newSelf
|
||||
modify { $0.maxSidebarWidth = maxSidebarWidth }
|
||||
}
|
||||
|
||||
/// The minimum sidebar width.
|
||||
///
|
||||
/// Minimum width is affected by
|
||||
/// [property@OverlaySplitView:sidebar-width-unit].
|
||||
/// ``sidebarWidthUnit(_:)``.
|
||||
///
|
||||
/// The sidebar widget can still be allocated with larger width if its own
|
||||
/// minimum width exceeds it.
|
||||
public func minSidebarWidth(_ minSidebarWidth: Double?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.minSidebarWidth = minSidebarWidth
|
||||
|
||||
return newSelf
|
||||
modify { $0.minSidebarWidth = minSidebarWidth }
|
||||
}
|
||||
|
||||
/// Whether the sidebar widget is pinned.
|
||||
///
|
||||
/// 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.
|
||||
public func pinSidebar(_ pinSidebar: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.pinSidebar = pinSidebar
|
||||
|
||||
return newSelf
|
||||
modify { $0.pinSidebar = pinSidebar }
|
||||
}
|
||||
|
||||
/// Whether the sidebar widget is shown.
|
||||
public func showSidebar(_ showSidebar: Binding<Bool>?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.showSidebar = showSidebar
|
||||
|
||||
return newSelf
|
||||
modify { $0.showSidebar = showSidebar }
|
||||
}
|
||||
|
||||
/// The sidebar widget.
|
||||
public func sidebar(@ViewBuilder _ sidebar: @escaping (() -> Body)) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.sidebar = sidebar
|
||||
|
||||
return newSelf
|
||||
public func sidebar(@ViewBuilder _ sidebar: () -> Body) -> Self {
|
||||
modify { $0.sidebar = sidebar() }
|
||||
}
|
||||
|
||||
/// The preferred sidebar width as a fraction of the total width.
|
||||
///
|
||||
/// The preferred width is additionally limited by
|
||||
/// [property@OverlaySplitView:min-sidebar-width] and
|
||||
/// [property@OverlaySplitView:max-sidebar-width].
|
||||
/// ``minSidebarWidth(_:)`` and
|
||||
/// ``maxSidebarWidth(_:)``.
|
||||
///
|
||||
/// The sidebar widget can be allocated with larger width if its own minimum
|
||||
/// width exceeds the preferred width.
|
||||
public func sidebarWidthFraction(_ sidebarWidthFraction: Double?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.sidebarWidthFraction = sidebarWidthFraction
|
||||
|
||||
return newSelf
|
||||
modify { $0.sidebarWidthFraction = sidebarWidthFraction }
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,15 +2,15 @@
|
||||
// PasswordEntryRow.swift
|
||||
// Adwaita
|
||||
//
|
||||
// Created by auto-generation on 15.08.24.
|
||||
// Created by auto-generation on 04.02.26.
|
||||
//
|
||||
|
||||
import CAdw
|
||||
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
|
||||
/// 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.
|
||||
///
|
||||
/// ## CSS Nodes
|
||||
///
|
||||
/// `AdwPasswordEntryRow` has a single CSS node with name `row` that carries
|
||||
/// `.entry` and `.password` style classes.
|
||||
public struct PasswordEntryRow: AdwaitaWidget {
|
||||
|
||||
#if exposeGeneratedAppearUpdateFunctions
|
||||
/// Additional update functions for type extensions.
|
||||
public var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
public var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#else
|
||||
/// Additional update functions for type extensions.
|
||||
var updateFunctions: [(ViewStorage, WidgetData, Bool) -> Void] = []
|
||||
/// Additional appear functions for type extensions.
|
||||
var appearFunctions: [(ViewStorage, WidgetData) -> Void] = []
|
||||
#endif
|
||||
|
||||
/// Whether activating the embedded entry can activate the default widget.
|
||||
var activatesDefault: Bool?
|
||||
@ -37,11 +41,13 @@ public struct PasswordEntryRow: AdwaitaWidget {
|
||||
///
|
||||
/// Emoji replacement is done with :-delimited names, like `:heart:`.
|
||||
var enableEmojiCompletion: Bool?
|
||||
/// Maximum number of characters for the entry.
|
||||
var maxLength: Int?
|
||||
/// 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
|
||||
/// emit the [signal@EntryRow::apply] signal.
|
||||
/// emit the `EntryRow::apply` signal.
|
||||
///
|
||||
/// This is useful if changing the entry contents can trigger an expensive
|
||||
/// 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 is interpreted as Pango markup unless
|
||||
/// [property@PreferencesRow:use-markup] is set to `FALSE`.
|
||||
/// ``useMarkup(_:)`` is set to `false`.
|
||||
var title: String?
|
||||
/// Whether the user can copy the title from the label.
|
||||
///
|
||||
/// See also [property@Gtk.Label:selectable].
|
||||
/// See also ``selectable(_:)``.
|
||||
var titleSelectable: Bool?
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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?
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
var useUnderline: Bool?
|
||||
/// Emitted when the apply button is pressed.
|
||||
///
|
||||
/// See [property@EntryRow:show-apply-button].
|
||||
/// See ``showApplyButton(_:)``.
|
||||
var apply: (() -> Void)?
|
||||
/// Emitted when the embedded entry is activated.
|
||||
var entryActivated: (() -> Void)?
|
||||
@ -78,7 +84,7 @@ public struct PasswordEntryRow: AdwaitaWidget {
|
||||
var prefix: () -> Body = { [] }
|
||||
|
||||
/// Initialize `PasswordEntryRow`.
|
||||
public init() {
|
||||
init() {
|
||||
}
|
||||
|
||||
/// The view storage.
|
||||
@ -91,7 +97,6 @@ public struct PasswordEntryRow: AdwaitaWidget {
|
||||
for function in appearFunctions {
|
||||
function(storage, data)
|
||||
}
|
||||
update(storage, data: data, updateProperties: true, type: type)
|
||||
|
||||
var suffixStorage: [ViewStorage] = []
|
||||
for view in suffix() {
|
||||
@ -133,6 +138,9 @@ public struct PasswordEntryRow: AdwaitaWidget {
|
||||
if let enableEmojiCompletion, updateProperties, (storage.previousState as? Self)?.enableEmojiCompletion != enableEmojiCompletion {
|
||||
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 {
|
||||
adw_entry_row_set_show_apply_button(widget?.cast(), showApplyButton.cBool)
|
||||
}
|
||||
@ -150,6 +158,7 @@ public struct PasswordEntryRow: AdwaitaWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
for function in updateFunctions {
|
||||
function(storage, data, updateProperties)
|
||||
@ -161,90 +170,71 @@ public struct PasswordEntryRow: AdwaitaWidget {
|
||||
|
||||
/// Whether activating the embedded entry can activate the default widget.
|
||||
public func activatesDefault(_ activatesDefault: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.activatesDefault = activatesDefault
|
||||
|
||||
return newSelf
|
||||
modify { $0.activatesDefault = activatesDefault }
|
||||
}
|
||||
|
||||
/// Whether to suggest emoji replacements on the entry row.
|
||||
///
|
||||
/// Emoji replacement is done with :-delimited names, like `:heart:`.
|
||||
public func enableEmojiCompletion(_ enableEmojiCompletion: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.enableEmojiCompletion = enableEmojiCompletion
|
||||
|
||||
return newSelf
|
||||
modify { $0.enableEmojiCompletion = enableEmojiCompletion }
|
||||
}
|
||||
|
||||
/// Maximum number of characters for the entry.
|
||||
public func maxLength(_ maxLength: Int?) -> Self {
|
||||
modify { $0.maxLength = maxLength }
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// emit the [signal@EntryRow::apply] signal.
|
||||
/// emit the `EntryRow::apply` signal.
|
||||
///
|
||||
/// This is useful if changing the entry contents can trigger an expensive
|
||||
/// operation, e.g. network activity, to avoid triggering it after typing every
|
||||
/// character.
|
||||
public func showApplyButton(_ showApplyButton: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.showApplyButton = showApplyButton
|
||||
|
||||
return newSelf
|
||||
modify { $0.showApplyButton = showApplyButton }
|
||||
}
|
||||
|
||||
/// The length of the text in the entry row.
|
||||
public func textLength(_ textLength: UInt?) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.textLength = textLength
|
||||
|
||||
return newSelf
|
||||
modify { $0.textLength = textLength }
|
||||
}
|
||||
|
||||
/// The title of the preference represented by this row.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.title = title
|
||||
|
||||
return newSelf
|
||||
modify { $0.title = title }
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.titleSelectable = titleSelectable
|
||||
|
||||
return newSelf
|
||||
modify { $0.titleSelectable = titleSelectable }
|
||||
}
|
||||
|
||||
/// Whether to use Pango markup for the title label.
|
||||
///
|
||||
/// 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 {
|
||||
var newSelf = self
|
||||
newSelf.useMarkup = useMarkup
|
||||
|
||||
return newSelf
|
||||
modify { $0.useMarkup = useMarkup }
|
||||
}
|
||||
|
||||
/// Whether an embedded underline in the title indicates a mnemonic.
|
||||
public func useUnderline(_ useUnderline: Bool? = true) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.useUnderline = useUnderline
|
||||
|
||||
return newSelf
|
||||
modify { $0.useUnderline = useUnderline }
|
||||
}
|
||||
|
||||
/// Emitted when the apply button is pressed.
|
||||
///
|
||||
/// See [property@EntryRow:show-apply-button].
|
||||
/// See ``showApplyButton(_:)``.
|
||||
public func apply(_ apply: @escaping () -> Void) -> Self {
|
||||
var newSelf = self
|
||||
newSelf.apply = apply
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user