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        let system_color = SystemColor::new();
 28
 29        Self {
 30            id: id.into(),
 31            state_type: PhantomData,
 32            size,
 33            fill: hsla(0.3, 0.3, 0.3, 1.),
 34            // fill: system_color.transparent,
 35            children: SmallVec::new(),
 36        }
 37    }
 38
 39    pub fn fill(mut self, fill: Hsla) -> Self {
 40        self.fill = fill;
 41        self
 42    }
 43
 44    fn render(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 45        let color = ThemeColor::new(cx);
 46
 47        div()
 48            .id(self.id.clone())
 49            .flex()
 50            .flex_initial()
 51            .bg(self.fill)
 52            .w(self.size.width)
 53            .h(self.size.height)
 54            .overflow_y_scroll()
 55            .children(self.children.drain(..))
 56    }
 57}
 58
 59impl<S: 'static + Send + Sync> ParentElement for Pane<S> {
 60    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
 61        &mut self.children
 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, view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 93        let color = ThemeColor::new(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                .children(self.panes.iter_mut().map(|pane| pane.render(view, cx)));
103
104            if self.split_direction == SplitDirection::Horizontal {
105                return el;
106            } else {
107                return el.flex_col();
108            }
109        }
110
111        if !self.groups.is_empty() {
112            let el = div()
113                .flex()
114                .flex_1()
115                .gap_px()
116                .w_full()
117                .h_full()
118                .bg(color.editor)
119                .children(self.groups.iter_mut().map(|group| group.render(view, cx)));
120
121            if self.split_direction == SplitDirection::Horizontal {
122                return el;
123            } else {
124                return el.flex_col();
125            }
126        }
127
128        unreachable!()
129    }
130}