1use std::sync::Arc;
2
3use crate::{get_workspace_state, Button, Icon, IconButton, IconColor, ToolDivider};
4use crate::{prelude::*, 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 theme = theme(cx);
91
92 div()
93 .py_0p5()
94 .px_1()
95 .flex()
96 .items_center()
97 .justify_between()
98 .w_full()
99 .fill(theme.lowest.base.default.background)
100 .child(self.left_tools(view, &theme))
101 .child(self.right_tools(&theme))
102 }
103
104 fn left_tools(
105 &self,
106 workspace: &mut Workspace,
107 theme: &Theme,
108 ) -> impl Element<ViewState = Workspace> {
109 div::<Workspace>()
110 .flex()
111 .items_center()
112 .gap_1()
113 .child(
114 IconButton::<Workspace>::new(Icon::FileTree)
115 .when(workspace.is_project_panel_open(), |this| {
116 this.color(IconColor::Accent)
117 })
118 .on_click(|workspace, cx| {
119 workspace.toggle_project_panel(cx);
120 }),
121 )
122 .child(
123 IconButton::<Workspace>::new(Icon::Hash)
124 .when(workspace.is_collab_panel_open(), |this| {
125 this.color(IconColor::Accent)
126 })
127 .on_click(|workspace, cx| {
128 workspace.toggle_collab_panel();
129 cx.notify();
130 }),
131 )
132 .child(ToolDivider::new())
133 .child(IconButton::new(Icon::XCircle))
134 }
135
136 fn right_tools(&self, theme: &Theme) -> impl Element<ViewState = Workspace> {
137 let workspace_state = get_workspace_state();
138
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(Button::new("Rust").on_click(Arc::new(|_, cx| {
150 workspace_state.toggle_language_selector();
151 cx.notify();
152 }))),
153 )
154 .child(ToolDivider::new())
155 .child(
156 div()
157 .flex()
158 .items_center()
159 .gap_1()
160 .child(
161 IconButton::new(Icon::Copilot)
162 .on_click(|_, _| println!("Copilot clicked.")),
163 )
164 .child(
165 IconButton::new(Icon::Envelope)
166 .on_click(|_, _| println!("Send Feedback clicked.")),
167 ),
168 )
169 .child(ToolDivider::new())
170 .child(
171 div()
172 .flex()
173 .items_center()
174 .gap_1()
175 .child(
176 IconButton::new(Icon::Terminal)
177 .when(workspace_state.is_terminal_open(), |this| {
178 this.color(IconColor::Accent)
179 })
180 .on_click(|_, cx| {
181 workspace_state.toggle_terminal();
182 cx.notify();
183 }),
184 )
185 .child(
186 IconButton::new(Icon::MessageBubbles)
187 .when(workspace_state.is_chat_panel_open(), |this| {
188 this.color(IconColor::Accent)
189 })
190 .on_click(|_, cx| {
191 workspace_state.toggle_chat_panel();
192 cx.notify();
193 }),
194 )
195 .child(
196 IconButton::new(Icon::Ai)
197 .when(workspace_state.is_assistant_panel_open(), |this| {
198 this.color(IconColor::Accent)
199 })
200 .on_click(|_, cx| {
201 workspace_state.toggle_assistant_panel();
202 cx.notify();
203 }),
204 ),
205 )
206 }
207}