use std::collections::HashMap;
pub struct ActionItem {
pub key: String,
pub label: String,
pub tooltip: String,
pub enabled: bool,
}
impl ActionItem {
pub fn new(key: impl Into<String>, label: impl Into<String>, tooltip: impl Into<String>) -> Self {
Self {
key: key.into(),
label: label.into(),
tooltip: tooltip.into(),
enabled: true,
}
}
pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
}
pub fn action_rail(
ui: &mut egui::Ui,
title: Option<&str>,
subtitle: Option<&str>,
items: &[ActionItem],
hits: &mut HashMap<String, egui::Rect>,
) -> Option<String> {
if items.is_empty() {
return None;
}
let font = egui::TextStyle::Button.resolve(ui.style());
let measure = |ui: &egui::Ui, text: &str| -> f32 {
ui.ctx().fonts_mut(|f| {
f.layout_no_wrap(text.to_owned(), font.clone(), egui::Color32::PLACEHOLDER)
.size()
.x
})
};
let icon_w = ui.text_style_height(&egui::TextStyle::Body);
let mut widest = 0.0f32;
for item in items {
let (icon, rest) = crate::icon_text::split_caption(&item.label);
let text_w = measure(ui, rest);
widest = widest.max(if icon.is_some() {
text_w + icon_w + ui.spacing().item_spacing.x
} else {
text_w
});
}
let col_w = widest + 2.0 * ui.spacing().button_padding.x;
ui.set_width(col_w.max(1.0));
if let Some(title) = title {
ui.label(egui::RichText::new(title).strong());
}
if let Some(subtitle) = subtitle {
ui.label(egui::RichText::new(subtitle).weak().small());
}
ui.add_space(2.0);
let full = ui.available_width();
let h = ui.spacing().interact_size.y;
let mut clicked = None;
for item in items {
let resp = ui
.add_enabled_ui(item.enabled, |ui| {
let button = crate::icon_text::icon_button(ui, &item.label);
ui.add_sized([full, h], button)
})
.inner
.on_hover_text(&item.tooltip);
hits.insert(item.key.clone(), resp.rect);
if resp.clicked() {
clicked = Some(item.key.clone());
}
}
clicked
}