disclosure.rs

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