status_bar.rs

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