Add Pane and PaneGroup components

This commit is contained in:
Marshall Bowers 2023-10-06 18:37:28 -04:00
parent b53579858a
commit d5ffd4a1fb
4 changed files with 211 additions and 57 deletions

View file

@ -104,7 +104,7 @@ impl StoryWrapper {
div() div()
.flex() .flex()
.flex_col() .flex_col()
.h_full() .size_full()
.child_any(self.selector.story()) .child_any(self.selector.story())
}) })
} }

View file

@ -3,6 +3,7 @@ mod buffer;
mod icon_button; mod icon_button;
mod list; mod list;
mod panel; mod panel;
mod panes;
mod project_panel; mod project_panel;
mod status_bar; mod status_bar;
mod workspace; mod workspace;
@ -12,6 +13,7 @@ pub use buffer::*;
pub use icon_button::*; pub use icon_button::*;
pub use list::*; pub use list::*;
pub use panel::*; pub use panel::*;
pub use panes::*;
pub use project_panel::*; pub use project_panel::*;
pub use status_bar::*; pub use status_bar::*;
pub use workspace::*; pub use workspace::*;

View file

@ -0,0 +1,131 @@
use std::marker::PhantomData;
use gpui3::{hsla, Hsla, Length, Size};
use crate::prelude::*;
use crate::theme;
#[derive(Default, PartialEq)]
pub enum SplitDirection {
#[default]
Horizontal,
Vertical,
}
#[derive(Element)]
pub struct Pane<S: 'static + Send + Sync> {
state_type: PhantomData<S>,
scroll_state: ScrollState,
size: Size<Length>,
fill: Hsla,
children: HackyChildren<S>,
payload: HackyChildrenPayload,
}
impl<S: 'static + Send + Sync> Pane<S> {
pub fn new(
scroll_state: ScrollState,
size: Size<Length>,
children: HackyChildren<S>,
payload: HackyChildrenPayload,
) -> Self {
// Fill is only here for debugging purposes, remove before release
let system_color = SystemColor::new();
Self {
state_type: PhantomData,
scroll_state,
size,
fill: hsla(0.3, 0.3, 0.3, 1.),
// fill: system_color.transparent,
children,
payload,
}
}
pub fn fill(mut self, fill: Hsla) -> Self {
self.fill = fill;
self
}
fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
let theme = theme(cx);
div()
.flex()
.flex_initial()
.fill(self.fill)
.w(self.size.width)
.h(self.size.height)
.overflow_y_scroll(self.scroll_state.clone())
.children_any((self.children)(cx, self.payload.as_ref()))
}
}
#[derive(Element)]
pub struct PaneGroup<S: 'static + Send + Sync> {
state_type: PhantomData<S>,
groups: Vec<PaneGroup<S>>,
panes: Vec<Pane<S>>,
split_direction: SplitDirection,
}
impl<S: 'static + Send + Sync> PaneGroup<S> {
pub fn new_groups(groups: Vec<PaneGroup<S>>, split_direction: SplitDirection) -> Self {
Self {
state_type: PhantomData,
groups,
panes: Vec::new(),
split_direction,
}
}
pub fn new_panes(panes: Vec<Pane<S>>, split_direction: SplitDirection) -> Self {
Self {
state_type: PhantomData,
groups: Vec::new(),
panes,
split_direction,
}
}
fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
let theme = theme(cx);
if !self.panes.is_empty() {
let el = div()
.flex()
.flex_1()
.gap_px()
.w_full()
.h_full()
.fill(theme.lowest.base.default.background)
.children(self.panes.iter_mut().map(|pane| pane.render(cx)));
if self.split_direction == SplitDirection::Horizontal {
return el;
} else {
return el.flex_col();
}
}
if !self.groups.is_empty() {
let el = div()
.flex()
.flex_1()
.gap_px()
.w_full()
.h_full()
.fill(theme.lowest.base.default.background)
.children(self.groups.iter_mut().map(|group| group.render(cx)));
if self.split_direction == SplitDirection::Horizontal {
return el;
} else {
return el.flex_col();
}
}
unreachable!()
}
}

View file

@ -4,7 +4,7 @@ use std::sync::Arc;
use chrono::DateTime; use chrono::DateTime;
use gpui3::{relative, rems, Size}; use gpui3::{relative, rems, Size};
use crate::prelude::*; use crate::{prelude::*, Pane, PaneGroup, SplitDirection};
use crate::{theme, v_stack, Panel, PanelAllowedSides, PanelSide, ProjectPanel, StatusBar}; use crate::{theme, v_stack, Panel, PanelAllowedSides, PanelSide, ProjectPanel, StatusBar};
#[derive(Element)] #[derive(Element)]
@ -30,62 +30,81 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
pub fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> { pub fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
let theme = theme(cx).clone(); let theme = theme(cx).clone();
// let temp_size = rems(36.).into(); let temp_size = rems(36.).into();
// let root_group = PaneGroup::new_groups( let root_group = PaneGroup::new_groups(
// vec![ vec![
// PaneGroup::new_panes( PaneGroup::new_panes(
// vec![ vec![
// Pane::new( Pane::new(
// ScrollState::default(), ScrollState::default(),
// Size { Size {
// width: relative(1.).into(), width: relative(1.).into(),
// height: temp_size, height: temp_size,
// }, },
// |_, payload| { |_, payload| {
// let theme = payload.downcast_ref::<Arc<Theme>>().unwrap(); let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
// vec![EditorPane::new(hello_world_rust_editor_with_status_example( vec![
div()
.w_full()
.fill(gpui3::rgb::<gpui3::Hsla>(0xff0000))
.into_any(), // EditorPane::new(hello_world_rust_editor_with_status_example(
// &theme, // &theme,
// )) // ))
// .into_any()] // .into_any()
// }, ]
// Box::new(theme.clone()), },
// ), Box::new(theme.clone()),
// Pane::new( ),
// ScrollState::default(), Pane::new(
// Size { ScrollState::default(),
// width: relative(1.).into(), Size {
// height: temp_size, width: relative(1.).into(),
// }, height: temp_size,
// |_, _| vec![Terminal::new().into_any()], },
// Box::new(()), |_, _| {
// ), vec![
// ], div()
// SplitDirection::Vertical, .w_full()
// ), .fill(gpui3::rgb::<gpui3::Hsla>(0x00ff00))
// PaneGroup::new_panes( .into_any(),
// vec![Pane::new( // Terminal::new().into_any()
// ScrollState::default(), ]
// Size { },
// width: relative(1.).into(), Box::new(()),
// height: relative(1.).into(), ),
// }, ],
// |_, payload| { SplitDirection::Vertical,
// let theme = payload.downcast_ref::<Arc<Theme>>().unwrap(); ),
PaneGroup::new_panes(
vec![Pane::new(
ScrollState::default(),
Size {
width: relative(1.).into(),
height: relative(1.).into(),
},
|_, payload| {
let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
// vec![EditorPane::new(hello_world_rust_editor_with_status_example( vec![
div()
.w_full()
.fill(gpui3::rgb::<gpui3::Hsla>(0x0000ff))
.into_any(),
// EditorPane::new(hello_world_rust_editor_with_status_example(
// &theme, // &theme,
// )) // ))
// .into_any()] // .into_any()
// }, ]
// Box::new(theme.clone()), },
// )], Box::new(theme.clone()),
// SplitDirection::Vertical, )],
// ), SplitDirection::Vertical,
// ], ),
// SplitDirection::Horizontal, ],
// ); SplitDirection::Horizontal,
);
div() div()
.relative() .relative()
@ -130,7 +149,8 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
.flex_1() .flex_1()
// CSS Hack: Flex 1 has to have a set height to properly fill the space // CSS Hack: Flex 1 has to have a set height to properly fill the space
// Or it will give you a height of 0 // Or it will give you a height of 0
.h_px(), // .child(root_group), .h_px()
.child(root_group),
) )
.child( .child(
Panel::new( Panel::new(
@ -153,7 +173,8 @@ impl<S: 'static + Send + Sync + Clone> WorkspaceElement<S> {
Box::new(()), Box::new(()),
) )
.side(PanelSide::Right), .side(PanelSide::Right),
), // .child( ),
// .child(
// Panel::new( // Panel::new(
// self.right_panel_scroll_state.clone(), // self.right_panel_scroll_state.clone(),
// |_, payload| { // |_, payload| {