use egui::{CentralPanel, Response, Ui, Widget};
use std::collections::BTreeMap;
pub(super) struct SettingsMenu<'a, S> {
selected_submenu: &'a mut String,
edit_state: &'a mut S,
submenus: BTreeMap<String, Box<dyn FnOnce(&mut Ui, &mut S) + 'a>>,
}
impl<'a, S> SettingsMenu<'a, S> {
pub(super) fn new(edit_state: &'a mut S, selected_submenu: &'a mut String) -> Self {
Self {
selected_submenu,
edit_state,
submenus: BTreeMap::default(),
}
}
pub(super) fn add_submenu(
mut self,
submenu: String,
ui_callback: impl FnOnce(&mut Ui, &mut S) + 'a,
) -> Self {
self.submenus.insert(submenu, Box::new(ui_callback));
self
}
}
impl<'a, S> Widget for SettingsMenu<'a, S> {
fn ui(mut self, ui: &mut Ui) -> Response {
debug_assert!(!self.submenus.is_empty());
egui::Panel::left("artnet_input_config")
.resizable(true)
.size_range(100.0..=200.0)
.default_size(150.0)
.show(ui, |ui| {
ui.take_available_space();
self.submenus.keys().for_each(|key| {
ui.selectable_value(self.selected_submenu, key.clone(), key);
});
});
if !self.submenus.contains_key(self.selected_submenu) {
*self.selected_submenu = self
.submenus
.keys()
.next()
.expect("settings menu must have at least one submenu")
.clone();
}
let submenu = self
.submenus
.remove(self.selected_submenu)
.expect("submenu was just confirmed to be present");
CentralPanel::default()
.show(ui, |ui| submenu(ui, self.edit_state))
.response
}
}