status_bar.rs

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