use egui::{FontId, Stroke, TextStyle, Ui};
use super::corner;
use crate::{Icon, RADIUS, SPACING, palette_of};
pub struct Accordion<'a> {
title: &'a str,
subtitle: Option<&'a str>,
icon: Option<Icon>,
open_default: bool,
id: egui::Id,
}
impl<'a> Accordion<'a> {
pub fn new(title: &'a str) -> Self {
Self {
title,
subtitle: None,
icon: None,
open_default: false,
id: egui::Id::new(("sauge_accordion", title)),
}
}
pub fn subtitle(mut self, subtitle: &'a str) -> Self {
self.subtitle = Some(subtitle);
self
}
pub fn icon(mut self, icon: Icon) -> Self {
self.icon = Some(icon);
self
}
pub fn open(mut self) -> Self {
self.open_default = true;
self
}
pub fn id(mut self, id: egui::Id) -> Self {
self.id = id;
self
}
pub fn show<R>(
self,
ui: &mut Ui,
body: impl FnOnce(&mut Ui) -> R,
) -> egui::CollapsingResponse<R> {
let palette = palette_of(ui.ctx());
let frame = egui::Frame::default()
.fill(palette.bg_surface)
.stroke(Stroke::new(1.0, palette.border_subtle))
.corner_radius(corner(RADIUS.md))
.inner_margin(egui::Margin::symmetric(SPACING.s3 as i8, SPACING.s2 as i8));
let mut header = egui::CollapsingHeader::new(format_header(
self.title,
self.subtitle,
&palette,
self.icon,
))
.id_salt(self.id)
.default_open(self.open_default);
if self.icon.is_some() {
}
let mut inner: Option<egui::CollapsingResponse<R>> = None;
frame.show(ui, |ui| {
header = std::mem::replace(
&mut header,
egui::CollapsingHeader::new("placeholder").id_salt(self.id),
);
inner = Some(header.show(ui, body));
});
inner.expect("CollapsingHeader::show always runs")
}
}
fn format_header(
title: &str,
subtitle: Option<&str>,
palette: &crate::Palette,
icon: Option<Icon>,
) -> egui::WidgetText {
use egui::text::LayoutJob;
let mut job = LayoutJob::default();
if let Some(icon) = icon
&& let Some(cp) = icon.glyph()
{
job.append(
cp,
0.0,
egui::TextFormat {
font_id: FontId::new(15.0, egui::FontFamily::Proportional),
color: palette.text_secondary,
..Default::default()
},
);
job.append(
" ",
0.0,
egui::TextFormat {
font_id: FontId::new(15.0, egui::FontFamily::Proportional),
color: palette.text_secondary,
..Default::default()
},
);
}
job.append(
title,
0.0,
egui::TextFormat {
font_id: FontId::new(15.0, egui::FontFamily::Proportional),
color: palette.text_primary,
..Default::default()
},
);
if let Some(sub) = subtitle {
job.append(
" ",
0.0,
egui::TextFormat {
font_id: FontId::new(15.0, egui::FontFamily::Proportional),
color: palette.text_secondary,
..Default::default()
},
);
job.append(
sub,
0.0,
egui::TextFormat {
font_id: FontId::new(12.0, egui::FontFamily::Proportional),
color: palette.text_secondary,
..Default::default()
},
);
}
let _ = TextStyle::Body;
egui::WidgetText::LayoutJob(job.into())
}