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