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}