panes.rs

  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}