status_bar.rs

  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}