// // 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( _ title: String, selection: Binding, values: [Element] ) where Element: Identifiable, Element: CustomStringConvertible { self = self.title(title) self = self.selected(.init { .init(values.firstIndex { $0.id == selection.wrappedValue } ?? 0) } set: { index in if let id = values[safe: .init(index)]?.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()) Self.updateContent(storage: storage, values: values, element: Element.self) } updateFunctions.append { storage, _, _ in Self.updateContent(storage: storage, values: values, element: Element.self) } } /// Update the combo row's content. /// - Parameters: /// - storage: The view storage. /// - values: The elements. /// - element: The type of the elements. static func updateContent( storage: ViewStorage, values: [Element], element: Element.Type ) where Element: Identifiable, Element: CustomStringConvertible { if let list = storage.fields[Self.stringList] as? OpaquePointer { let old = storage.fields[Self.values] as? [Element] ?? [] old.identifiableTransform( to: values, functions: .init { index in gtk_string_list_remove(list, .init(index)) } insert: { _, element in gtk_string_list_append(list, element.description) } ) storage.fields[Self.values] = values } } }