1use std::marker::PhantomData;
2
3use crate::prelude::*;
4use crate::theme::{theme, Theme};
5use crate::{Icon, IconButton, IconColor, ToolDivider};
6
7#[derive(Default, PartialEq)]
8pub enum Tool {
9 #[default]
10 ProjectPanel,
11 CollaborationPanel,
12 Terminal,
13 Assistant,
14 Feedback,
15 Diagnostics,
16}
17
18struct ToolGroup {
19 active_index: Option<usize>,
20 tools: Vec<Tool>,
21}
22
23impl Default for ToolGroup {
24 fn default() -> Self {
25 ToolGroup {
26 active_index: None,
27 tools: vec![],
28 }
29 }
30}
31
32#[derive(Element)]
33pub struct StatusBar<S: 'static + Send + Sync> {
34 state_type: PhantomData<S>,
35 left_tools: Option<ToolGroup>,
36 right_tools: Option<ToolGroup>,
37 bottom_tools: Option<ToolGroup>,
38}
39
40impl<S: 'static + Send + Sync> StatusBar<S> {
41 pub fn new() -> Self {
42 Self {
43 state_type: PhantomData,
44 left_tools: None,
45 right_tools: None,
46 bottom_tools: None,
47 }
48 }
49
50 pub fn left_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
51 self.left_tools = {
52 let mut tools = vec![tool];
53 tools.extend(self.left_tools.take().unwrap_or_default().tools);
54 Some(ToolGroup {
55 active_index,
56 tools,
57 })
58 };
59 self
60 }
61
62 pub fn right_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
63 self.right_tools = {
64 let mut tools = vec![tool];
65 tools.extend(self.left_tools.take().unwrap_or_default().tools);
66 Some(ToolGroup {
67 active_index,
68 tools,
69 })
70 };
71 self
72 }
73
74 pub fn bottom_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
75 self.bottom_tools = {
76 let mut tools = vec![tool];
77 tools.extend(self.left_tools.take().unwrap_or_default().tools);
78 Some(ToolGroup {
79 active_index,
80 tools,
81 })
82 };
83 self
84 }
85
86 fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
87 let theme = theme(cx);
88
89 div()
90 .py_0p5()
91 .px_1()
92 .flex()
93 .items_center()
94 .justify_between()
95 .w_full()
96 .fill(theme.lowest.base.default.background)
97 .child(self.left_tools(&theme))
98 .child(self.right_tools(&theme))
99 }
100
101 fn left_tools(&self, theme: &Theme) -> impl Element<State = S> {
102 div()
103 .flex()
104 .items_center()
105 .gap_1()
106 .child(IconButton::new(Icon::FileTree).color(IconColor::Accent))
107 .child(IconButton::new(Icon::Hash))
108 .child(ToolDivider::new())
109 .child(IconButton::new(Icon::XCircle))
110 }
111
112 fn right_tools(&self, theme: &Theme) -> impl Element<State = S> {
113 div()
114 .flex()
115 .items_center()
116 .gap_2()
117 .child(
118 div()
119 .flex()
120 .items_center()
121 .gap_1()
122 // .child(Button::new("116:25"))
123 // .child(Button::new("Rust")),
124 )
125 .child(ToolDivider::new())
126 .child(
127 div()
128 .flex()
129 .items_center()
130 .gap_1()
131 .child(IconButton::new(Icon::Copilot))
132 .child(IconButton::new(Icon::Envelope)),
133 )
134 .child(ToolDivider::new())
135 .child(
136 div()
137 .flex()
138 .items_center()
139 .gap_1()
140 .child(IconButton::new(Icon::Terminal))
141 .child(IconButton::new(Icon::MessageBubbles))
142 .child(IconButton::new(Icon::Ai)),
143 )
144 }
145}