workspace.rs

  1use std::marker::PhantomData;
  2use std::sync::Arc;
  3
  4use chrono::DateTime;
  5use gpui3::{relative, rems, Size};
  6
  7use crate::prelude::*;
  8use crate::{
  9    hello_world_rust_editor_with_status_example, random_players_with_call_status, theme, v_stack,
 10    ChatMessage, ChatPanel, EditorPane, Livestream, Pane, PaneGroup, Panel, PanelAllowedSides,
 11    PanelSide, ProjectPanel, SplitDirection, StatusBar, Terminal, TitleBar,
 12};
 13
 14#[derive(Element)]
 15pub struct WorkspaceElement<S: 'static + Send + Sync + Clone> {
 16    state_type: PhantomData<S>,
 17    left_panel_scroll_state: ScrollState,
 18    right_panel_scroll_state: ScrollState,
 19    tab_bar_scroll_state: ScrollState,
 20    bottom_panel_scroll_state: ScrollState,
 21}
 22
 23impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
 24    pub fn new() -> Self {
 25        Self {
 26            state_type: PhantomData,
 27            left_panel_scroll_state: ScrollState::default(),
 28            right_panel_scroll_state: ScrollState::default(),
 29            tab_bar_scroll_state: ScrollState::default(),
 30            bottom_panel_scroll_state: ScrollState::default(),
 31        }
 32    }
 33
 34    pub fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
 35        let theme = theme(cx).clone();
 36
 37        let temp_size = rems(36.).into();
 38
 39        let root_group = PaneGroup::new_groups(
 40            vec![
 41                PaneGroup::new_panes(
 42                    vec![
 43                        Pane::new(
 44                            ScrollState::default(),
 45                            Size {
 46                                width: relative(1.).into(),
 47                                height: temp_size,
 48                            },
 49                            |_, payload| {
 50                                let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
 51
 52                                vec![EditorPane::new(hello_world_rust_editor_with_status_example(
 53                                    &theme,
 54                                ))
 55                                .into_any()]
 56                            },
 57                            Box::new(theme.clone()),
 58                        ),
 59                        Pane::new(
 60                            ScrollState::default(),
 61                            Size {
 62                                width: relative(1.).into(),
 63                                height: temp_size,
 64                            },
 65                            |_, _| vec![Terminal::new().into_any()],
 66                            Box::new(()),
 67                        ),
 68                    ],
 69                    SplitDirection::Vertical,
 70                ),
 71                PaneGroup::new_panes(
 72                    vec![Pane::new(
 73                        ScrollState::default(),
 74                        Size {
 75                            width: relative(1.).into(),
 76                            height: relative(1.).into(),
 77                        },
 78                        |_, payload| {
 79                            let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
 80
 81                            vec![EditorPane::new(hello_world_rust_editor_with_status_example(
 82                                &theme,
 83                            ))
 84                            .into_any()]
 85                        },
 86                        Box::new(theme.clone()),
 87                    )],
 88                    SplitDirection::Vertical,
 89                ),
 90            ],
 91            SplitDirection::Horizontal,
 92        );
 93
 94        div()
 95            .relative()
 96            .size_full()
 97            .flex()
 98            .flex_col()
 99            .font("Zed Sans Extended")
100            .gap_0()
101            .justify_start()
102            .items_start()
103            .text_color(theme.lowest.base.default.foreground)
104            .fill(theme.lowest.base.default.background)
105            .child(TitleBar::new(cx).set_livestream(Some(Livestream {
106                players: random_players_with_call_status(7),
107                channel: Some("gpui2-ui".to_string()),
108            })))
109            .child(
110                div()
111                    .flex_1()
112                    .w_full()
113                    .flex()
114                    .flex_row()
115                    .overflow_hidden()
116                    .border_t()
117                    .border_b()
118                    .border_color(theme.lowest.base.default.border)
119                    .child(
120                        Panel::new(
121                            self.left_panel_scroll_state.clone(),
122                            |_, payload| vec![ProjectPanel::new(ScrollState::default()).into_any()],
123                            Box::new(()),
124                        )
125                        .side(PanelSide::Left),
126                    )
127                    .child(
128                        v_stack()
129                            .flex_1()
130                            .h_full()
131                            .child(
132                                div()
133                                    .flex()
134                                    .flex_1()
135                                    // CSS Hack: Flex 1 has to have a set height to properly fill the space
136                                    // Or it will give you a height of 0
137                                    .h_px()
138                                    .child(root_group),
139                            )
140                            .child(
141                                Panel::new(
142                                    self.bottom_panel_scroll_state.clone(),
143                                    |_, _| vec![Terminal::new().into_any()],
144                                    Box::new(()),
145                                )
146                                .allowed_sides(PanelAllowedSides::BottomOnly)
147                                .side(PanelSide::Bottom),
148                            ),
149                    )
150                    .child(
151                        Panel::new(
152                            self.right_panel_scroll_state.clone(),
153                            |_, payload| {
154                                vec![ChatPanel::new(ScrollState::default())
155                                    .with_messages(vec![
156                                        ChatMessage::new(
157                                            "osiewicz".to_string(),
158                                            "is this thing on?".to_string(),
159                                            DateTime::parse_from_rfc3339(
160                                                "2023-09-27T15:40:52.707Z",
161                                            )
162                                            .unwrap()
163                                            .naive_local(),
164                                        ),
165                                        ChatMessage::new(
166                                            "maxdeviant".to_string(),
167                                            "Reading you loud and clear!".to_string(),
168                                            DateTime::parse_from_rfc3339(
169                                                "2023-09-28T15:40:52.707Z",
170                                            )
171                                            .unwrap()
172                                            .naive_local(),
173                                        ),
174                                    ])
175                                    .into_any()]
176                            },
177                            Box::new(()),
178                        )
179                        .side(PanelSide::Right),
180                    ),
181            )
182            .child(StatusBar::new())
183        // An example of a toast is below
184        // Currently because of stacking order this gets obscured by other elements
185
186        // .child(Toast::new(
187        //     ToastOrigin::Bottom,
188        //     |_, payload| {
189        //         let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
190
191        //         vec![Label::new("label").into_any()]
192        //     },
193        //     Box::new(theme.clone()),
194        // ))
195    }
196}