1use std::marker::PhantomData;
2
3use gpui3::{hsla, Hsla, Length, Size};
4
5use crate::prelude::*;
6use crate::theme;
7
8#[derive(Default, PartialEq)]
9pub enum SplitDirection {
10 #[default]
11 Horizontal,
12 Vertical,
13}
14
15#[derive(Element)]
16pub struct Pane<S: 'static + Send + Sync> {
17 state_type: PhantomData<S>,
18 scroll_state: ScrollState,
19 size: Size<Length>,
20 fill: Hsla,
21 children: HackyChildren<S>,
22 payload: HackyChildrenPayload,
23}
24
25impl<S: 'static + Send + Sync> Pane<S> {
26 pub fn new(
27 scroll_state: ScrollState,
28 size: Size<Length>,
29 children: HackyChildren<S>,
30 payload: HackyChildrenPayload,
31 ) -> Self {
32 // Fill is only here for debugging purposes, remove before release
33 let system_color = SystemColor::new();
34
35 Self {
36 state_type: PhantomData,
37 scroll_state,
38 size,
39 fill: hsla(0.3, 0.3, 0.3, 1.),
40 // fill: system_color.transparent,
41 children,
42 payload,
43 }
44 }
45
46 pub fn fill(mut self, fill: Hsla) -> Self {
47 self.fill = fill;
48 self
49 }
50
51 fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
52 let theme = theme(cx);
53
54 div()
55 .flex()
56 .flex_initial()
57 .fill(self.fill)
58 .w(self.size.width)
59 .h(self.size.height)
60 .overflow_y_scroll(self.scroll_state.clone())
61 .children_any((self.children)(cx, self.payload.as_ref()))
62 }
63}
64
65#[derive(Element)]
66pub struct PaneGroup<S: 'static + Send + Sync> {
67 state_type: PhantomData<S>,
68 groups: Vec<PaneGroup<S>>,
69 panes: Vec<Pane<S>>,
70 split_direction: SplitDirection,
71}
72
73impl<S: 'static + Send + Sync> PaneGroup<S> {
74 pub fn new_groups(groups: Vec<PaneGroup<S>>, split_direction: SplitDirection) -> Self {
75 Self {
76 state_type: PhantomData,
77 groups,
78 panes: Vec::new(),
79 split_direction,
80 }
81 }
82
83 pub fn new_panes(panes: Vec<Pane<S>>, split_direction: SplitDirection) -> Self {
84 Self {
85 state_type: PhantomData,
86 groups: Vec::new(),
87 panes,
88 split_direction,
89 }
90 }
91
92 fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
93 let theme = theme(cx);
94
95 if !self.panes.is_empty() {
96 let el = div()
97 .flex()
98 .flex_1()
99 .gap_px()
100 .w_full()
101 .h_full()
102 .fill(theme.lowest.base.default.background)
103 .children(self.panes.iter_mut().map(|pane| pane.render(cx)));
104
105 if self.split_direction == SplitDirection::Horizontal {
106 return el;
107 } else {
108 return el.flex_col();
109 }
110 }
111
112 if !self.groups.is_empty() {
113 let el = div()
114 .flex()
115 .flex_1()
116 .gap_px()
117 .w_full()
118 .h_full()
119 .fill(theme.lowest.base.default.background)
120 .children(self.groups.iter_mut().map(|group| group.render(cx)));
121
122 if self.split_direction == SplitDirection::Horizontal {
123 return el;
124 } else {
125 return el.flex_col();
126 }
127 }
128
129 unreachable!()
130 }
131}