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}