relm4_components/
simple_combo_box.rs1use std::fmt::Debug;
5
6use relm4::gtk::prelude::{ComboBoxExt, ComboBoxExtManual};
7use relm4::{Component, ComponentParts};
8use relm4::{ComponentSender, gtk};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct SimpleComboBox<E: ToString> {
20 pub variants: Vec<E>,
22 pub active_index: Option<usize>,
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub enum SimpleComboBoxMsg<E: ToString> {
29 UpdateData(SimpleComboBox<E>),
31 SetActiveIdx(usize),
33 #[doc(hidden)]
34 UpdateIndex(usize),
35}
36
37impl<E> Component for SimpleComboBox<E>
38where
39 E: ToString + 'static + Debug,
40{
41 type CommandOutput = ();
42 type Input = SimpleComboBoxMsg<E>;
43 type Output = usize;
44 type Init = Self;
45 type Root = gtk::ComboBoxText;
46 type Widgets = gtk::ComboBoxText;
47
48 fn init_root() -> Self::Root {
49 gtk::ComboBoxText::default()
50 }
51
52 fn init(
53 model: Self::Init,
54 widgets: Self::Root,
55 sender: ComponentSender<Self>,
56 ) -> ComponentParts<Self> {
57 model.render(&widgets);
58
59 widgets.connect_changed(move |combo_box| {
60 if let Some(active_idx) = combo_box.active() {
61 sender.input(Self::Input::UpdateIndex(active_idx as usize));
62 }
63 });
64
65 ComponentParts { model, widgets }
66 }
67
68 fn update_with_view(
69 &mut self,
70 widgets: &mut Self::Widgets,
71 input: Self::Input,
72 sender: ComponentSender<Self>,
73 _root: &Self::Root,
74 ) {
75 match input {
76 SimpleComboBoxMsg::UpdateIndex(idx) => {
77 sender.output(idx).ok();
80 self.active_index = Some(idx);
81 }
82 SimpleComboBoxMsg::SetActiveIdx(idx) => {
83 if idx < self.variants.len() {
84 self.active_index = Some(idx);
85 widgets.set_active(u32::try_from(idx).ok());
86 }
87 }
88 SimpleComboBoxMsg::UpdateData(data) => {
89 *self = data;
90 self.render(widgets);
91 }
92 }
93 }
94}
95
96impl<E> SimpleComboBox<E>
97where
98 E: ToString,
99{
100 fn render(&self, combo_box: >k::ComboBoxText) {
101 combo_box.remove_all();
102
103 for (idx, e) in self.variants.iter().enumerate() {
104 combo_box.insert_text(idx as i32, &e.to_string());
105 }
106
107 combo_box.set_active(self.active_index.and_then(|val| u32::try_from(val).ok()));
108 }
109
110 #[must_use]
112 pub fn get_active_elem(&self) -> Option<&E> {
113 self.active_index.and_then(|idx| self.variants.get(idx))
114 }
115}