From 30afc8b1d26903df1d05350562577482940b5a2c Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 2 Oct 2023 20:16:55 -0400 Subject: [PATCH] WIP: Panel --- crates/gpui3_macros/src/derive_element.rs | 17 ++- crates/storybook2/src/ui.rs | 6 +- crates/storybook2/src/ui/children.rs | 7 + crates/storybook2/src/ui/components.rs | 3 + crates/storybook2/src/ui/components/panel.rs | 146 +++++++++++++++++++ crates/storybook2/src/ui/prelude.rs | 4 +- crates/storybook2/src/ui/tokens.rs | 24 +++ crates/storybook2/src/workspace.rs | 10 +- 8 files changed, 201 insertions(+), 16 deletions(-) create mode 100644 crates/storybook2/src/ui/children.rs create mode 100644 crates/storybook2/src/ui/components/panel.rs create mode 100644 crates/storybook2/src/ui/tokens.rs diff --git a/crates/gpui3_macros/src/derive_element.rs b/crates/gpui3_macros/src/derive_element.rs index a45eca9534b6dd24834e5b139668a1a725bcca46..e0fdeb4b5075f0d7f2cf4c5bc7368ddd6ff1c1a8 100644 --- a/crates/gpui3_macros/src/derive_element.rs +++ b/crates/gpui3_macros/src/derive_element.rs @@ -27,21 +27,24 @@ pub fn derive_element(input: TokenStream) -> TokenStream { fn layout( &mut self, state: &mut #state_type, - cx: &mut gpui3::ViewContext, + cx: &mut gpui3::ViewContext, ) -> anyhow::Result<(gpui3::LayoutId, Self::FrameState)> { - let mut rendered_element = self.render(state, cx).into_element().into_any(); + use gpui3::IntoAnyElement; + + let mut rendered_element = self.render(cx).into_any(); let layout_id = rendered_element.layout(state, cx)?; Ok((layout_id, rendered_element)) } fn paint( &mut self, - layout: &gpui3::Layout, - state: &mut #state_type, + layout: gpui3::Layout, + state: &mut Self::State, rendered_element: &mut Self::FrameState, - cx: &mut gpui3::ViewContext, - ) { - rendered_element.paint(layout.origin, state, cx); + cx: &mut gpui3::ViewContext, + ) -> anyhow::Result<()> { + // TODO: Where do we get the `offset` from? + rendered_element.paint(state, None, cx) } } }; diff --git a/crates/storybook2/src/ui.rs b/crates/storybook2/src/ui.rs index ef6bc60aff8fef703cc74567cf33d8dc2e809578..8b09f6f0ffc69cd1cf703920768cded33cefed79 100644 --- a/crates/storybook2/src/ui.rs +++ b/crates/storybook2/src/ui.rs @@ -1,6 +1,10 @@ -pub mod prelude; +mod children; mod components; mod elements; +pub mod prelude; +mod tokens; +pub use children::*; pub use components::*; pub use elements::*; +pub use tokens::*; diff --git a/crates/storybook2/src/ui/children.rs b/crates/storybook2/src/ui/children.rs new file mode 100644 index 0000000000000000000000000000000000000000..c7c81e97263b499b2202bc983fd39c4dc9b2a83f --- /dev/null +++ b/crates/storybook2/src/ui/children.rs @@ -0,0 +1,7 @@ +use std::any::Any; + +use gpui3::{AnyElement, ViewContext}; + +pub type HackyChildren = fn(&mut ViewContext, &dyn Any) -> Vec>; + +pub type HackyChildrenPayload = Box; diff --git a/crates/storybook2/src/ui/components.rs b/crates/storybook2/src/ui/components.rs index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ef2e41f583e3692ddc7eed8841916ca2a2c701a3 100644 --- a/crates/storybook2/src/ui/components.rs +++ b/crates/storybook2/src/ui/components.rs @@ -0,0 +1,3 @@ +mod panel; + +pub use panel::*; diff --git a/crates/storybook2/src/ui/components/panel.rs b/crates/storybook2/src/ui/components/panel.rs new file mode 100644 index 0000000000000000000000000000000000000000..39e103dd63eb56581af67919234669caf2fc6608 --- /dev/null +++ b/crates/storybook2/src/ui/components/panel.rs @@ -0,0 +1,146 @@ +use std::marker::PhantomData; + +use gpui3::AbsoluteLength; + +use crate::themes::rose_pine_dawn; +use crate::ui::prelude::*; +use crate::ui::{token, v_stack}; + +#[derive(Default, Debug, PartialEq, Eq, Hash, Clone, Copy)] +pub enum PanelAllowedSides { + LeftOnly, + RightOnly, + BottomOnly, + #[default] + LeftAndRight, + All, +} + +impl PanelAllowedSides { + /// Return a `HashSet` that contains the allowable `PanelSide`s. + pub fn allowed_sides(&self) -> HashSet { + match self { + Self::LeftOnly => HashSet::from_iter([PanelSide::Left]), + Self::RightOnly => HashSet::from_iter([PanelSide::Right]), + Self::BottomOnly => HashSet::from_iter([PanelSide::Bottom]), + Self::LeftAndRight => HashSet::from_iter([PanelSide::Left, PanelSide::Right]), + Self::All => HashSet::from_iter([PanelSide::Left, PanelSide::Right, PanelSide::Bottom]), + } + } +} + +#[derive(Default, Debug, PartialEq, Eq, Hash, Clone, Copy)] +pub enum PanelSide { + #[default] + Left, + Right, + Bottom, +} + +use std::collections::HashSet; + +#[derive(Element)] +pub struct Panel { + scroll_state: ScrollState, + current_side: PanelSide, + /// Defaults to PanelAllowedSides::LeftAndRight + allowed_sides: PanelAllowedSides, + initial_width: AbsoluteLength, + width: Option, + // children: HackyChildren, + // payload: HackyChildrenPayload, +} + +impl Panel { + pub fn new( + scroll_state: ScrollState, + // children: HackyChildren, + // payload: HackyChildrenPayload, + ) -> Self { + let token = token(); + + Self { + scroll_state, + current_side: PanelSide::default(), + allowed_sides: PanelAllowedSides::default(), + initial_width: token.default_panel_size, + width: None, + // children, + // payload, + } + } + + pub fn initial_width(mut self, initial_width: AbsoluteLength) -> Self { + self.initial_width = initial_width; + self + } + + pub fn width(mut self, width: AbsoluteLength) -> Self { + self.width = Some(width); + self + } + + pub fn allowed_sides(mut self, allowed_sides: PanelAllowedSides) -> Self { + self.allowed_sides = allowed_sides; + self + } + + pub fn side(mut self, side: PanelSide) -> Self { + let allowed_sides = self.allowed_sides.allowed_sides(); + + if allowed_sides.contains(&side) { + self.current_side = side; + } else { + panic!( + "The panel side {:?} was not added as allowed before it was set.", + side + ); + } + self + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let token = token(); + let theme = rose_pine_dawn(); + + let panel_base; + let current_width = self.width.unwrap_or(self.initial_width); + + match self.current_side { + PanelSide::Left => { + panel_base = v_stack() + .flex_initial() + .h_full() + // .w(current_width) + .w_4() + .fill(theme.middle.base.default.background) + .border_r() + .border_color(theme.middle.base.default.border); + } + PanelSide::Right => { + panel_base = v_stack() + .flex_initial() + .h_full() + // .w(current_width) + .w_4() + .fill(theme.middle.base.default.background) + .border_l() + .border_color(theme.middle.base.default.border); + } + PanelSide::Bottom => { + panel_base = v_stack() + .flex_initial() + .w_full() + // .h(current_width) + .h_4() + .fill(theme.middle.base.default.background) + .border_t() + .border_color(theme.middle.base.default.border); + } + } + + panel_base + + // panel_base.children_any((self.children)(cx, self.payload.as_ref())) + } +} diff --git a/crates/storybook2/src/ui/prelude.rs b/crates/storybook2/src/ui/prelude.rs index a6243621a67af01edf1e812183b1c950291a92a0..0be2c78c03bf27fa8edf83876f76ee07800543d5 100644 --- a/crates/storybook2/src/ui/prelude.rs +++ b/crates/storybook2/src/ui/prelude.rs @@ -1 +1,3 @@ -pub use gpui3::StyleHelpers; +pub use gpui3::{Element, ScrollState, StyleHelpers, ViewContext}; + +pub use crate::ui::{HackyChildren, HackyChildrenPayload}; diff --git a/crates/storybook2/src/ui/tokens.rs b/crates/storybook2/src/ui/tokens.rs new file mode 100644 index 0000000000000000000000000000000000000000..1f77b3c2d5cd848b2cf429e1b57cc10e8ac1280d --- /dev/null +++ b/crates/storybook2/src/ui/tokens.rs @@ -0,0 +1,24 @@ +use gpui3::{hsla, rems, AbsoluteLength, Hsla}; + +#[derive(Clone, Copy)] +pub struct Token { + pub list_indent_depth: AbsoluteLength, + pub default_panel_size: AbsoluteLength, + pub state_hover_background: Hsla, + pub state_active_background: Hsla, +} + +impl Default for Token { + fn default() -> Self { + Self { + list_indent_depth: AbsoluteLength::Rems(rems(0.5)), + default_panel_size: AbsoluteLength::Rems(rems(16.)), + state_hover_background: hsla(0.0, 0.0, 0.0, 0.08), + state_active_background: hsla(0.0, 0.0, 0.0, 0.16), + } + } +} + +pub fn token() -> Token { + Token::default() +} diff --git a/crates/storybook2/src/workspace.rs b/crates/storybook2/src/workspace.rs index fbe97698e0b3fa6dade311313834fc65c571e037..075fd183f7e559b55cb901f5d90cd039bcaa5047 100644 --- a/crates/storybook2/src/workspace.rs +++ b/crates/storybook2/src/workspace.rs @@ -1,4 +1,5 @@ -use crate::ui::Stack; +use crate::ui::prelude::*; +use crate::ui::{Panel, Stack}; use crate::{ collab_panel::{collab_panel, CollabPanel}, theme::theme, @@ -33,12 +34,7 @@ impl Workspace { .size_full() .v_stack() .fill(theme.lowest.base.default.background) - .child( - div() - .size_full() - .flex() - .fill(theme.middle.positive.default.background), - ) + .child(Panel::new(ScrollState::default())) .child( div() .size_full()