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 theme = theme(cx);
91
92 div()
93 .py_0p5()
94 .px_1()
95 .flex()
96 .items_center()
97 .justify_between()
98 .w_full()
99 .bg(theme.lowest.base.default.background)
100 .child(self.left_tools(view, &theme))
101 .child(self.right_tools(view, &theme))
102 }
103
104 fn left_tools(
105 &self,
106 workspace: &mut Workspace,
107 theme: &Theme,
108 ) -> impl Element<ViewState = Workspace> {
109 div()
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 }),
130 )
131 .child(ToolDivider::new())
132 .child(IconButton::new(Icon::XCircle))
133 }
134
135 fn right_tools(
136 &self,
137 workspace: &mut Workspace,
138 theme: &Theme,
139 ) -> impl Element<ViewState = Workspace> {
140 div()
141 .flex()
142 .items_center()
143 .gap_2()
144 .child(
145 div()
146 .flex()
147 .items_center()
148 .gap_1()
149 .child(Button::new("116:25"))
150 .child(
151 Button::<Workspace>::new("Rust").on_click(Arc::new(|workspace, cx| {
152 workspace.toggle_language_selector(cx);
153 })),
154 ),
155 )
156 .child(ToolDivider::new())
157 .child(
158 div()
159 .flex()
160 .items_center()
161 .gap_1()
162 .child(
163 IconButton::new(Icon::Copilot)
164 .on_click(|_, _| println!("Copilot clicked.")),
165 )
166 .child(
167 IconButton::new(Icon::Envelope)
168 .on_click(|_, _| println!("Send Feedback clicked.")),
169 ),
170 )
171 .child(ToolDivider::new())
172 .child(
173 div()
174 .flex()
175 .items_center()
176 .gap_1()
177 .child(
178 IconButton::<Workspace>::new(Icon::Terminal)
179 .when(workspace.is_terminal_open(), |this| {
180 this.color(IconColor::Accent)
181 })
182 .on_click(|workspace, cx| {
183 workspace.toggle_terminal(cx);
184 }),
185 )
186 .child(
187 IconButton::<Workspace>::new(Icon::MessageBubbles)
188 .when(workspace.is_chat_panel_open(), |this| {
189 this.color(IconColor::Accent)
190 })
191 .on_click(|workspace, cx| {
192 workspace.toggle_chat_panel(cx);
193 }),
194 )
195 .child(
196 IconButton::<Workspace>::new(Icon::Ai)
197 .when(workspace.is_assistant_panel_open(), |this| {
198 this.color(IconColor::Accent)
199 })
200 .on_click(|workspace, cx| {
201 workspace.toggle_assistant_panel(cx);
202 }),
203 ),
204 )
205 }
206}