thread_sidebar_toggle.rs

  1use gpui::{AnyView, ClickEvent};
  2use ui_macros::RegisterComponent;
  3
  4use crate::prelude::*;
  5use crate::{IconButton, IconName, Tooltip};
  6
  7#[derive(IntoElement, RegisterComponent)]
  8pub struct ThreadSidebarToggle {
  9    sidebar_selected: bool,
 10    thread_selected: bool,
 11    flipped: bool,
 12    sidebar_tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView + 'static>>,
 13    thread_tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView + 'static>>,
 14    on_sidebar_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
 15    on_thread_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
 16}
 17
 18impl ThreadSidebarToggle {
 19    pub fn new() -> Self {
 20        Self {
 21            sidebar_selected: false,
 22            thread_selected: false,
 23            flipped: false,
 24            sidebar_tooltip: None,
 25            thread_tooltip: None,
 26            on_sidebar_click: None,
 27            on_thread_click: None,
 28        }
 29    }
 30
 31    pub fn sidebar_selected(mut self, selected: bool) -> Self {
 32        self.sidebar_selected = selected;
 33        self
 34    }
 35
 36    pub fn thread_selected(mut self, selected: bool) -> Self {
 37        self.thread_selected = selected;
 38        self
 39    }
 40
 41    pub fn flipped(mut self, flipped: bool) -> Self {
 42        self.flipped = flipped;
 43        self
 44    }
 45
 46    pub fn sidebar_tooltip(
 47        mut self,
 48        tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static,
 49    ) -> Self {
 50        self.sidebar_tooltip = Some(Box::new(tooltip));
 51        self
 52    }
 53
 54    pub fn thread_tooltip(
 55        mut self,
 56        tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static,
 57    ) -> Self {
 58        self.thread_tooltip = Some(Box::new(tooltip));
 59        self
 60    }
 61
 62    pub fn on_sidebar_click(
 63        mut self,
 64        handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
 65    ) -> Self {
 66        self.on_sidebar_click = Some(Box::new(handler));
 67        self
 68    }
 69
 70    pub fn on_thread_click(
 71        mut self,
 72        handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
 73    ) -> Self {
 74        self.on_thread_click = Some(Box::new(handler));
 75        self
 76    }
 77}
 78
 79impl RenderOnce for ThreadSidebarToggle {
 80    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
 81        let sidebar_icon = match (self.sidebar_selected, self.flipped) {
 82            (true, false) => IconName::ThreadsSidebarLeftOpen,
 83            (false, false) => IconName::ThreadsSidebarLeftClosed,
 84            (true, true) => IconName::ThreadsSidebarRightOpen,
 85            (false, true) => IconName::ThreadsSidebarRightClosed,
 86        };
 87
 88        h_flex()
 89            .min_w_0()
 90            .rounded_sm()
 91            .gap_px()
 92            .border_1()
 93            .border_color(cx.theme().colors().border)
 94            .when(self.flipped, |this| this.flex_row_reverse())
 95            .child(
 96                IconButton::new("sidebar-toggle", sidebar_icon)
 97                    .icon_size(IconSize::Small)
 98                    .toggle_state(self.sidebar_selected)
 99                    .when_some(self.sidebar_tooltip, |this, tooltip| this.tooltip(tooltip))
100                    .when_some(self.on_sidebar_click, |this, handler| {
101                        this.on_click(handler)
102                    }),
103            )
104            .child(div().h_4().w_px().bg(cx.theme().colors().border))
105            .child(
106                IconButton::new("thread-toggle", IconName::Thread)
107                    .icon_size(IconSize::Small)
108                    .toggle_state(self.thread_selected)
109                    .when_some(self.thread_tooltip, |this, tooltip| this.tooltip(tooltip))
110                    .when_some(self.on_thread_click, |this, handler| this.on_click(handler)),
111            )
112    }
113}
114
115impl Component for ThreadSidebarToggle {
116    fn scope() -> ComponentScope {
117        ComponentScope::Agent
118    }
119
120    fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {
121        let container = || div().p_2().bg(cx.theme().colors().status_bar_background);
122
123        let examples = vec![
124            single_example(
125                "Both Unselected",
126                container()
127                    .child(ThreadSidebarToggle::new())
128                    .into_any_element(),
129            ),
130            single_example(
131                "Sidebar Selected",
132                container()
133                    .child(ThreadSidebarToggle::new().sidebar_selected(true))
134                    .into_any_element(),
135            ),
136            single_example(
137                "Thread Selected",
138                container()
139                    .child(ThreadSidebarToggle::new().thread_selected(true))
140                    .into_any_element(),
141            ),
142            single_example(
143                "Both Selected",
144                container()
145                    .child(
146                        ThreadSidebarToggle::new()
147                            .sidebar_selected(true)
148                            .thread_selected(true),
149                    )
150                    .into_any_element(),
151            ),
152            single_example(
153                "Flipped",
154                container()
155                    .child(
156                        ThreadSidebarToggle::new()
157                            .sidebar_selected(true)
158                            .thread_selected(true)
159                            .flipped(true),
160                    )
161                    .into_any_element(),
162            ),
163            single_example(
164                "With Tooltips",
165                container()
166                    .child(
167                        ThreadSidebarToggle::new()
168                            .sidebar_tooltip(Tooltip::text("Toggle Sidebar"))
169                            .thread_tooltip(Tooltip::text("Toggle Thread")),
170                    )
171                    .into_any_element(),
172            ),
173        ];
174
175        Some(example_group(examples).into_any_element())
176    }
177}