store dropdown item keys in gobject properties to prevent selection mismatch

This commit is contained in:
yggverse 2024-11-17 18:38:07 +02:00
parent 14c31734fd
commit 36bfc30664
2 changed files with 47 additions and 30 deletions

View File

@ -17,9 +17,9 @@ impl Form {
// Constructors // Constructors
/// Create new `Self` /// Create new `Self`
pub fn new(list_options: Vec<(Option<i64>, String, bool)>) -> Self { pub fn new(items: Vec<(Option<i64>, String, bool)>) -> Self {
// Init components // Init components
let list = List::new(&list_options); let list = List::new();
let name = Name::new(); let name = Name::new();
// Init main container // Init main container
@ -28,17 +28,6 @@ impl Form {
gobject.append(list.gobject()); gobject.append(list.gobject());
gobject.append(name.gobject()); gobject.append(name.gobject());
// Init events
list.gobject().connect_selected_notify(move |this| {
// Get selection ID from vector @TODO use GObject storage instead
// https://gtk-rs.org/gtk4-rs/stable/latest/book/list_widgets.html
match list_options.get(this.selected() as usize) {
// Hide name entry on existing identity selected
Some((id, _, _)) => name.gobject().set_visible(id.is_none()),
None => todo!(),
}
});
// Return activated `Self` // Return activated `Self`
Self { gobject } Self { gobject }
} }

View File

@ -1,35 +1,63 @@
use gtk::{DropDown, StringList}; use gtk::{gio::ListStore, prelude::ObjectExt, DropDown, Label};
const PROPERTY_KEY_NAME: &str = "key"; // Store item key as GTK property
const PROPERTY_KEY_NONE_VALUE: i64 = -1; // C-type conversion for `None` values
pub struct List { pub struct List {
gobject: DropDown, gobject: DropDown,
model: ListStore,
} }
impl List { impl List {
// Constructors // Constructors
/// Create new `Self` /// Create new `Self`
pub fn new(list_options: &Vec<(Option<i64>, String, bool)>) -> Self { pub fn new() -> Self {
// Init empty list model let model = ListStore::new::<Label>();
let model = StringList::new(&[]);
// Init `GObject`
let gobject = DropDown::builder().model(&model).build(); let gobject = DropDown::builder().model(&model).build();
// Build selection list Self { model, gobject }
let mut index = 0; }
for (_key, value, is_selected) in list_options { // Actions
model.append(&value);
if *is_selected { /// Append new item with `profile_identity_gemini_id` as `key` and name as `value`
gobject.set_selected(index); pub fn append(&self, key: Option<i64>, value: &str) {
// Create new label for item
let item = Label::new(Some(value));
// Store key as property
item.set_property(
PROPERTY_KEY_NAME,
match key {
Some(key) => key,
None => PROPERTY_KEY_NONE_VALUE,
},
);
// Set value as label
item.set_label(value);
// Append formatted record
self.model.append(&item);
}
/// Get selected `key` or panic on selection not found
/// * return `None` if current selection key match `PROPERTY_KEY_NONE_VALUE`
pub fn selected(&self) -> Option<i64> {
match self.gobject.selected_item() {
Some(gobject) => {
// Convert back from C-based GObject type
let key = gobject.property::<i64>(PROPERTY_KEY_NAME);
if key == PROPERTY_KEY_NONE_VALUE {
None
} else {
Some(key)
}
} }
None => panic!(),
index += 1;
} }
// Done
Self { gobject }
} }
// Getters // Getters