panes.rs

  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}