gpui_component/setting/
group.rs1use gpui::{
2 prelude::FluentBuilder as _, App, IntoElement, ParentElement as _, SharedString,
3 StyleRefinement, Styled, Window,
4};
5
6use crate::{
7 group_box::{GroupBox, GroupBoxVariants},
8 label::Label,
9 setting::{RenderOptions, SettingItem},
10 v_flex, ActiveTheme, StyledExt,
11};
12
13#[derive(Clone)]
15pub struct SettingGroup {
16 style: StyleRefinement,
17
18 pub(super) title: Option<SharedString>,
19 pub(super) description: Option<SharedString>,
20 pub(super) items: Vec<SettingItem>,
21}
22
23impl Styled for SettingGroup {
24 fn style(&mut self) -> &mut StyleRefinement {
25 &mut self.style
26 }
27}
28
29impl SettingGroup {
30 pub fn new() -> Self {
32 Self {
33 style: StyleRefinement::default(),
34 title: None,
35 description: None,
36 items: Vec::new(),
37 }
38 }
39
40 pub fn title(mut self, title: impl Into<SharedString>) -> Self {
42 self.title = Some(title.into());
43 self
44 }
45
46 pub fn description(mut self, description: impl Into<SharedString>) -> Self {
48 self.description = Some(description.into());
49 self
50 }
51
52 pub fn item(mut self, item: SettingItem) -> Self {
54 self.items.push(item);
55 self
56 }
57
58 pub fn items<I>(mut self, items: I) -> Self
60 where
61 I: IntoIterator<Item = SettingItem>,
62 {
63 self.items.extend(items);
64 self
65 }
66
67 pub(super) fn is_match(&self, query: &str) -> bool {
69 self.items.iter().any(|item| item.is_match(query))
70 }
71
72 pub(super) fn is_resettable(&self, cx: &App) -> bool {
73 self.items.iter().any(|item| item.is_resettable(cx))
74 }
75
76 pub(crate) fn render(
77 self,
78 group_ix: usize,
79 query: &str,
80 options: &RenderOptions,
81 window: &mut Window,
82 cx: &mut App,
83 ) -> impl IntoElement {
84 GroupBox::new()
85 .id(SharedString::from(format!("group-{}", group_ix)))
86 .with_variant(options.group_variant)
87 .when_some(self.title.clone(), |this, title| {
88 this.title(v_flex().gap_1().child(title).when_some(
89 self.description.clone(),
90 |this, description| {
91 this.child(
92 Label::new(description)
93 .text_sm()
94 .text_color(cx.theme().muted_foreground),
95 )
96 },
97 ))
98 })
99 .gap_4()
100 .children(self.items.iter().enumerate().filter_map(|(item_ix, item)| {
101 if item.is_match(&query) {
102 Some(item.clone().render_item(item_ix, options, window, cx))
103 } else {
104 None
105 }
106 }))
107 .refine_style(&self.style)
108 }
109
110 pub(crate) fn reset(&self, window: &mut Window, cx: &mut App) {
111 for item in &self.items {
112 item.reset(window, cx);
113 }
114 }
115}