disclosure.rs

 1use std::sync::Arc;
 2
 3use gpui::{ClickEvent, CursorStyle};
 4
 5use crate::{Color, IconButton, IconButtonShape, IconName, IconSize, prelude::*};
 6
 7#[derive(IntoElement)]
 8pub struct Disclosure {
 9    id: ElementId,
10    is_open: bool,
11    selected: bool,
12    on_toggle: Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
13    cursor_style: CursorStyle,
14    opened_icon: IconName,
15    closed_icon: IconName,
16}
17
18impl Disclosure {
19    pub fn new(id: impl Into<ElementId>, is_open: bool) -> Self {
20        Self {
21            id: id.into(),
22            is_open,
23            selected: false,
24            on_toggle: None,
25            cursor_style: CursorStyle::PointingHand,
26            opened_icon: IconName::ChevronDown,
27            closed_icon: IconName::ChevronRight,
28        }
29    }
30
31    pub fn on_toggle(
32        mut self,
33        handler: impl Into<Option<Arc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>>,
34    ) -> Self {
35        self.on_toggle = handler.into();
36        self
37    }
38
39    pub fn opened_icon(mut self, icon: IconName) -> Self {
40        self.opened_icon = icon;
41        self
42    }
43
44    pub fn closed_icon(mut self, icon: IconName) -> Self {
45        self.closed_icon = icon;
46        self
47    }
48}
49
50impl Toggleable for Disclosure {
51    fn toggle_state(mut self, selected: bool) -> Self {
52        self.selected = selected;
53        self
54    }
55}
56
57impl Clickable for Disclosure {
58    fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static) -> Self {
59        self.on_toggle = Some(Arc::new(handler));
60        self
61    }
62
63    fn cursor_style(mut self, cursor_style: gpui::CursorStyle) -> Self {
64        self.cursor_style = cursor_style;
65        self
66    }
67}
68
69impl RenderOnce for Disclosure {
70    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
71        IconButton::new(
72            self.id,
73            match self.is_open {
74                true => self.opened_icon,
75                false => self.closed_icon,
76            },
77        )
78        .shape(IconButtonShape::Square)
79        .icon_color(Color::Muted)
80        .icon_size(IconSize::Small)
81        .toggle_state(self.selected)
82        .when_some(self.on_toggle, move |this, on_toggle| {
83            this.on_click(move |event, window, cx| on_toggle(event, window, cx))
84        })
85    }
86}