1use std::marker::PhantomData;
2
3use crate::theme::{theme, Theme};
4use crate::{icon_button, text_button, tool_divider};
5use gpui2::style::StyleHelpers;
6use gpui2::{elements::div, IntoElement};
7use gpui2::{Element, ParentElement, ViewContext};
8
9#[derive(Default, PartialEq)]
10pub enum Tool {
11 #[default]
12 ProjectPanel,
13 CollaborationPanel,
14 Terminal,
15 Assistant,
16 Feedback,
17 Diagnostics,
18}
19
20struct ToolGroup {
21 active_index: Option<usize>,
22 tools: Vec<Tool>,
23}
24
25impl Default for ToolGroup {
26 fn default() -> Self {
27 ToolGroup {
28 active_index: None,
29 tools: vec![],
30 }
31 }
32}
33
34#[derive(Element)]
35pub struct StatusBar<V: 'static> {
36 view_type: PhantomData<V>,
37 left_tools: Option<ToolGroup>,
38 right_tools: Option<ToolGroup>,
39 bottom_tools: Option<ToolGroup>,
40}
41
42pub fn status_bar<V: 'static>() -> StatusBar<V> {
43 StatusBar {
44 view_type: PhantomData,
45 left_tools: None,
46 right_tools: None,
47 bottom_tools: None,
48 }
49}
50
51impl<V: 'static> StatusBar<V> {
52 pub fn left_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
53 self.left_tools = {
54 let mut tools = vec![tool];
55 tools.extend(self.left_tools.take().unwrap_or_default().tools);
56 Some(ToolGroup {
57 active_index,
58 tools,
59 })
60 };
61 self
62 }
63
64 pub fn right_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
65 self.right_tools = {
66 let mut tools = vec![tool];
67 tools.extend(self.left_tools.take().unwrap_or_default().tools);
68 Some(ToolGroup {
69 active_index,
70 tools,
71 })
72 };
73 self
74 }
75
76 pub fn bottom_tool(mut self, tool: Tool, active_index: Option<usize>) -> Self {
77 self.bottom_tools = {
78 let mut tools = vec![tool];
79 tools.extend(self.left_tools.take().unwrap_or_default().tools);
80 Some(ToolGroup {
81 active_index,
82 tools,
83 })
84 };
85 self
86 }
87
88 fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
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 .fill(theme.lowest.base.default.background)
99 .child(self.left_tools(theme))
100 .child(self.right_tools(theme))
101 }
102
103 fn left_tools(&self, theme: &Theme) -> impl Element<V> {
104 div()
105 .flex()
106 .items_center()
107 .gap_1()
108 .child(icon_button("icons/project.svg"))
109 .child(icon_button("icons/hash.svg"))
110 .child(tool_divider())
111 .child(icon_button("icons/error.svg"))
112 }
113 fn right_tools(&self, theme: &Theme) -> impl Element<V> {
114 div()
115 .flex()
116 .items_center()
117 .gap_2()
118 .child(
119 div()
120 .flex()
121 .items_center()
122 .gap_1()
123 .child(text_button("116:25"))
124 .child(text_button("Rust")),
125 )
126 .child(tool_divider())
127 .child(
128 div()
129 .flex()
130 .items_center()
131 .gap_1()
132 .child(icon_button("icons/copilot.svg"))
133 .child(icon_button("icons/feedback.svg")),
134 )
135 .child(tool_divider())
136 .child(
137 div()
138 .flex()
139 .items_center()
140 .gap_1()
141 .child(icon_button("icons/terminal.svg"))
142 .child(icon_button("icons/conversations.svg"))
143 .child(icon_button("icons/ai.svg")),
144 )
145 }
146}