1use std::marker::PhantomData;
2use std::sync::Arc;
3
4use chrono::DateTime;
5use gpui3::{relative, rems, Size};
6
7use crate::prelude::*;
8use crate::{
9 theme, v_stack, Pane, PaneGroup, Panel, PanelAllowedSides, PanelSide, ProjectPanel,
10 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![
52 Terminal::new().into_any(), // EditorPane::new(hello_world_rust_editor_with_status_example(
53 // &theme,
54 // ))
55 // .into_any()
56 ]
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![
83 Terminal::new().into_any(),
84 // EditorPane::new(hello_world_rust_editor_with_status_example(
85 // &theme,
86 // ))
87 // .into_any()
88 ]
89 },
90 Box::new(theme.clone()),
91 )],
92 SplitDirection::Vertical,
93 ),
94 ],
95 SplitDirection::Horizontal,
96 );
97
98 div()
99 .relative()
100 .size_full()
101 .flex()
102 .flex_col()
103 .font("Zed Sans Extended")
104 .gap_0()
105 .justify_start()
106 .items_start()
107 .text_color(theme.lowest.base.default.foreground)
108 .fill(theme.lowest.base.default.background)
109 // .child(TitleBar::new(cx).set_livestream(Some(Livestream {
110 // players: random_players_with_call_status(7),
111 // channel: Some("gpui2-ui".to_string()),
112 // })))
113 .child(
114 div()
115 .flex_1()
116 .w_full()
117 .flex()
118 .flex_row()
119 .overflow_hidden()
120 .border_t()
121 .border_b()
122 .border_color(theme.lowest.base.default.border)
123 .child(
124 Panel::new(
125 self.left_panel_scroll_state.clone(),
126 |_, payload| vec![ProjectPanel::new(ScrollState::default()).into_any()],
127 Box::new(()),
128 )
129 .side(PanelSide::Left),
130 )
131 .child(
132 v_stack()
133 .flex_1()
134 .h_full()
135 .child(
136 div()
137 .flex()
138 .flex_1()
139 // CSS Hack: Flex 1 has to have a set height to properly fill the space
140 // Or it will give you a height of 0
141 .h_px()
142 .child(root_group),
143 )
144 .child(
145 Panel::new(
146 self.bottom_panel_scroll_state.clone(),
147 |_, _| {
148 vec![
149 // Terminal::new().into_any()
150 ]
151 },
152 Box::new(()),
153 )
154 .allowed_sides(PanelAllowedSides::BottomOnly)
155 .side(PanelSide::Bottom),
156 ),
157 )
158 .child(
159 Panel::new(
160 self.right_panel_scroll_state.clone(),
161 |_, payload| vec![ProjectPanel::new(ScrollState::default()).into_any()],
162 Box::new(()),
163 )
164 .side(PanelSide::Right),
165 ),
166 // .child(
167 // Panel::new(
168 // self.right_panel_scroll_state.clone(),
169 // |_, payload| {
170 // vec![ChatPanel::new(ScrollState::default())
171 // .with_messages(vec![
172 // ChatMessage::new(
173 // "osiewicz".to_string(),
174 // "is this thing on?".to_string(),
175 // DateTime::parse_from_rfc3339(
176 // "2023-09-27T15:40:52.707Z",
177 // )
178 // .unwrap()
179 // .naive_local(),
180 // ),
181 // ChatMessage::new(
182 // "maxdeviant".to_string(),
183 // "Reading you loud and clear!".to_string(),
184 // DateTime::parse_from_rfc3339(
185 // "2023-09-28T15:40:52.707Z",
186 // )
187 // .unwrap()
188 // .naive_local(),
189 // ),
190 // ])
191 // .into_any()]
192 // },
193 // Box::new(()),
194 // )
195 // .side(PanelSide::Right),
196 // ),
197 )
198 .child(StatusBar::new())
199 // An example of a toast is below
200 // Currently because of stacking order this gets obscured by other elements
201
202 // .child(Toast::new(
203 // ToastOrigin::Bottom,
204 // |_, payload| {
205 // let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
206
207 // vec![Label::new("label").into_any()]
208 // },
209 // Box::new(theme.clone()),
210 // ))
211 }
212}