use gpui::{
App, IntoElement, ParentElement as _, SharedString, StyleRefinement, Styled, Window,
prelude::FluentBuilder as _,
};
use crate::{
ActiveTheme, StyledExt,
group_box::{GroupBox, GroupBoxVariants},
label::Label,
setting::{RenderOptions, SettingItem},
v_flex,
};
#[derive(Clone)]
pub struct SettingGroup {
style: StyleRefinement,
pub(super) title: Option<SharedString>,
pub(super) description: Option<SharedString>,
pub(super) items: Vec<SettingItem>,
}
impl Styled for SettingGroup {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.style
}
}
impl SettingGroup {
pub fn new() -> Self {
Self {
style: StyleRefinement::default(),
title: None,
description: None,
items: Vec::new(),
}
}
pub fn title(mut self, title: impl Into<SharedString>) -> Self {
self.title = Some(title.into());
self
}
pub fn description(mut self, description: impl Into<SharedString>) -> Self {
self.description = Some(description.into());
self
}
pub fn item(mut self, item: SettingItem) -> Self {
self.items.push(item);
self
}
pub fn items<I>(mut self, items: I) -> Self
where
I: IntoIterator<Item = SettingItem>,
{
self.items.extend(items);
self
}
pub(super) fn is_match(&self, query: &str) -> bool {
self.items.iter().any(|item| item.is_match(query))
}
pub(super) fn is_resettable(&self, cx: &App) -> bool {
self.items.iter().any(|item| item.is_resettable(cx))
}
pub(crate) fn render(
self,
query: &str,
options: &RenderOptions,
window: &mut Window,
cx: &mut App,
) -> impl IntoElement {
GroupBox::new()
.id(SharedString::from(format!("group-{}", options.group_ix)))
.with_variant(options.group_variant)
.when_some(self.title.clone(), |this, title| {
this.title(v_flex().gap_1().child(title).when_some(
self.description.clone(),
|this, description| {
this.child(
Label::new(description)
.text_sm()
.text_color(cx.theme().muted_foreground),
)
},
))
})
.gap_4()
.children(self.items.iter().enumerate().filter_map(|(item_ix, item)| {
if item.is_match(&query) {
Some(item.clone().render_item(
&RenderOptions {
item_ix,
..*options
},
window,
cx,
))
} else {
None
}
}))
.refine_style(&self.style)
}
pub(crate) fn reset(&self, window: &mut Window, cx: &mut App) {
for item in &self.items {
item.reset(window, cx);
}
}
}