106 lines
3.5 KiB
Swift
106 lines
3.5 KiB
Swift
//
|
|
// ToggleGroup+.swift
|
|
// Adwaita
|
|
//
|
|
// Created by david-swift on 03.11.25.
|
|
//
|
|
|
|
import CAdw
|
|
import LevenshteinTransformations
|
|
|
|
extension ToggleGroup {
|
|
|
|
/// The identifier for the values.
|
|
static var values: String { "values" }
|
|
/// The identifier for the toggles.
|
|
static var toggle: String { "Toggle::" }
|
|
|
|
/// Initialize a toggle group.
|
|
/// - Parameters:
|
|
/// - selection: The selected value.
|
|
/// - values: The available values.
|
|
public init<Element>(
|
|
selection: Binding<Element.ID>,
|
|
values: [Element]
|
|
) where Element: ToggleGroupItem {
|
|
self.init()
|
|
appearFunctions.append { storage, _ in
|
|
storage.notify(name: "active-name", id: "init") {
|
|
if let name = adw_toggle_group_get_active_name(storage.opaquePointer),
|
|
let values = storage.fields[Self.values] as? [Element],
|
|
let value = values.first(where: { $0.id.description == String(cString: name) }) {
|
|
selection.wrappedValue = value.id
|
|
}
|
|
}
|
|
Self.updateContent(
|
|
storage: storage,
|
|
selection: selection.wrappedValue,
|
|
values: values,
|
|
updateProperties: true
|
|
)
|
|
}
|
|
updateFunctions.append { storage, _, updateProperties in
|
|
Self.updateContent(
|
|
storage: storage,
|
|
selection: selection.wrappedValue,
|
|
values: values,
|
|
updateProperties: updateProperties
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Update the combo row's content.
|
|
/// - Parameters:
|
|
/// - storage: The view storage.
|
|
/// - values: The elements.
|
|
/// - updateProperties: Whether to update the properties.
|
|
static func updateContent<Element>(
|
|
storage: ViewStorage,
|
|
selection: Element.ID,
|
|
values: [Element],
|
|
updateProperties: Bool
|
|
) where Element: ToggleGroupItem {
|
|
guard updateProperties else {
|
|
return
|
|
}
|
|
let old = storage.fields[Self.values] as? [Element] ?? []
|
|
old.identifiableTransform(
|
|
to: values,
|
|
functions: .init { index in
|
|
if let id = old[safe: index]?.id.description,
|
|
let toggle = storage.fields[Self.toggle + id] as? OpaquePointer {
|
|
adw_toggle_group_remove(storage.opaquePointer, toggle)
|
|
}
|
|
} insert: { _, element in
|
|
let toggle = adw_toggle_new()
|
|
adw_toggle_set_name(toggle, element.id.description)
|
|
if element.showLabel {
|
|
adw_toggle_set_label(toggle, element.id.description)
|
|
} else {
|
|
adw_toggle_set_tooltip(toggle, element.id.description)
|
|
}
|
|
if let icon = element.icon {
|
|
adw_toggle_set_icon_name(toggle, icon.string)
|
|
}
|
|
storage.fields[Self.toggle + element.id.description] = toggle
|
|
adw_toggle_group_add(storage.opaquePointer, toggle)
|
|
}
|
|
)
|
|
storage.fields[Self.values] = values
|
|
adw_toggle_group_set_active_name(storage.opaquePointer, selection.description)
|
|
}
|
|
|
|
}
|
|
|
|
/// An item of a toggle group.
|
|
public protocol ToggleGroupItem: Identifiable where Self.ID: CustomStringConvertible {
|
|
|
|
/// The item's icon.
|
|
var icon: Icon? { get }
|
|
/// Whether to show the label in the UI (the identifier's string conversion).
|
|
///
|
|
/// Otherwise, it will be used as the tooltip.
|
|
var showLabel: Bool { get }
|
|
|
|
}
|