1use std::marker::PhantomData;
2
3use crate::prelude::*;
4use crate::{Button, 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}
38
39impl<S: 'static + Send + Sync + Clone> StatusBar<S> {
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(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
86 let theme = theme(cx);
87
88 div()
89 .py_0p5()
90 .px_1()
91 .flex()
92 .items_center()
93 .justify_between()
94 .w_full()
95 .fill(theme.lowest.base.default.background)
96 .child(self.left_tools(&theme))
97 .child(self.right_tools(&theme))
98 }
99
100 fn left_tools(&self, theme: &Theme) -> impl Element<State = S> {
101 div()
102 .flex()
103 .items_center()
104 .gap_1()
105 .child(IconButton::new(Icon::FileTree).color(IconColor::Accent))
106 .child(IconButton::new(Icon::Hash))
107 .child(ToolDivider::new())
108 .child(IconButton::new(Icon::XCircle))
109 }
110
111 fn right_tools(&self, theme: &Theme) -> impl Element<State = S> {
112 div()
113 .flex()
114 .items_center()
115 .gap_2()
116 .child(
117 div()
118 .flex()
119 .items_center()
120 .gap_1()
121 .child(Button::new("116:25"))
122 .child(Button::new("Rust")),
123 )
124 .child(ToolDivider::new())
125 .child(
126 div()
127 .flex()
128 .items_center()
129 .gap_1()
130 .child(IconButton::new(Icon::Copilot))
131 .child(IconButton::new(Icon::Envelope)),
132 )
133 .child(ToolDivider::new())
134 .child(
135 div()
136 .flex()
137 .items_center()
138 .gap_1()
139 .child(IconButton::new(Icon::Terminal))
140 .child(IconButton::new(Icon::MessageBubbles))
141 .child(IconButton::new(Icon::Ai)),
142 )
143 }
144}