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(Element)]
 32#[element(view_state = "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            // state_type: PhantomData,
 43            left_tools: None,
 44            right_tools: None,
 45            bottom_tools: None,
 46        }
 47    }
 48
 49    pub fn left_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
 50        self.left_tools = {
 51            let mut tools = vec![tool];
 52            tools.extend(self.left_tools.take().unwrap_or_default().tools);
 53            Some(ToolGroup {
 54                active_index,
 55                tools,
 56            })
 57        };
 58        self
 59    }
 60
 61    pub fn right_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
 62        self.right_tools = {
 63            let mut tools = vec![tool];
 64            tools.extend(self.left_tools.take().unwrap_or_default().tools);
 65            Some(ToolGroup {
 66                active_index,
 67                tools,
 68            })
 69        };
 70        self
 71    }
 72
 73    pub fn bottom_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
 74        self.bottom_tools = {
 75            let mut tools = vec![tool];
 76            tools.extend(self.left_tools.take().unwrap_or_default().tools);
 77            Some(ToolGroup {
 78                active_index,
 79                tools,
 80            })
 81        };
 82        self
 83    }
 84
 85    fn render(
 86        &mut self,
 87        view: &mut Workspace,
 88        cx: &mut ViewContext<Workspace>,
 89    ) -> impl Element<ViewState = Workspace> {
 90        let color = ThemeColor::new(cx);
 91
 92        div()
 93            .py_0p5()
 94            .px_1()
 95            .flex()
 96            .items_center()
 97            .justify_between()
 98            .w_full()
 99            .bg(color.status_bar)
100            .child(self.left_tools(view, cx))
101            .child(self.right_tools(view, cx))
102    }
103
104    fn left_tools(
105        &self,
106        workspace: &mut Workspace,
107        cx: &WindowContext,
108    ) -> impl Element<ViewState = Workspace> {
109        let color = ThemeColor::new(cx);
110
111        div()
112            .flex()
113            .items_center()
114            .gap_1()
115            .child(
116                IconButton::<Workspace>::new("project_panel", Icon::FileTree)
117                    .when(workspace.is_project_panel_open(), |this| {
118                        this.color(IconColor::Accent)
119                    })
120                    .on_click(|workspace, cx| {
121                        workspace.toggle_project_panel(cx);
122                    }),
123            )
124            .child(
125                IconButton::<Workspace>::new("collab_panel", Icon::Hash)
126                    .when(workspace.is_collab_panel_open(), |this| {
127                        this.color(IconColor::Accent)
128                    })
129                    .on_click(|workspace, cx| {
130                        workspace.toggle_collab_panel();
131                    }),
132            )
133            .child(ToolDivider::new())
134            .child(IconButton::new("diagnostics", Icon::XCircle))
135    }
136
137    fn right_tools(
138        &self,
139        workspace: &mut Workspace,
140        cx: &WindowContext,
141    ) -> impl Element<ViewState = Workspace> {
142        let color = ThemeColor::new(cx);
143
144        div()
145            .flex()
146            .items_center()
147            .gap_2()
148            .child(
149                div()
150                    .flex()
151                    .items_center()
152                    .gap_1()
153                    .child(Button::new("116:25"))
154                    .child(
155                        Button::<Workspace>::new("Rust").on_click(Arc::new(|workspace, cx| {
156                            workspace.toggle_language_selector(cx);
157                        })),
158                    ),
159            )
160            .child(ToolDivider::new())
161            .child(
162                div()
163                    .flex()
164                    .items_center()
165                    .gap_1()
166                    .child(
167                        IconButton::new("copilot", Icon::Copilot)
168                            .on_click(|_, _| println!("Copilot clicked.")),
169                    )
170                    .child(
171                        IconButton::new("envelope", Icon::Envelope)
172                            .on_click(|_, _| println!("Send Feedback clicked.")),
173                    ),
174            )
175            .child(ToolDivider::new())
176            .child(
177                div()
178                    .flex()
179                    .items_center()
180                    .gap_1()
181                    .child(
182                        IconButton::<Workspace>::new("terminal", Icon::Terminal)
183                            .when(workspace.is_terminal_open(), |this| {
184                                this.color(IconColor::Accent)
185                            })
186                            .on_click(|workspace, cx| {
187                                workspace.toggle_terminal(cx);
188                            }),
189                    )
190                    .child(
191                        IconButton::<Workspace>::new("chat_panel", Icon::MessageBubbles)
192                            .when(workspace.is_chat_panel_open(), |this| {
193                                this.color(IconColor::Accent)
194                            })
195                            .on_click(|workspace, cx| {
196                                workspace.toggle_chat_panel(cx);
197                            }),
198                    )
199                    .child(
200                        IconButton::<Workspace>::new("assistant_panel", Icon::Ai)
201                            .when(workspace.is_assistant_panel_open(), |this| {
202                                this.color(IconColor::Accent)
203                            })
204                            .on_click(|workspace, cx| {
205                                workspace.toggle_assistant_panel(cx);
206                            }),
207                    ),
208            )
209    }
210}