1use std::marker::PhantomData;
2
3use crate::prelude::*;
4use crate::{Button, ClickHandler, Icon, IconButton, IconColor, ToolDivider};
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)]
32pub struct StatusBar<S: 'static + Send + Sync + Clone> {
33 state_type: PhantomData<S>,
34 left_tools: Option<ToolGroup>,
35 right_tools: Option<ToolGroup>,
36 bottom_tools: Option<ToolGroup>,
37 on_select_language: ClickHandler<S>,
38}
39
40impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
41 pub fn new(on_select_language: ClickHandler<S>) -> Self {
42 Self {
43 state_type: PhantomData,
44 left_tools: None,
45 right_tools: None,
46 bottom_tools: None,
47 on_select_language,
48 }
49 }
50
51 pub fn left_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
52 self.left_tools = {
53 let mut tools = vec![tool];
54 tools.extend(self.left_tools.take().unwrap_or_default().tools);
55 Some(ToolGroup {
56 active_index,
57 tools,
58 })
59 };
60 self
61 }
62
63 pub fn right_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
64 self.right_tools = {
65 let mut tools = vec![tool];
66 tools.extend(self.left_tools.take().unwrap_or_default().tools);
67 Some(ToolGroup {
68 active_index,
69 tools,
70 })
71 };
72 self
73 }
74
75 pub fn bottom_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
76 self.bottom_tools = {
77 let mut tools = vec![tool];
78 tools.extend(self.left_tools.take().unwrap_or_default().tools);
79 Some(ToolGroup {
80 active_index,
81 tools,
82 })
83 };
84 self
85 }
86
87 fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
88 let theme = theme(cx);
89
90 div()
91 .py_0p5()
92 .px_1()
93 .flex()
94 .items_center()
95 .justify_between()
96 .w_full()
97 .fill(theme.lowest.base.default.background)
98 .child(self.left_tools(&theme))
99 .child(self.right_tools(&theme))
100 }
101
102 fn left_tools(&self, theme: &Theme) -> impl Element<State = S> {
103 div()
104 .flex()
105 .items_center()
106 .gap_1()
107 .child(IconButton::new(Icon::FileTree).color(IconColor::Accent))
108 .child(IconButton::new(Icon::Hash))
109 .child(ToolDivider::new())
110 .child(IconButton::new(Icon::XCircle))
111 }
112
113 fn right_tools(&self, theme: &Theme) -> impl Element<State = S> {
114 div()
115 .flex()
116 .items_center()
117 .gap_2()
118 .child(
119 div()
120 .flex()
121 .items_center()
122 .gap_1()
123 .child(Button::new("116:25"))
124 .child(Button::new("Rust").on_click(self.on_select_language.clone())),
125 )
126 .child(ToolDivider::new())
127 .child(
128 div()
129 .flex()
130 .items_center()
131 .gap_1()
132 .child(
133 IconButton::new(Icon::Copilot)
134 .on_click(|_, _| println!("Copilot clicked.")),
135 )
136 .child(
137 IconButton::new(Icon::Envelope)
138 .on_click(|_, _| println!("Send Feedback clicked.")),
139 ),
140 )
141 .child(ToolDivider::new())
142 .child(
143 div()
144 .flex()
145 .items_center()
146 .gap_1()
147 .child(IconButton::new(Icon::Terminal))
148 .child(
149 IconButton::new(Icon::MessageBubbles)
150 .on_click(|_, _| println!("Chat Panel clicked.")),
151 )
152 .child(IconButton::new(Icon::Ai)),
153 )
154 }
155}