diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 5364ec77f571..eec3493389b1 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -74,6 +74,10 @@ path = "clock/main.rs" name = "clone_macro" path = "clone_macro/main.rs" +[[bin]] +name = "combobox_liststore" +path = "combobox_liststore/main.rs" + [[bin]] name = "communication_thread" path = "communication_thread/main.rs" diff --git a/examples/combobox_liststore/README.md b/examples/combobox_liststore/README.md new file mode 100644 index 000000000000..75bde137cde7 --- /dev/null +++ b/examples/combobox_liststore/README.md @@ -0,0 +1,11 @@ +# Combobox liststore + +Example on how to use combobox and liststore. + +Run it by executing: + +```bash +cargo run --bin combobox_liststore +``` + +![screenshot](screenshot.png) \ No newline at end of file diff --git a/examples/combobox_liststore/main.rs b/examples/combobox_liststore/main.rs new file mode 100644 index 000000000000..cb5331146518 --- /dev/null +++ b/examples/combobox_liststore/main.rs @@ -0,0 +1,100 @@ +use glib::clone; +use gtk::{ + prelude::*, CellRendererText, CellRendererToggle, ComboBox, Entry, ListStore, TreeModel, +}; +use std::{cell::RefCell, rc::Rc}; + +fn build_ui(application: >k::Application) { + let window = gtk::ApplicationWindow::new(application); + window.set_title("First GTK+ Program"); + window.set_border_width(10); + window.set_position(gtk::WindowPosition::Center); + window.set_default_size(350, 70); + + let combobox = gtk::ComboBox::new(); + let renderer = CellRendererToggle::new(); + combobox.pack_start(&renderer, true); + combobox.add_attribute(&renderer, "active", 0); + + let renderer = CellRendererText::new(); + combobox.pack_start(&renderer, true); + combobox.add_attribute(&renderer, "text", 1); + combobox.set_entry_text_column(1); + + let model = gtk::ListStore::new(&[glib::Type::BOOL, glib::Type::STRING]); + let data: [(u32, &dyn ToValue); 2] = [(0, &true), (1, &"data1")]; + model.insert_with_values(Some(0), &data); + let data: [(u32, &dyn ToValue); 2] = [(0, &false), (1, &"date2")]; + model.insert_with_values(Some(1), &data); + let data: [(u32, &dyn ToValue); 2] = [(0, &false), (1, &"date3")]; + model.insert_with_values(Some(2), &data); + + combobox.set_model(Some(&model)); + window.add(&combobox); + let entry = gtk::Entry::new(); + entry.set_editable(false); + combobox.add(&entry); + + combobox.connect_changed(clone!( + @weak entry => move |cb| { + let model = cb.property::("model"); + let store = model.dynamic_cast_ref::().unwrap(); + if let Some(iter) = cb.active_iter() { + let value = store.value(&iter, 0).get::().unwrap(); + store.set(&iter, &[(0, &!value)]); + } + update_entry(&entry, cb); + cb.set_active_iter(None); + })); + combobox.connect_map(move |cb| update_entry(&entry, cb)); + window.show_all(); +} + +fn for_each(cb: >k::ComboBox, f: F) { + let model = cb.property::("model"); + if let Some(iter) = model.iter_first() { + let store = model.dynamic_cast_ref::().unwrap(); + + loop { + f(cb, &iter, store); + #[cfg(debug_assertions)] + { + if !store.iter_is_valid(&iter) { + unreachable!("iter is not valid: Don't remove iter in for_each.") + } + } + + if !model.iter_next(&iter) { + break; + } + } + } +} + +fn update_entry(entry: &Entry, cb: &ComboBox) { + entry.set_text(""); + let vec_string: Vec = Default::default(); + let vec_string = Rc::new(RefCell::new(vec_string)); + for_each( + cb, + clone!( + @weak vec_string, => move |_, iter, store| { + if store.value(iter, 0).get::().unwrap() { + let value = store.value(iter, 1).get::().unwrap(); + vec_string.borrow_mut().push(value); + } + }), + ); + entry.set_text(vec_string.borrow().join(", ").as_str()); +} + +fn main() { + let application = gtk::Application::new( + Some("com.github.gtk-rs.examples.combobox_liststore"), + Default::default(), + ); + + application.connect_activate(build_ui); + + application.run(); +} diff --git a/examples/combobox_liststore/screenshot.png b/examples/combobox_liststore/screenshot.png new file mode 100644 index 000000000000..8275f87101ad Binary files /dev/null and b/examples/combobox_liststore/screenshot.png differ