1use gpui2::{hsla, red, AnyElement, ElementId, ExternalPaths, Hsla, Length, Size};
2use smallvec::SmallVec;
3
4use crate::prelude::*;
5
6#[derive(Default, PartialEq)]
7pub enum SplitDirection {
8 #[default]
9 Horizontal,
10 Vertical,
11}
12
13#[derive(Component)]
14pub struct Pane<V: 'static> {
15 id: ElementId,
16 size: Size<Length>,
17 fill: Hsla,
18 children: SmallVec<[AnyElement<V>; 2]>,
19}
20
21// impl<V: 'static> IntoAnyElement<V> for Pane<V> {
22// fn into_any(self) -> AnyElement<V> {
23// (move |view_state: &mut V, cx: &mut ViewContext<'_, '_, V>| self.render(view_state, cx))
24// .into_any()
25// }
26// }
27
28impl<V: 'static> Pane<V> {
29 pub fn new(id: impl Into<ElementId>, size: Size<Length>) -> Self {
30 // Fill is only here for debugging purposes, remove before release
31
32 Self {
33 id: id.into(),
34 size,
35 fill: hsla(0.3, 0.3, 0.3, 1.),
36 children: SmallVec::new(),
37 }
38 }
39
40 pub fn fill(mut self, fill: Hsla) -> Self {
41 self.fill = fill;
42 self
43 }
44
45 fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
46 div()
47 .id(self.id.clone())
48 .flex()
49 .flex_initial()
50 .bg(self.fill)
51 .w(self.size.width)
52 .h(self.size.height)
53 .relative()
54 .child(div().z_index(0).size_full().children(self.children))
55 .child(
56 div()
57 .z_index(1)
58 .id("drag-target")
59 .drag_over::<ExternalPaths>(|d| d.bg(red()))
60 .on_drop(|_, files: ExternalPaths, _| {
61 dbg!("dropped files!", files);
62 })
63 .absolute()
64 .inset_0(),
65 )
66 }
67}
68
69impl<V: 'static> ParentElement<V> for Pane<V> {
70 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
71 &mut self.children
72 }
73}
74
75#[derive(Component)]
76pub struct PaneGroup<V: 'static> {
77 groups: Vec<PaneGroup<V>>,
78 panes: Vec<Pane<V>>,
79 split_direction: SplitDirection,
80}
81
82impl<V: 'static> PaneGroup<V> {
83 pub fn new_groups(groups: Vec<PaneGroup<V>>, split_direction: SplitDirection) -> Self {
84 Self {
85 groups,
86 panes: Vec::new(),
87 split_direction,
88 }
89 }
90
91 pub fn new_panes(panes: Vec<Pane<V>>, split_direction: SplitDirection) -> Self {
92 Self {
93 groups: Vec::new(),
94 panes,
95 split_direction,
96 }
97 }
98
99 fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
100 let theme = theme(cx);
101
102 if !self.panes.is_empty() {
103 let el = div()
104 .flex()
105 .flex_1()
106 .gap_px()
107 .w_full()
108 .h_full()
109 .children(self.panes.into_iter().map(|pane| pane.render(view, cx)));
110
111 if self.split_direction == SplitDirection::Horizontal {
112 return el;
113 } else {
114 return el.flex_col();
115 }
116 }
117
118 if !self.groups.is_empty() {
119 let el = div()
120 .flex()
121 .flex_1()
122 .gap_px()
123 .w_full()
124 .h_full()
125 .bg(theme.editor)
126 .children(self.groups.into_iter().map(|group| group.render(view, cx)));
127
128 if self.split_direction == SplitDirection::Horizontal {
129 return el;
130 } else {
131 return el.flex_col();
132 }
133 }
134
135 unreachable!()
136 }
137}