panes.rs

  1use std::marker::PhantomData;
  2
  3use gpui2::{hsla, AnyElement, ElementId, Hsla, Length, Size};
  4use smallvec::SmallVec;
  5
  6use crate::prelude::*;
  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    id: ElementId,
 18    state_type: PhantomData<S>,
 19    size: Size<Length>,
 20    fill: Hsla,
 21    children: SmallVec<[AnyElement<S>; 2]>,
 22}
 23
 24impl<S: 'static + Send + Sync> Pane<S> {
 25    pub fn new(id: impl Into<ElementId>, size: Size<Length>) -> Self {
 26        // Fill is only here for debugging purposes, remove before release
 27
 28        Self {
 29            id: id.into(),
 30            state_type: PhantomData,
 31            size,
 32            fill: hsla(0.3, 0.3, 0.3, 1.),
 33            // fill: system_color.transparent,
 34            children: SmallVec::new(),
 35        }
 36    }
 37
 38    pub fn fill(mut self, fill: Hsla) -> Self {
 39        self.fill = fill;
 40        self
 41    }
 42
 43    fn render(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 44        let color = ThemeColor::new(cx);
 45
 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            .overflow_y_scroll()
 54            .children(self.children.drain(..))
 55    }
 56}
 57
 58impl<S: 'static + Send + Sync> ParentElement for Pane<S> {
 59    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
 60        &mut self.children
 61    }
 62}
 63
 64#[derive(Element)]
 65pub struct PaneGroup<S: 'static + Send + Sync> {
 66    state_type: PhantomData<S>,
 67    groups: Vec<PaneGroup<S>>,
 68    panes: Vec<Pane<S>>,
 69    split_direction: SplitDirection,
 70}
 71
 72impl<S: 'static + Send + Sync> PaneGroup<S> {
 73    pub fn new_groups(groups: Vec<PaneGroup<S>>, split_direction: SplitDirection) -> Self {
 74        Self {
 75            state_type: PhantomData,
 76            groups,
 77            panes: Vec::new(),
 78            split_direction,
 79        }
 80    }
 81
 82    pub fn new_panes(panes: Vec<Pane<S>>, split_direction: SplitDirection) -> Self {
 83        Self {
 84            state_type: PhantomData,
 85            groups: Vec::new(),
 86            panes,
 87            split_direction,
 88        }
 89    }
 90
 91    fn render(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 92        let color = ThemeColor::new(cx);
 93
 94        if !self.panes.is_empty() {
 95            let el = div()
 96                .flex()
 97                .flex_1()
 98                .gap_px()
 99                .w_full()
100                .h_full()
101                .children(self.panes.iter_mut().map(|pane| pane.render(view, cx)));
102
103            if self.split_direction == SplitDirection::Horizontal {
104                return el;
105            } else {
106                return el.flex_col();
107            }
108        }
109
110        if !self.groups.is_empty() {
111            let el = div()
112                .flex()
113                .flex_1()
114                .gap_px()
115                .w_full()
116                .h_full()
117                .bg(color.editor)
118                .children(self.groups.iter_mut().map(|group| group.render(view, cx)));
119
120            if self.split_direction == SplitDirection::Horizontal {
121                return el;
122            } else {
123                return el.flex_col();
124            }
125        }
126
127        unreachable!()
128    }
129}