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}