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