gpui_component/setting/
group.rs1use gpui::{
2 App, IntoElement, ParentElement as _, SharedString, StyleRefinement, Styled, Window,
3 prelude::FluentBuilder as _,
4};
5
6use crate::{
7 ActiveTheme, StyledExt,
8 group_box::{GroupBox, GroupBoxVariants},
9 label::Label,
10 setting::{RenderOptions, SettingItem},
11 v_flex,
12};
13
14#[derive(Clone)]
16pub struct SettingGroup {
17 style: StyleRefinement,
18
19 pub(super) title: Option<SharedString>,
20 pub(super) description: Option<SharedString>,
21 pub(super) items: Vec<SettingItem>,
22}
23
24impl Styled for SettingGroup {
25 fn style(&mut self) -> &mut StyleRefinement {
26 &mut self.style
27 }
28}
29
30impl SettingGroup {
31 pub fn new() -> Self {
33 Self {
34 style: StyleRefinement::default(),
35 title: None,
36 description: None,
37 items: Vec::new(),
38 }
39 }
40
41 pub fn title(mut self, title: impl Into<SharedString>) -> Self {
43 self.title = Some(title.into());
44 self
45 }
46
47 pub fn description(mut self, description: impl Into<SharedString>) -> Self {
49 self.description = Some(description.into());
50 self
51 }
52
53 pub fn item(mut self, item: SettingItem) -> Self {
55 self.items.push(item);
56 self
57 }
58
59 pub fn items<I>(mut self, items: I) -> Self
61 where
62 I: IntoIterator<Item = SettingItem>,
63 {
64 self.items.extend(items);
65 self
66 }
67
68 pub(super) fn is_match(&self, query: &str) -> bool {
70 self.items.iter().any(|item| item.is_match(query))
71 }
72
73 pub(super) fn is_resettable(&self, cx: &App) -> bool {
74 self.items.iter().any(|item| item.is_resettable(cx))
75 }
76
77 pub(crate) fn render(
78 self,
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-{}", options.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(
103 &RenderOptions {
104 item_ix,
105 ..*options
106 },
107 window,
108 cx,
109 ))
110 } else {
111 None
112 }
113 }))
114 .refine_style(&self.style)
115 }
116
117 pub(crate) fn reset(&self, window: &mut Window, cx: &mut App) {
118 for item in &self.items {
119 item.reset(window, cx);
120 }
121 }
122}