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