status_bar.rs

  1use std::marker::PhantomData;
  2use std::sync::Arc;
  3
  4use crate::prelude::*;
  5use crate::{get_workspace_state, Button, Icon, IconButton, IconColor, ToolDivider};
  6
  7#[derive(Default, PartialEq)]
  8pub enum Tool {
  9    #[default]
 10    ProjectPanel,
 11    CollaborationPanel,
 12    Terminal,
 13    Assistant,
 14    Feedback,
 15    Diagnostics,
 16}
 17
 18struct ToolGroup {
 19    active_index: Option<usize>,
 20    tools: Vec<Tool>,
 21}
 22
 23impl Default for ToolGroup {
 24    fn default() -> Self {
 25        ToolGroup {
 26            active_index: None,
 27            tools: vec![],
 28        }
 29    }
 30}
 31
 32#[derive(Element)]
 33pub struct StatusBar<S: 'static + Send + Sync + Clone> {
 34    state_type: PhantomData<S>,
 35    left_tools: Option<ToolGroup>,
 36    right_tools: Option<ToolGroup>,
 37    bottom_tools: Option<ToolGroup>,
 38}
 39
 40impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
 41    pub fn new() -> Self {
 42        Self {
 43            state_type: PhantomData,
 44            left_tools: None,
 45            right_tools: None,
 46            bottom_tools: None,
 47        }
 48    }
 49
 50    pub fn left_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
 51        self.left_tools = {
 52            let mut tools = vec![tool];
 53            tools.extend(self.left_tools.take().unwrap_or_default().tools);
 54            Some(ToolGroup {
 55                active_index,
 56                tools,
 57            })
 58        };
 59        self
 60    }
 61
 62    pub fn right_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
 63        self.right_tools = {
 64            let mut tools = vec![tool];
 65            tools.extend(self.left_tools.take().unwrap_or_default().tools);
 66            Some(ToolGroup {
 67                active_index,
 68                tools,
 69            })
 70        };
 71        self
 72    }
 73
 74    pub fn bottom_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
 75        self.bottom_tools = {
 76            let mut tools = vec![tool];
 77            tools.extend(self.left_tools.take().unwrap_or_default().tools);
 78            Some(ToolGroup {
 79                active_index,
 80                tools,
 81            })
 82        };
 83        self
 84    }
 85
 86    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 87        let theme = theme(cx);
 88
 89        div()
 90            .py_0p5()
 91            .px_1()
 92            .flex()
 93            .items_center()
 94            .justify_between()
 95            .w_full()
 96            .fill(theme.lowest.base.default.background)
 97            .child(self.left_tools(&theme))
 98            .child(self.right_tools(&theme))
 99    }
100
101    fn left_tools(&self, theme: &Theme) -> impl Element<ViewState = S> {
102        let workspace_state = get_workspace_state();
103
104        div()
105            .flex()
106            .items_center()
107            .gap_1()
108            .child(
109                IconButton::new(Icon::FileTree)
110                    .when(workspace_state.is_project_panel_open(), |this| {
111                        this.color(IconColor::Accent)
112                    })
113                    .on_click(|_, cx| {
114                        workspace_state.toggle_project_panel();
115                        cx.notify();
116                    }),
117            )
118            .child(
119                IconButton::new(Icon::Hash)
120                    .when(workspace_state.is_collab_panel_open(), |this| {
121                        this.color(IconColor::Accent)
122                    })
123                    .on_click(|_, cx| {
124                        workspace_state.toggle_collab_panel();
125                        cx.notify();
126                    }),
127            )
128            .child(ToolDivider::new())
129            .child(IconButton::new(Icon::XCircle))
130    }
131
132    fn right_tools(&self, theme: &Theme) -> impl Element<ViewState = S> {
133        let workspace_state = get_workspace_state();
134
135        div()
136            .flex()
137            .items_center()
138            .gap_2()
139            .child(
140                div()
141                    .flex()
142                    .items_center()
143                    .gap_1()
144                    .child(Button::new("116:25"))
145                    .child(Button::new("Rust").on_click(Arc::new(|_, cx| {
146                        workspace_state.toggle_language_selector();
147                        cx.notify();
148                    }))),
149            )
150            .child(ToolDivider::new())
151            .child(
152                div()
153                    .flex()
154                    .items_center()
155                    .gap_1()
156                    .child(
157                        IconButton::new(Icon::Copilot)
158                            .on_click(|_, _| println!("Copilot clicked.")),
159                    )
160                    .child(
161                        IconButton::new(Icon::Envelope)
162                            .on_click(|_, _| println!("Send Feedback clicked.")),
163                    ),
164            )
165            .child(ToolDivider::new())
166            .child(
167                div()
168                    .flex()
169                    .items_center()
170                    .gap_1()
171                    .child(
172                        IconButton::new(Icon::Terminal)
173                            .when(workspace_state.is_terminal_open(), |this| {
174                                this.color(IconColor::Accent)
175                            })
176                            .on_click(|_, cx| {
177                                workspace_state.toggle_terminal();
178                                cx.notify();
179                            }),
180                    )
181                    .child(
182                        IconButton::new(Icon::MessageBubbles)
183                            .when(workspace_state.is_chat_panel_open(), |this| {
184                                this.color(IconColor::Accent)
185                            })
186                            .on_click(|_, cx| {
187                                workspace_state.toggle_chat_panel();
188                                cx.notify();
189                            }),
190                    )
191                    .child(
192                        IconButton::new(Icon::Ai)
193                            .when(workspace_state.is_assistant_panel_open(), |this| {
194                                this.color(IconColor::Accent)
195                            })
196                            .on_click(|_, cx| {
197                                workspace_state.toggle_assistant_panel();
198                                cx.notify();
199                            }),
200                    ),
201            )
202    }
203}