From e762f7f3c04852758af39f193087901c3f10890b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 19 Sep 2023 13:09:00 -0600 Subject: [PATCH] Checkpoint --- Cargo.lock | 25 ++ Cargo.toml | 1 + crates/storybook/Cargo.toml | 3 + crates/storybook/src/gpui3/app.rs | 200 ----------- crates/storybook/src/gpui3/color.rs | 190 ---------- crates/storybook/src/gpui3/element.rs | 275 --------------- crates/storybook/src/gpui3/elements.rs | 8 - crates/storybook/src/gpui3/elements/div.rs | 38 -- crates/storybook/src/gpui3/elements/editor.rs | 61 ---- crates/storybook/src/gpui3/geometry.rs | 325 ------------------ crates/storybook/src/gpui3/mod.rs | 101 ------ crates/storybook/src/gpui3/platform.rs | 58 ---- crates/storybook/src/gpui3/platform/test.rs | 0 crates/storybook/src/gpui3/renderer.rs | 164 --------- crates/storybook/src/gpui3/scene.rs | 111 ------ crates/storybook/src/gpui3/shader.frag.wgsl | 1 - crates/storybook/src/gpui3/shader.vert.wgsl | 0 crates/storybook/src/gpui3/style.rs | 245 ------------- crates/storybook/src/gpui3/taffy.rs | 238 ------------- crates/storybook/src/gpui3/window.rs | 231 ------------- crates/storybook/src/storybook.rs | 1 - 21 files changed, 29 insertions(+), 2247 deletions(-) delete mode 100644 crates/storybook/src/gpui3/app.rs delete mode 100644 crates/storybook/src/gpui3/color.rs delete mode 100644 crates/storybook/src/gpui3/element.rs delete mode 100644 crates/storybook/src/gpui3/elements.rs delete mode 100644 crates/storybook/src/gpui3/elements/div.rs delete mode 100644 crates/storybook/src/gpui3/elements/editor.rs delete mode 100644 crates/storybook/src/gpui3/geometry.rs delete mode 100644 crates/storybook/src/gpui3/mod.rs delete mode 100644 crates/storybook/src/gpui3/platform.rs delete mode 100644 crates/storybook/src/gpui3/platform/test.rs delete mode 100644 crates/storybook/src/gpui3/renderer.rs delete mode 100644 crates/storybook/src/gpui3/scene.rs delete mode 100644 crates/storybook/src/gpui3/shader.frag.wgsl delete mode 100644 crates/storybook/src/gpui3/shader.vert.wgsl delete mode 100644 crates/storybook/src/gpui3/style.rs delete mode 100644 crates/storybook/src/gpui3/taffy.rs delete mode 100644 crates/storybook/src/gpui3/window.rs diff --git a/Cargo.lock b/Cargo.lock index cfa8ffc80df690b1d1961f7e3659ea1c5e7e7721..2980dcd1f0401f794e88a9c4262db50039663ccb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3340,6 +3340,31 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "gpui3" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytemuck", + "derive_more", + "font-kit", + "itertools 0.11.0", + "log", + "parking_lot 0.11.2", + "plane-split", + "raw-window-handle", + "refineable", + "rust-embed", + "schemars", + "serde", + "simplelog", + "slotmap", + "smallvec", + "taffy", + "util", + "wgpu", +] + [[package]] name = "gpui_macros" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 96070658b9351e4539818c7b83c73d9979da6eb3..4c6d3a6fb9d742534e9b13dcef9e645db7761fa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ members = [ "crates/gpui_macros", "crates/gpui2", "crates/gpui2_macros", + "crates/gpui3", "crates/install_cli", "crates/journal", "crates/language", diff --git a/crates/storybook/Cargo.toml b/crates/storybook/Cargo.toml index 53a36f38a44be87f29047a9d1776debf6a5029e5..5f9c38a5fb471debb12db4c82d9986a352cd91d6 100644 --- a/crates/storybook/Cargo.toml +++ b/crates/storybook/Cargo.toml @@ -8,6 +8,9 @@ publish = false name = "storybook" path = "src/storybook.rs" +[features] +test-support = [] + [dependencies] anyhow.workspace = true bytemuck = "1.14.0" diff --git a/crates/storybook/src/gpui3/app.rs b/crates/storybook/src/gpui3/app.rs deleted file mode 100644 index 2222070888aceb696394680e76666798607c7d95..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/app.rs +++ /dev/null @@ -1,200 +0,0 @@ -use anyhow::{anyhow, Result}; -use slotmap::SlotMap; -use std::{any::Any, marker::PhantomData, rc::Rc}; - -use super::{ - platform::Platform, - window::{Window, WindowHandle, WindowId}, - Context, LayoutId, Reference, View, WindowContext, -}; - -pub struct AppContext { - platform: Rc, - pub(crate) entities: SlotMap>>, - pub(crate) windows: SlotMap>, - // We recycle this memory across layout requests. - pub(crate) layout_id_buffer: Vec, -} - -impl AppContext { - pub fn new(platform: Rc) -> Self { - AppContext { - platform, - entities: SlotMap::with_key(), - windows: SlotMap::with_key(), - layout_id_buffer: Default::default(), - } - } - - pub fn test() -> Self { - Self::new(TestPlatform::new()) - } - - pub fn open_window( - &mut self, - build_root_view: impl FnOnce(&mut WindowContext) -> View, - ) -> WindowHandle { - let id = self.windows.insert(None); - - let mut window = Window::new(id); - let root_view = build_root_view(&mut WindowContext::mutable(self, &mut window)); - window.root_view.replace(Box::new(root_view)); - - self.windows.get_mut(id).unwrap().replace(window); - WindowHandle::new(id) - } - - pub(crate) fn update_window( - &mut self, - window_id: WindowId, - update: impl FnOnce(&mut WindowContext) -> R, - ) -> Result { - let mut window = self - .windows - .get_mut(window_id) - .ok_or_else(|| anyhow!("window not found"))? - .take() - .unwrap(); - - let result = update(&mut WindowContext::mutable(self, &mut window)); - - self.windows - .get_mut(window_id) - .ok_or_else(|| anyhow!("window not found"))? - .replace(window); - - Ok(result) - } -} - -impl Context for AppContext { - type EntityContext<'a, 'w, T: 'static> = ModelContext<'a, T>; - - fn entity( - &mut self, - build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, - ) -> Handle { - let id = self.entities.insert(None); - let entity = Box::new(build_entity(&mut ModelContext::mutable(self, id))); - self.entities.get_mut(id).unwrap().replace(entity); - - Handle::new(id) - } - - fn update_entity( - &mut self, - handle: &Handle, - update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, - ) -> R { - let mut entity = self - .entities - .get_mut(handle.id) - .unwrap() - .take() - .unwrap() - .downcast::() - .unwrap(); - - let result = update(&mut *entity, &mut ModelContext::mutable(self, handle.id)); - self.entities.get_mut(handle.id).unwrap().replace(entity); - result - } -} - -pub struct ModelContext<'a, T> { - app: Reference<'a, AppContext>, - entity_type: PhantomData, - entity_id: EntityId, -} - -impl<'a, T: 'static> ModelContext<'a, T> { - pub(crate) fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self { - Self { - app: Reference::Mutable(app), - entity_type: PhantomData, - entity_id, - } - } - - fn immutable(app: &'a AppContext, entity_id: EntityId) -> Self { - Self { - app: Reference::Immutable(app), - entity_type: PhantomData, - entity_id, - } - } - - fn update(&mut self, update: impl FnOnce(&mut T, &mut Self) -> R) -> R { - let mut entity = self - .app - .entities - .get_mut(self.entity_id) - .unwrap() - .take() - .unwrap(); - let result = update(entity.downcast_mut::().unwrap(), self); - self.app - .entities - .get_mut(self.entity_id) - .unwrap() - .replace(entity); - result - } -} - -impl<'a, T: 'static> Context for ModelContext<'a, T> { - type EntityContext<'b, 'c, U: 'static> = ModelContext<'b, U>; - - fn entity( - &mut self, - build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, U>) -> U, - ) -> Handle { - self.app.entity(build_entity) - } - - fn update_entity( - &mut self, - handle: &Handle, - update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R, - ) -> R { - self.app.update_entity(handle, update) - } -} - -pub struct Handle { - pub(crate) id: EntityId, - pub(crate) entity_type: PhantomData, -} - -slotmap::new_key_type! { pub struct EntityId; } - -impl Handle { - fn new(id: EntityId) -> Self { - Self { - id, - entity_type: PhantomData, - } - } - - /// Update the entity referenced by this handle with the given function. - /// - /// The update function receives a context appropriate for its environment. - /// When updating in an `AppContext`, it receives a `ModelContext`. - /// When updating an a `WindowContext`, it receives a `ViewContext`. - pub fn update( - &self, - cx: &mut C, - update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R, - ) -> R { - cx.update_entity(self, update) - } -} - -impl Clone for Handle { - fn clone(&self) -> Self { - Self { - id: self.id, - entity_type: PhantomData, - } - } -} diff --git a/crates/storybook/src/gpui3/color.rs b/crates/storybook/src/gpui3/color.rs deleted file mode 100644 index 7287bf106c3fbf14e9fefba9e56acc134fb12c71..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/color.rs +++ /dev/null @@ -1,190 +0,0 @@ -#![allow(dead_code)] - -use bytemuck::{Pod, Zeroable}; -use serde::de::{self, Deserialize, Deserializer, Visitor}; -use std::fmt; -use std::num::ParseIntError; - -pub fn rgb>(hex: u32) -> C { - let r = ((hex >> 16) & 0xFF) as f32 / 255.0; - let g = ((hex >> 8) & 0xFF) as f32 / 255.0; - let b = (hex & 0xFF) as f32 / 255.0; - Rgba { r, g, b, a: 1.0 }.into() -} - -#[derive(Clone, Copy, Default, Debug)] -pub struct Rgba { - pub r: f32, - pub g: f32, - pub b: f32, - pub a: f32, -} - -struct RgbaVisitor; - -impl<'de> Visitor<'de> for RgbaVisitor { - type Value = Rgba; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a string in the format #rrggbb or #rrggbbaa") - } - - fn visit_str(self, value: &str) -> Result { - if value.len() == 7 || value.len() == 9 { - let r = u8::from_str_radix(&value[1..3], 16).unwrap() as f32 / 255.0; - let g = u8::from_str_radix(&value[3..5], 16).unwrap() as f32 / 255.0; - let b = u8::from_str_radix(&value[5..7], 16).unwrap() as f32 / 255.0; - let a = if value.len() == 9 { - u8::from_str_radix(&value[7..9], 16).unwrap() as f32 / 255.0 - } else { - 1.0 - }; - Ok(Rgba { r, g, b, a }) - } else { - Err(E::custom( - "Bad format for RGBA. Expected #rrggbb or #rrggbbaa.", - )) - } - } -} - -impl<'de> Deserialize<'de> for Rgba { - fn deserialize>(deserializer: D) -> Result { - deserializer.deserialize_str(RgbaVisitor) - } -} - -impl From for Rgba { - fn from(color: Hsla) -> Self { - let h = color.h; - let s = color.s; - let l = color.l; - - let c = (1.0 - (2.0 * l - 1.0).abs()) * s; - let x = c * (1.0 - ((h * 6.0) % 2.0 - 1.0).abs()); - let m = l - c / 2.0; - let cm = c + m; - let xm = x + m; - - let (r, g, b) = match (h * 6.0).floor() as i32 { - 0 | 6 => (cm, xm, m), - 1 => (xm, cm, m), - 2 => (m, cm, xm), - 3 => (m, xm, cm), - 4 => (xm, m, cm), - _ => (cm, m, xm), - }; - - Rgba { - r, - g, - b, - a: color.a, - } - } -} - -impl TryFrom<&'_ str> for Rgba { - type Error = ParseIntError; - - fn try_from(value: &'_ str) -> Result { - let r = u8::from_str_radix(&value[1..3], 16)? as f32 / 255.0; - let g = u8::from_str_radix(&value[3..5], 16)? as f32 / 255.0; - let b = u8::from_str_radix(&value[5..7], 16)? as f32 / 255.0; - let a = if value.len() > 7 { - u8::from_str_radix(&value[7..9], 16)? as f32 / 255.0 - } else { - 1.0 - }; - - Ok(Rgba { r, g, b, a }) - } -} - -#[derive(Default, Copy, Clone, Debug, PartialEq)] -#[repr(C)] -pub struct Hsla { - pub h: f32, - pub s: f32, - pub l: f32, - pub a: f32, -} - -unsafe impl Zeroable for Hsla {} -unsafe impl Pod for Hsla {} - -pub fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla { - Hsla { - h: h.clamp(0., 1.), - s: s.clamp(0., 1.), - l: l.clamp(0., 1.), - a: a.clamp(0., 1.), - } -} - -pub fn black() -> Hsla { - Hsla { - h: 0., - s: 0., - l: 0., - a: 1., - } -} - -impl Hsla { - /// Returns true if the HSLA color is fully transparent, false otherwise. - pub fn is_transparent(&self) -> bool { - self.a == 0.0 - } -} - -impl From for Hsla { - fn from(color: Rgba) -> Self { - let r = color.r; - let g = color.g; - let b = color.b; - - let max = r.max(g.max(b)); - let min = r.min(g.min(b)); - let delta = max - min; - - let l = (max + min) / 2.0; - let s = if l == 0.0 || l == 1.0 { - 0.0 - } else if l < 0.5 { - delta / (2.0 * l) - } else { - delta / (2.0 - 2.0 * l) - }; - - let h = if delta == 0.0 { - 0.0 - } else if max == r { - ((g - b) / delta).rem_euclid(6.0) / 6.0 - } else if max == g { - ((b - r) / delta + 2.0) / 6.0 - } else { - ((r - g) / delta + 4.0) / 6.0 - }; - - Hsla { - h, - s, - l, - a: color.a, - } - } -} - -impl<'de> Deserialize<'de> for Hsla { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - // First, deserialize it into Rgba - let rgba = Rgba::deserialize(deserializer)?; - - // Then, use the From for Hsla implementation to convert it - Ok(Hsla::from(rgba)) - } -} diff --git a/crates/storybook/src/gpui3/element.rs b/crates/storybook/src/gpui3/element.rs deleted file mode 100644 index afb50fabec2fe80b07dee30880c8ae604691a156..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/element.rs +++ /dev/null @@ -1,275 +0,0 @@ -use super::{Handle, Layout, LayoutId, Pixels, Point, Result, ViewContext, WindowContext}; -use std::{any::Any, cell::RefCell, marker::PhantomData, rc::Rc}; - -pub trait Element: 'static { - type State; - type FrameState; - - fn layout( - &mut self, - state: &mut Self::State, - cx: &mut ViewContext, - ) -> Result<(LayoutId, Self::FrameState)>; - - fn paint( - &mut self, - layout: Layout, - state: &mut Self::State, - frame_state: &mut Self::FrameState, - cx: &mut ViewContext, - ) -> Result<()>; -} - -pub trait ParentElement { - fn child(self, child: impl IntoAnyElement) -> Self; -} - -trait ElementObject { - fn layout(&mut self, state: &mut S, cx: &mut ViewContext) -> Result; - fn paint( - &mut self, - parent_origin: super::Point, - state: &mut S, - cx: &mut ViewContext, - ) -> Result<()>; -} - -struct RenderedElement { - element: E, - phase: ElementRenderPhase, -} - -#[derive(Default)] -enum ElementRenderPhase { - #[default] - Rendered, - LayoutRequested { - layout_id: LayoutId, - frame_state: S, - }, - Painted { - layout: Layout, - frame_state: S, - }, -} - -/// Internal struct that wraps an element to store Layout and FrameState after the element is rendered. -/// It's allocated as a trait object to erase the element type and wrapped in AnyElement for -/// improved usability. -impl RenderedElement { - fn new(element: E) -> Self { - RenderedElement { - element, - phase: ElementRenderPhase::Rendered, - } - } -} - -impl ElementObject for RenderedElement { - fn layout(&mut self, state: &mut E::State, cx: &mut ViewContext) -> Result { - let (layout_id, frame_state) = self.element.layout(state, cx)?; - self.phase = ElementRenderPhase::LayoutRequested { - layout_id, - frame_state, - }; - Ok(layout_id) - } - - fn paint( - &mut self, - parent_origin: Point, - state: &mut E::State, - cx: &mut ViewContext, - ) -> Result<()> { - self.phase = match std::mem::take(&mut self.phase) { - ElementRenderPhase::Rendered => panic!("must call layout before paint"), - - ElementRenderPhase::LayoutRequested { - layout_id, - mut frame_state, - } => { - let mut layout = cx.layout(layout_id)?; - layout.bounds.origin += parent_origin; - self.element - .paint(layout.clone(), state, &mut frame_state, cx)?; - ElementRenderPhase::Painted { - layout, - frame_state, - } - } - - ElementRenderPhase::Painted { - layout, - mut frame_state, - } => { - self.element - .paint(layout.clone(), state, &mut frame_state, cx)?; - ElementRenderPhase::Painted { - layout, - frame_state, - } - } - }; - - Ok(()) - } -} - -pub struct AnyElement(Box>); - -impl AnyElement { - pub fn layout(&mut self, state: &mut S, cx: &mut ViewContext) -> Result { - self.0.layout(state, cx) - } - - pub fn paint( - &mut self, - parent_origin: Point, - state: &mut S, - cx: &mut ViewContext, - ) -> Result<()> { - self.0.paint(parent_origin, state, cx) - } -} - -pub trait IntoAnyElement { - fn into_any(self) -> AnyElement; -} - -impl IntoAnyElement for E { - fn into_any(self) -> AnyElement { - AnyElement(Box::new(RenderedElement::new(self))) - } -} - -impl IntoAnyElement for AnyElement { - fn into_any(self) -> AnyElement { - self - } -} - -#[derive(Clone)] -pub struct View { - state: Handle, - render: Rc) -> AnyElement>, -} - -pub fn view>( - state: Handle, - render: impl 'static + Fn(&mut S, &mut ViewContext) -> E, -) -> View { - View { - state, - render: Rc::new(move |state, cx| render(state, cx).into_any()), - } -} - -impl View { - pub fn into_any(self) -> AnyView { - AnyView { - view: Rc::new(RefCell::new(self)), - parent_state_type: PhantomData, - } - } -} - -impl Element for View { - type State = (); - type FrameState = AnyElement; - - fn layout( - &mut self, - _: &mut Self::State, - cx: &mut ViewContext, - ) -> Result<(LayoutId, Self::FrameState)> { - self.state.update(cx, |state, cx| { - let mut element = (self.render)(state, cx); - let layout_id = element.layout(state, cx)?; - Ok((layout_id, element)) - }) - } - - fn paint( - &mut self, - layout: Layout, - _: &mut Self::State, - element: &mut Self::FrameState, - cx: &mut ViewContext, - ) -> Result<()> { - self.state.update(cx, |state, cx| { - element.paint(layout.bounds.origin, state, cx) - }) - } -} - -trait ViewObject { - fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box)>; - fn paint( - &mut self, - layout: Layout, - element: &mut dyn Any, - cx: &mut WindowContext, - ) -> Result<()>; -} - -impl ViewObject for View { - fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box)> { - self.state.update(cx, |state, cx| { - let mut element = (self.render)(state, cx); - let layout_id = element.layout(state, cx)?; - let element = Box::new(element) as Box; - Ok((layout_id, element)) - }) - } - - fn paint( - &mut self, - layout: Layout, - element: &mut dyn Any, - cx: &mut WindowContext, - ) -> Result<()> { - self.state.update(cx, |state, cx| { - element - .downcast_mut::>() - .unwrap() - .paint(layout.bounds.origin, state, cx) - }) - } -} - -pub struct AnyView { - view: Rc>, - parent_state_type: PhantomData, -} - -impl Element for AnyView { - type State = S; - type FrameState = Box; - - fn layout( - &mut self, - _: &mut Self::State, - cx: &mut ViewContext, - ) -> Result<(LayoutId, Self::FrameState)> { - self.view.borrow_mut().layout(cx) - } - - fn paint( - &mut self, - layout: Layout, - _: &mut Self::State, - element: &mut Self::FrameState, - cx: &mut ViewContext, - ) -> Result<()> { - self.view.borrow_mut().paint(layout, element, cx) - } -} - -impl Clone for AnyView { - fn clone(&self) -> Self { - Self { - view: self.view.clone(), - parent_state_type: PhantomData, - } - } -} diff --git a/crates/storybook/src/gpui3/elements.rs b/crates/storybook/src/gpui3/elements.rs deleted file mode 100644 index 3847db24cc5fcdbaf135ec517f0415dec8da138a..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/elements.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod div; -pub mod editor; - -use super::*; -use std::marker::PhantomData; - -pub use div::div; -pub use editor::field; diff --git a/crates/storybook/src/gpui3/elements/div.rs b/crates/storybook/src/gpui3/elements/div.rs deleted file mode 100644 index 7d3f70042b09ac01b567dc410e673ca660c5fb7e..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/elements/div.rs +++ /dev/null @@ -1,38 +0,0 @@ -use super::{ - Element, IntoAnyElement, Layout, LayoutId, ParentElement, PhantomData, Result, ViewContext, -}; - -pub struct Div(PhantomData); - -impl Element for Div { - type State = S; - type FrameState = (); - - fn layout( - &mut self, - state: &mut Self::State, - cx: &mut ViewContext, - ) -> Result<(LayoutId, Self::FrameState)> { - todo!() - } - - fn paint( - &mut self, - layout: Layout, - state: &mut Self::State, - frame_state: &mut Self::FrameState, - cx: &mut ViewContext, - ) -> Result<()> { - todo!() - } -} - -impl ParentElement for Div { - fn child(self, child: impl IntoAnyElement) -> Self { - todo!() - } -} - -pub fn div() -> Div { - todo!() -} diff --git a/crates/storybook/src/gpui3/elements/editor.rs b/crates/storybook/src/gpui3/elements/editor.rs deleted file mode 100644 index 77f27d3d1fcdd06dfe4240468f0223124753f5d8..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/elements/editor.rs +++ /dev/null @@ -1,61 +0,0 @@ -use super::{Element, Handle, Layout, LayoutId, Result, SharedString, ViewContext}; -use std::marker::PhantomData; - -pub fn field(editor: Handle) -> EditorElement { - EditorElement { - editor, - field: true, - placeholder_text: None, - parent_state: PhantomData, - } -} - -pub struct EditorElement { - editor: Handle, - field: bool, - placeholder_text: Option, - parent_state: PhantomData, -} - -impl EditorElement { - pub fn field(mut self) -> Self { - self.field = true; - self - } - - pub fn placeholder_text(mut self, text: impl Into) -> Self { - self.placeholder_text = Some(text.into()); - self - } -} - -impl Element for EditorElement { - type State = S; - type FrameState = (); - - fn layout( - &mut self, - _: &mut Self::State, - cx: &mut ViewContext, - ) -> Result<(LayoutId, Self::FrameState)> { - self.editor.update(cx, |editor, cx| todo!()) - } - - fn paint( - &mut self, - layout: Layout, - state: &mut Self::State, - frame_state: &mut Self::FrameState, - cx: &mut ViewContext, - ) -> Result<()> { - self.editor.update(cx, |editor, cx| todo!()) - } -} - -pub struct Editor {} - -impl Editor { - pub fn new(_: &mut ViewContext) -> Self { - Editor {} - } -} diff --git a/crates/storybook/src/gpui3/geometry.rs b/crates/storybook/src/gpui3/geometry.rs deleted file mode 100644 index 64293d121bec6f067bda42e9b77213d2ddc6576d..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/geometry.rs +++ /dev/null @@ -1,325 +0,0 @@ -use bytemuck::{Pod, Zeroable}; -use core::fmt::Debug; -use derive_more::{Add, AddAssign, Div, Mul, Sub}; -use refineable::Refineable; -use std::ops::Mul; - -#[derive(Refineable, Default, Add, AddAssign, Sub, Mul, Div, Copy, Debug, PartialEq, Eq, Hash)] -#[refineable(debug)] -#[repr(C)] -pub struct Point { - pub x: T, - pub y: T, -} - -impl Point { - pub fn new(x: T, y: T) -> Self { - Self { x, y } - } -} - -impl Clone for Point { - fn clone(&self) -> Self { - Self { - x: self.x.clone(), - y: self.y.clone(), - } - } -} - -unsafe impl Zeroable for Point {} - -unsafe impl Pod for Point {} - -#[derive(Refineable, Default, Clone, Copy, Debug, PartialEq)] -#[refineable(debug)] -pub struct Size { - pub width: T, - pub height: T, -} - -impl Size { - pub fn full() -> Self { - Self { - width: relative(1.), - height: relative(1.), - } - } -} - -impl Size { - pub fn zero() -> Self { - Self { - width: px(0.), - height: px(0.), - } - } -} - -impl Size { - pub fn auto() -> Self { - Self { - width: Length::Auto, - height: Length::Auto, - } - } -} - -#[derive(Refineable, Clone, Default, Debug, PartialEq)] -#[refineable(debug)] -pub struct Bounds { - pub origin: Point, - pub size: Size, -} - -impl Copy for Bounds {} - -#[derive(Refineable, Clone, Default, Debug)] -#[refineable(debug)] -pub struct Edges { - pub top: T, - pub right: T, - pub bottom: T, - pub left: T, -} - -impl Edges { - pub fn auto() -> Self { - Self { - top: Length::Auto, - right: Length::Auto, - bottom: Length::Auto, - left: Length::Auto, - } - } - - pub fn zero() -> Self { - Self { - top: px(0.), - right: px(0.), - bottom: px(0.), - left: px(0.), - } - } -} - -impl Edges { - pub fn zero() -> Self { - Self { - top: px(0.), - right: px(0.), - bottom: px(0.), - left: px(0.), - } - } -} - -impl Edges { - pub fn zero() -> Self { - Self { - top: px(0.), - right: px(0.), - bottom: px(0.), - left: px(0.), - } - } - - pub fn to_pixels(&self, rem_size: Pixels) -> Edges { - Edges { - top: self.top.to_pixels(rem_size), - right: self.right.to_pixels(rem_size), - bottom: self.bottom.to_pixels(rem_size), - left: self.left.to_pixels(rem_size), - } - } -} - -impl Edges { - pub fn is_empty(&self) -> bool { - self.top == px(0.) && self.right == px(0.) && self.bottom == px(0.) && self.left == px(0.) - } -} - -#[derive(Clone, Copy, Default, Add, AddAssign, Sub, Mul, Div, PartialEq)] -#[repr(transparent)] -pub struct Pixels(pub(crate) f32); - -unsafe impl bytemuck::Pod for Pixels {} -unsafe impl bytemuck::Zeroable for Pixels {} - -impl Debug for Pixels { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{} px", self.0) - } -} - -impl From for f32 { - fn from(pixels: Pixels) -> Self { - pixels.0 - } -} - -impl From<&Pixels> for f32 { - fn from(pixels: &Pixels) -> Self { - pixels.0 - } -} - -#[derive(Clone, Copy, Default, Add, Sub, Mul, Div)] -pub struct Rems(f32); - -impl Mul for Rems { - type Output = Pixels; - - fn mul(self, other: Pixels) -> Pixels { - Pixels(self.0 * other.0) - } -} - -impl Debug for Rems { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{} rem", self.0) - } -} - -#[derive(Clone, Copy, Debug)] -pub enum AbsoluteLength { - Pixels(Pixels), - Rems(Rems), -} - -impl From for AbsoluteLength { - fn from(pixels: Pixels) -> Self { - AbsoluteLength::Pixels(pixels) - } -} - -impl From for AbsoluteLength { - fn from(rems: Rems) -> Self { - AbsoluteLength::Rems(rems) - } -} - -impl AbsoluteLength { - pub fn to_pixels(&self, rem_size: Pixels) -> Pixels { - match self { - AbsoluteLength::Pixels(pixels) => *pixels, - AbsoluteLength::Rems(rems) => *rems * rem_size, - } - } -} - -impl Default for AbsoluteLength { - fn default() -> Self { - px(0.) - } -} - -/// A non-auto length that can be defined in pixels, rems, or percent of parent. -#[derive(Clone, Copy)] -pub enum DefiniteLength { - Absolute(AbsoluteLength), - /// A fraction of the parent's size between 0 and 1. - Fraction(f32), -} - -impl Debug for DefiniteLength { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - DefiniteLength::Absolute(length) => Debug::fmt(length, f), - DefiniteLength::Fraction(fract) => write!(f, "{}%", (fract * 100.0) as i32), - } - } -} - -impl From for DefiniteLength { - fn from(pixels: Pixels) -> Self { - Self::Absolute(pixels.into()) - } -} - -impl From for DefiniteLength { - fn from(rems: Rems) -> Self { - Self::Absolute(rems.into()) - } -} - -impl From for DefiniteLength { - fn from(length: AbsoluteLength) -> Self { - Self::Absolute(length) - } -} - -impl Default for DefiniteLength { - fn default() -> Self { - Self::Absolute(AbsoluteLength::default()) - } -} - -/// A length that can be defined in pixels, rems, percent of parent, or auto. -#[derive(Clone, Copy)] -pub enum Length { - Definite(DefiniteLength), - Auto, -} - -impl Debug for Length { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Length::Definite(definite_length) => write!(f, "{:?}", definite_length), - Length::Auto => write!(f, "auto"), - } - } -} - -pub fn relative>(fraction: f32) -> T { - DefiniteLength::Fraction(fraction).into() -} - -pub fn rems>(rems: f32) -> T { - Rems(rems).into() -} - -pub fn px>(pixels: f32) -> T { - Pixels(pixels).into() -} - -pub fn auto() -> Length { - Length::Auto -} - -impl From for Length { - fn from(pixels: Pixels) -> Self { - Self::Definite(pixels.into()) - } -} - -impl From for Length { - fn from(rems: Rems) -> Self { - Self::Definite(rems.into()) - } -} - -impl From for Length { - fn from(length: DefiniteLength) -> Self { - Self::Definite(length) - } -} - -impl From for Length { - fn from(length: AbsoluteLength) -> Self { - Self::Definite(length.into()) - } -} - -impl Default for Length { - fn default() -> Self { - Self::Definite(DefiniteLength::default()) - } -} - -impl From<()> for Length { - fn from(_: ()) -> Self { - Self::Definite(DefiniteLength::default()) - } -} diff --git a/crates/storybook/src/gpui3/mod.rs b/crates/storybook/src/gpui3/mod.rs deleted file mode 100644 index 79fba6f447767e0654ccc390a3c7dfba4fbb131a..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/mod.rs +++ /dev/null @@ -1,101 +0,0 @@ -mod app; -mod color; -mod element; -mod elements; -mod geometry; -mod platform; -mod renderer; -mod scene; -mod style; -mod taffy; -mod window; - -use self::editor::Editor; -use anyhow::Result; -pub use app::*; -pub use color::*; -pub use element::*; -pub use elements::*; -pub use geometry::*; -pub use gpui2::ArcCow; -use gpui2::Reference; -pub use scene::*; -pub use style::*; -pub use taffy::LayoutId; -use taffy::TaffyLayoutEngine; -pub use window::*; - -pub trait Context { - type EntityContext<'a, 'w, T: 'static>; - - fn entity( - &mut self, - build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, - ) -> Handle; - - fn update_entity( - &mut self, - handle: &Handle, - update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, - ) -> R; -} - -#[derive(Clone, Eq, PartialEq)] -pub struct SharedString(ArcCow<'static, str>); - -impl std::fmt::Debug for SharedString { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } -} - -impl>> From for SharedString { - fn from(value: T) -> Self { - Self(value.into()) - } -} - -struct Workspace { - left_panel: AnyView, -} - -fn workspace(cx: &mut WindowContext) -> View { - let workspace = cx.entity(|cx| Workspace { - left_panel: collab_panel(cx).into_any(), - }); - view(workspace, |workspace, cx| { - div().child(workspace.left_panel.clone()) - }) -} - -struct CollabPanel { - filter_editor: Handle, -} - -fn collab_panel(cx: &mut WindowContext) -> View { - let panel = cx.entity(|cx| CollabPanel::new(cx)); - view(panel, |panel, cx| { - div() - .child(div()) - .child(field(panel.filter_editor.clone()).placeholder_text("Search channels, contacts")) - }) -} - -impl CollabPanel { - fn new(cx: &mut ViewContext) -> Self { - Self { - filter_editor: cx.entity(|cx| Editor::new(cx)), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test() { - let mut cx = AppContext::new(); - cx.open_window(|cx| workspace(cx)); - } -} diff --git a/crates/storybook/src/gpui3/platform.rs b/crates/storybook/src/gpui3/platform.rs deleted file mode 100644 index f475ce39406ae9322dc278412b44bb3d5ef62eff..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/platform.rs +++ /dev/null @@ -1,58 +0,0 @@ -mod test; -use super::{AnyWindowHandle, Bounds, Point}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; - -pub trait Platform { - fn open_window( - &self, - handle: AnyWindowHandle, - options: WindowOptions, - ) -> Box; -} - -pub trait PlatformWindow: HasRawWindowHandle + HasRawDisplayHandle {} - -#[derive(Debug)] -pub struct WindowOptions<'a> { - pub bounds: WindowBounds, - pub titlebar: Option>, - pub center: bool, - pub focus: bool, - pub show: bool, - pub kind: WindowKind, - pub is_movable: bool, -} - -#[derive(Debug, Default)] -pub struct TitlebarOptions<'a> { - pub title: Option<&'a str>, - pub appears_transparent: bool, - pub traffic_light_position: Option>, -} - -#[derive(Copy, Clone, Debug)] -pub enum Appearance { - Light, - VibrantLight, - Dark, - VibrantDark, -} - -impl Default for Appearance { - fn default() -> Self { - Self::Light - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum WindowKind { - Normal, - PopUp, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum WindowBounds { - Fullscreen, - Maximized, - Fixed(Bounds), -} diff --git a/crates/storybook/src/gpui3/platform/test.rs b/crates/storybook/src/gpui3/platform/test.rs deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/crates/storybook/src/gpui3/renderer.rs b/crates/storybook/src/gpui3/renderer.rs deleted file mode 100644 index 9bcd347f8d26b5aa784cf12392228e5c6db97665..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/renderer.rs +++ /dev/null @@ -1,164 +0,0 @@ -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; - -use super::{Scene, Size}; - -pub struct Renderer { - device: wgpu::Device, - queue: wgpu::Queue, - surface: wgpu::Surface, - surface_config: wgpu::SurfaceConfiguration, - pipeline: wgpu::RenderPipeline, - vertex_buffer: wgpu::Buffer, - vertex_count: u32, -} - -pub trait Window: HasRawWindowHandle + HasRawDisplayHandle { - fn inner_size(&self) -> Size; -} - -impl Renderer { - pub async fn new(window: &W) -> Self - where - W: Window, - { - let instance = wgpu::Instance::new(Default::default()); - let surface = unsafe { instance.create_surface(window).unwrap() }; - - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions::default()) - .await - .unwrap(); - - let (device, queue) = adapter - .request_device(&wgpu::DeviceDescriptor::default(), None) - .await - .unwrap(); - - let surface_config = wgpu::SurfaceConfiguration { - usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: wgpu::TextureFormat::Bgra8UnormSrgb, - width: window.inner_size().width, - height: window.inner_size().height, - - // "FIFO" mode renders frames in queue synced with the display's refresh rate. - // Avoids screen tearing but may not offer the lowest latency. Ideal when image - // quality takes priority over input latency. - present_mode: wgpu::PresentMode::Fifo, - - // Use the Premultiplied alpha mode. With premultiplication, the color components - // are multiplied by the alpha value before storage or blending, meaning calculations - // with colors already factor in the influence of alpha. This typically results - // in better performance and avoids a separate multiplication operation during blending. - alpha_mode: wgpu::CompositeAlphaMode::PreMultiplied, - - // Specify the color formats for the views the surface can have. - // In this case, the format is BGRA (blue, green, red, alpha) with unsigned - // normalised integers in the 8-bit range and the color space is sRGB (standard RGB). - // sRGB is the standard color space for displaying images and video on digital displays, - // as it optimises color accuracy and consistency. - view_formats: vec![wgpu::TextureFormat::Bgra8UnormSrgb], - }; - - surface.configure(&device, &surface_config); - - let vs_module = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("Vertex Shader"), - source: wgpu::ShaderSource::Wgsl(include_str!("shader.vert.wgsl").into()), - }); - - let fs_module = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("Fragment Shader"), - source: wgpu::ShaderSource::Wgsl(include_str!("shader.frag.wgsl").into()), - }); - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Render Pipeline Layout"), - bind_group_layouts: &[], - push_constant_ranges: &[], - }); - - let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("Vertex Buffer"), - size: 0, - usage: wgpu::BufferUsages::VERTEX, - mapped_at_creation: false, - }); - - let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &vs_module, - entry_point: "main", - buffers: &[], - }, - fragment: Some(wgpu::FragmentState { - module: &fs_module, - entry_point: "main", - targets: &[Some(wgpu::ColorTargetState { - format: surface_config.format, - blend: Some(wgpu::BlendState::REPLACE), - write_mask: wgpu::ColorWrites::ALL, - })], - }), - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleStrip, - ..Default::default() - }, - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - multiview: None, - }); - - Self { - device, - queue, - surface, - surface_config, - pipeline, - vertex_buffer, - vertex_count: 0, - } - } - - pub fn render(&mut self, scene: &Scene) { - let frame = self.surface.get_current_texture().unwrap(); - let view = frame - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - - self.queue.write_buffer( - &self.vertex_buffer, - 0, - bytemuck::cast_slice(&scene.opaque_primitives().quads), - ); - self.vertex_count = scene.opaque_primitives().quads.len() as u32; - - let mut encoder = self - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Render Encoder"), - }); - - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("Render Pass"), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), - store: true, - }, - })], - depth_stencil_attachment: None, - }); - - render_pass.set_pipeline(&self.pipeline); - render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); - render_pass.draw(0..self.vertex_count, 0..1); - } - - self.queue.submit(std::iter::once(encoder.finish())); - } -} diff --git a/crates/storybook/src/gpui3/scene.rs b/crates/storybook/src/gpui3/scene.rs deleted file mode 100644 index c1b20eacff4b64c656875c6a7faea9140bc5a191..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/scene.rs +++ /dev/null @@ -1,111 +0,0 @@ -use super::{Bounds, Hsla, Pixels, Point}; -use bytemuck::{Pod, Zeroable}; -use plane_split::BspSplitter; - -pub struct Scene { - opaque_primitives: PrimitiveBatch, - transparent_primitives: slotmap::SlotMap, - splitter: BspSplitter, -} - -impl Scene { - pub fn new() -> Scene { - Scene { - opaque_primitives: PrimitiveBatch::default(), - transparent_primitives: slotmap::SlotMap::new(), - splitter: BspSplitter::new(), - } - } - - pub fn insert(&mut self, primitive: impl Into, is_transparent: bool) { - if is_transparent { - self.transparent_primitives.insert(primitive.into()); - } else { - match primitive.into() { - Primitive::Quad(quad) => self.opaque_primitives.quads.push(quad), - Primitive::Glyph(glyph) => self.opaque_primitives.glyphs.push(glyph), - } - } - } - - pub fn opaque_primitives(&self) -> &PrimitiveBatch { - &self.opaque_primitives - } -} - -#[derive(Clone, Debug)] -pub enum Primitive { - Quad(Quad), - Glyph(Glyph), -} - -impl Primitive { - pub fn is_transparent(&self) -> bool { - match self { - Primitive::Quad(quad) => { - quad.background.is_transparent() && quad.border_color.is_transparent() - } - Primitive::Glyph(glyph) => glyph.color.is_transparent(), - } - } -} - -#[derive(Default)] -pub struct PrimitiveBatch { - pub quads: Vec, - pub glyphs: Vec, -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Quad { - pub order: f32, - pub bounds: Bounds, - pub background: Hsla, - pub border_color: Hsla, - pub corner_radius: Pixels, - pub border_left: Pixels, - pub border_right: Pixels, - pub border_top: Pixels, - pub border_bottom: Pixels, -} - -impl Quad { - pub fn vertices(&self) -> impl Iterator> { - let x1 = self.bounds.origin.x; - let y1 = self.bounds.origin.y; - let x2 = x1 + self.bounds.size.width; - let y2 = y1 + self.bounds.size.height; - [ - Point::new(x1, y1), - Point::new(x2, y1), - Point::new(x2, y2), - Point::new(x1, y2), - ] - .into_iter() - } -} - -unsafe impl Zeroable for Quad {} - -unsafe impl Pod for Quad {} - -#[derive(Debug, Clone)] -pub struct Glyph { - pub order: f32, - pub bounds: Bounds, - pub color: Hsla, - // ... -} - -impl From for Primitive { - fn from(quad: Quad) -> Self { - Primitive::Quad(quad) - } -} - -impl From for Primitive { - fn from(glyph: Glyph) -> Self { - Primitive::Glyph(glyph) - } -} diff --git a/crates/storybook/src/gpui3/shader.frag.wgsl b/crates/storybook/src/gpui3/shader.frag.wgsl deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/shader.frag.wgsl +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/storybook/src/gpui3/shader.vert.wgsl b/crates/storybook/src/gpui3/shader.vert.wgsl deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/crates/storybook/src/gpui3/style.rs b/crates/storybook/src/gpui3/style.rs deleted file mode 100644 index 98d9a7395a6cc547438c7df300def56fe23b68d4..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/style.rs +++ /dev/null @@ -1,245 +0,0 @@ -use refineable::Refineable; - -pub use super::taffy::style::{ - AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent, - Overflow, Position, -}; -use super::{ - rems, AbsoluteLength, Bounds, DefiniteLength, Edges, EdgesRefinement, Hsla, Length, Pixels, - Point, PointRefinement, Rems, SharedString, Size, SizeRefinement, ViewContext, WindowContext, -}; -pub use gpui2::style::{FontStyle, FontWeight}; - -#[derive(Clone, Debug)] -pub struct FontSize(f32); - -#[derive(Clone, Refineable, Debug)] -#[refineable(debug)] -pub struct Style { - /// What layout strategy should be used? - pub display: Display, - - // Overflow properties - /// How children overflowing their container should affect layout - #[refineable] - pub overflow: Point, - /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes. - pub scrollbar_width: f32, - - // Position properties - /// What should the `position` value of this struct use as a base offset? - pub position: Position, - /// How should the position of this element be tweaked relative to the layout defined? - #[refineable] - pub inset: Edges, - - // Size properies - /// Sets the initial size of the item - #[refineable] - pub size: Size, - /// Controls the minimum size of the item - #[refineable] - pub min_size: Size, - /// Controls the maximum size of the item - #[refineable] - pub max_size: Size, - /// Sets the preferred aspect ratio for the item. The ratio is calculated as width divided by height. - pub aspect_ratio: Option, - - // Spacing Properties - /// How large should the margin be on each side? - #[refineable] - pub margin: Edges, - /// How large should the padding be on each side? - #[refineable] - pub padding: Edges, - /// How large should the border be on each side? - #[refineable] - pub border_widths: Edges, - - // Alignment properties - /// How this node's children aligned in the cross/block axis? - pub align_items: Option, - /// How this node should be aligned in the cross/block axis. Falls back to the parents [`AlignItems`] if not set - pub align_self: Option, - /// How should content contained within this item be aligned in the cross/block axis - pub align_content: Option, - /// How should contained within this item be aligned in the main/inline axis - pub justify_content: Option, - /// How large should the gaps between items in a flex container be? - #[refineable] - pub gap: Size, - - // Flexbox properies - /// Which direction does the main axis flow in? - pub flex_direction: FlexDirection, - /// Should elements wrap, or stay in a single line? - pub flex_wrap: FlexWrap, - /// Sets the initial main axis size of the item - pub flex_basis: Length, - /// The relative rate at which this item grows when it is expanding to fill space, 0.0 is the default value, and this value must be positive. - pub flex_grow: f32, - /// The relative rate at which this item shrinks when it is contracting to fit into space, 1.0 is the default value, and this value must be positive. - pub flex_shrink: f32, - - /// The fill color of this element - pub fill: Option, - - /// The border color of this element - pub border_color: Option, - - /// The radius of the corners of this element - #[refineable] - pub corner_radii: CornerRadii, - - /// The color of text within this element. Cascades to children unless overridden. - pub text_color: Option, - - /// The font size in rems. - pub font_size: Option, - - pub font_family: Option, - - pub font_weight: Option, - - pub font_style: Option, -} - -#[derive(Refineable, Clone, Debug)] -#[refineable(debug)] -pub struct TextStyle { - pub color: Hsla, - pub font_family: SharedString, - pub font_size: Rems, - pub font_weight: FontWeight, - pub font_style: FontStyle, - pub underline: Underline, -} - -#[derive(Refineable, Clone, Default, Debug)] -#[refineable(debug)] -pub struct Underline { - pub origin: Point, - pub width: Pixels, - pub thickness: Pixels, - pub color: Hsla, - pub squiggly: bool, -} - -impl Style { - pub fn text_style(&self, cx: &WindowContext) -> Option { - if self.text_color.is_none() - && self.font_size.is_none() - && self.font_family.is_none() - && self.font_weight.is_none() - && self.font_style.is_none() - { - return None; - } - - Some(TextStyleRefinement { - color: self.text_color, - font_family: self.font_family.clone(), - font_size: self.font_size, - font_weight: self.font_weight, - font_style: self.font_style, - underline: None, - }) - } - - /// Paints the background of an element styled with this style. - pub fn paint_background(&self, bounds: Bounds, cx: &mut ViewContext) { - let rem_size = cx.rem_size(); - if let Some(color) = self.fill.as_ref().and_then(Fill::color) { - todo!(); - } - } - - /// Paints the foreground of an element styled with this style. - pub fn paint_foreground(&self, bounds: Bounds, cx: &mut ViewContext) { - let rem_size = cx.rem_size(); - - if let Some(color) = self.border_color { - let border = self.border_widths.to_pixels(rem_size); - if !border.is_empty() { - todo!(); - } - } - } -} - -impl Default for Style { - fn default() -> Self { - Style { - display: Display::Block, - overflow: Point { - x: Overflow::Visible, - y: Overflow::Visible, - }, - scrollbar_width: 0.0, - position: Position::Relative, - inset: Edges::auto(), - margin: Edges::::zero(), - padding: Edges::::zero(), - border_widths: Edges::::zero(), - size: Size::auto(), - min_size: Size::auto(), - max_size: Size::auto(), - aspect_ratio: None, - gap: Size::zero(), - // Aligment - align_items: None, - align_self: None, - align_content: None, - justify_content: None, - // Flexbox - flex_direction: FlexDirection::Row, - flex_wrap: FlexWrap::NoWrap, - flex_grow: 0.0, - flex_shrink: 1.0, - flex_basis: Length::Auto, - fill: None, - border_color: None, - corner_radii: CornerRadii::default(), - text_color: None, - font_size: Some(rems(1.)), - font_family: None, - font_weight: None, - font_style: None, - } - } -} - -#[derive(Clone, Debug)] -pub enum Fill { - Color(Hsla), -} - -impl Fill { - pub fn color(&self) -> Option { - match self { - Fill::Color(color) => Some(*color), - } - } -} - -impl Default for Fill { - fn default() -> Self { - Self::Color(Hsla::default()) - } -} - -impl From for Fill { - fn from(color: Hsla) -> Self { - Self::Color(color) - } -} - -#[derive(Clone, Refineable, Default, Debug)] -#[refineable(debug)] -pub struct CornerRadii { - top_left: AbsoluteLength, - top_right: AbsoluteLength, - bottom_left: AbsoluteLength, - bottom_right: AbsoluteLength, -} diff --git a/crates/storybook/src/gpui3/taffy.rs b/crates/storybook/src/gpui3/taffy.rs deleted file mode 100644 index cfdf1ff06f3ed1746148adb45cfe59dd1ada4616..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/taffy.rs +++ /dev/null @@ -1,238 +0,0 @@ -use super::{ - AbsoluteLength, Bounds, DefiniteLength, Edges, Layout, Length, Pixels, Point, Result, Size, - Style, -}; -use gpui2::taffy::{self, Taffy}; -use std::fmt::Debug; -pub use taffy::*; - -pub use gpui2::taffy::tree::NodeId as LayoutId; -pub struct TaffyLayoutEngine(Taffy); - -impl TaffyLayoutEngine { - pub fn new() -> Self { - TaffyLayoutEngine(Taffy::new()) - } - - pub fn request_layout( - &mut self, - style: Style, - rem_size: Pixels, - children: &[LayoutId], - ) -> Result { - let style = style.to_taffy(rem_size); - if children.is_empty() { - Ok(self.0.new_leaf(style)?) - } else { - Ok(self.0.new_with_children(style, children)?) - } - } - - pub fn layout(&mut self, id: LayoutId) -> Result { - Ok(self.0.layout(id).map(Into::into)?) - } -} - -trait ToTaffy { - fn to_taffy(&self, rem_size: Pixels) -> Output; -} - -impl ToTaffy for Style { - fn to_taffy(&self, rem_size: Pixels) -> taffy::style::Style { - taffy::style::Style { - display: self.display, - overflow: self.overflow.clone().into(), - scrollbar_width: self.scrollbar_width, - position: self.position, - inset: self.inset.to_taffy(rem_size), - size: self.size.to_taffy(rem_size), - min_size: self.min_size.to_taffy(rem_size), - max_size: self.max_size.to_taffy(rem_size), - aspect_ratio: self.aspect_ratio, - margin: self.margin.to_taffy(rem_size), - padding: self.padding.to_taffy(rem_size), - border: self.border_widths.to_taffy(rem_size), - align_items: self.align_items, - align_self: self.align_self, - align_content: self.align_content, - justify_content: self.justify_content, - gap: self.gap.to_taffy(rem_size), - flex_direction: self.flex_direction, - flex_wrap: self.flex_wrap, - flex_basis: self.flex_basis.to_taffy(rem_size), - flex_grow: self.flex_grow, - flex_shrink: self.flex_shrink, - ..Default::default() // Ignore grid properties for now - } - } -} - -// impl ToTaffy for Bounds { -// type Output = taffy::prelude::Bounds; - -// fn to_taffy( -// &self, -// rem_size: Pixels, -// ) -> taffy::prelude::Bounds { -// taffy::prelude::Bounds { -// origin: self.origin.to_taffy(rem_size), -// size: self.size.to_taffy(rem_size), -// } -// } -// } - -impl ToTaffy for Length { - fn to_taffy(&self, rem_size: Pixels) -> taffy::prelude::LengthPercentageAuto { - match self { - Length::Definite(length) => length.to_taffy(rem_size), - Length::Auto => taffy::prelude::LengthPercentageAuto::Auto, - } - } -} - -impl ToTaffy for Length { - fn to_taffy(&self, rem_size: Pixels) -> taffy::prelude::Dimension { - match self { - Length::Definite(length) => length.to_taffy(rem_size), - Length::Auto => taffy::prelude::Dimension::Auto, - } - } -} - -impl ToTaffy for DefiniteLength { - fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentage { - match self { - DefiniteLength::Absolute(length) => match length { - AbsoluteLength::Pixels(pixels) => { - taffy::style::LengthPercentage::Length(pixels.into()) - } - AbsoluteLength::Rems(rems) => { - taffy::style::LengthPercentage::Length((*rems * rem_size).into()) - } - }, - DefiniteLength::Fraction(fraction) => { - taffy::style::LengthPercentage::Percent(*fraction) - } - } - } -} - -impl ToTaffy for DefiniteLength { - fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentageAuto { - match self { - DefiniteLength::Absolute(length) => match length { - AbsoluteLength::Pixels(pixels) => { - taffy::style::LengthPercentageAuto::Length(pixels.into()) - } - AbsoluteLength::Rems(rems) => { - taffy::style::LengthPercentageAuto::Length((*rems * rem_size).into()) - } - }, - DefiniteLength::Fraction(fraction) => { - taffy::style::LengthPercentageAuto::Percent(*fraction) - } - } - } -} - -impl ToTaffy for DefiniteLength { - fn to_taffy(&self, rem_size: Pixels) -> taffy::style::Dimension { - match self { - DefiniteLength::Absolute(length) => match length { - AbsoluteLength::Pixels(pixels) => taffy::style::Dimension::Length(pixels.into()), - AbsoluteLength::Rems(rems) => { - taffy::style::Dimension::Length((*rems * rem_size).into()) - } - }, - DefiniteLength::Fraction(fraction) => taffy::style::Dimension::Percent(*fraction), - } - } -} - -impl ToTaffy for AbsoluteLength { - fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentage { - match self { - AbsoluteLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(pixels.into()), - AbsoluteLength::Rems(rems) => { - taffy::style::LengthPercentage::Length((*rems * rem_size).into()) - } - } - } -} - -impl From> for Point -where - T: Into, -{ - fn from(point: taffy::geometry::Point) -> Point { - Point { - x: point.x.into(), - y: point.y.into(), - } - } -} - -impl Into> for Point -where - T: Into, -{ - fn into(self) -> taffy::geometry::Point { - taffy::geometry::Point { - x: self.x.into(), - y: self.y.into(), - } - } -} - -impl + Clone + Debug, U> ToTaffy> for Size { - fn to_taffy(&self, rem_size: Pixels) -> taffy::geometry::Size { - taffy::geometry::Size { - width: self.width.to_taffy(rem_size).into(), - height: self.height.to_taffy(rem_size).into(), - } - } -} - -impl ToTaffy> for Edges -where - T: ToTaffy + Clone + Debug, -{ - fn to_taffy(&self, rem_size: Pixels) -> taffy::geometry::Rect { - taffy::geometry::Rect { - top: self.top.to_taffy(rem_size).into(), - right: self.right.to_taffy(rem_size).into(), - bottom: self.bottom.to_taffy(rem_size).into(), - left: self.left.to_taffy(rem_size).into(), - } - } -} - -impl From> for Size -where - S: Into, -{ - fn from(value: taffy::geometry::Size) -> Self { - Self { - width: value.width.into(), - height: value.height.into(), - } - } -} - -impl From<&taffy::tree::Layout> for Layout { - fn from(layout: &taffy::tree::Layout) -> Self { - Layout { - order: layout.order, - bounds: Bounds { - origin: layout.location.into(), - size: layout.size.into(), - }, - } - } -} - -impl From for Pixels { - fn from(pixels: f32) -> Self { - Pixels(pixels) - } -} diff --git a/crates/storybook/src/gpui3/window.rs b/crates/storybook/src/gpui3/window.rs deleted file mode 100644 index 28e0bbb8c4c415c6f51bd5276adff0ce5c221daa..0000000000000000000000000000000000000000 --- a/crates/storybook/src/gpui3/window.rs +++ /dev/null @@ -1,231 +0,0 @@ -use super::{ - px, taffy::LayoutId, AppContext, Bounds, Context, EntityId, Handle, Pixels, Style, - TaffyLayoutEngine, -}; -use anyhow::Result; -use derive_more::{Deref, DerefMut}; -use gpui2::Reference; -use std::{ - any::{Any, TypeId}, - marker::PhantomData, -}; - -pub struct AnyWindow {} - -pub struct Window { - id: WindowId, - rem_size: Pixels, - layout_engine: TaffyLayoutEngine, - pub(crate) root_view: Option>, -} - -impl Window { - pub fn new(id: WindowId) -> Window { - Window { - id, - layout_engine: TaffyLayoutEngine::new(), - rem_size: px(16.), - root_view: None, - } - } -} - -#[derive(Deref, DerefMut)] -pub struct WindowContext<'a, 'b> { - #[deref] - #[deref_mut] - app: Reference<'a, AppContext>, - window: Reference<'b, Window>, -} - -impl<'a, 'w> WindowContext<'a, 'w> { - pub(crate) fn mutable(app: &'a mut AppContext, window: &'w mut Window) -> Self { - Self { - app: Reference::Mutable(app), - window: Reference::Mutable(window), - } - } - - pub(crate) fn immutable(app: &'a AppContext, window: &'w Window) -> Self { - Self { - app: Reference::Immutable(app), - window: Reference::Immutable(window), - } - } - - pub fn request_layout( - &mut self, - style: Style, - children: impl IntoIterator, - ) -> Result { - self.app.layout_id_buffer.clear(); - self.app.layout_id_buffer.extend(children.into_iter()); - let rem_size = self.rem_size(); - - self.window - .layout_engine - .request_layout(style, rem_size, &self.app.layout_id_buffer) - } - - pub fn layout(&mut self, layout_id: LayoutId) -> Result { - Ok(self - .window - .layout_engine - .layout(layout_id) - .map(Into::into)?) - } - - pub fn rem_size(&self) -> Pixels { - self.window.rem_size - } - - fn update_window( - &mut self, - window_id: WindowId, - update: impl FnOnce(&mut WindowContext) -> R, - ) -> Result { - if window_id == self.window.id { - Ok(update(self)) - } else { - self.app.update_window(window_id, update) - } - } -} - -impl Context for WindowContext<'_, '_> { - type EntityContext<'a, 'w, T: 'static> = ViewContext<'a, 'w, T>; - - fn entity( - &mut self, - build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, - ) -> Handle { - let id = self.entities.insert(None); - let entity = Box::new(build_entity(&mut ViewContext::mutable( - &mut *self.app, - &mut self.window, - id, - ))); - self.entities.get_mut(id).unwrap().replace(entity); - - Handle { - id, - entity_type: PhantomData, - } - } - - fn update_entity( - &mut self, - handle: &Handle, - update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, - ) -> R { - let mut entity = self - .app - .entities - .get_mut(handle.id) - .unwrap() - .take() - .unwrap() - .downcast::() - .unwrap(); - - let result = update( - &mut *entity, - &mut ViewContext::mutable(&mut *self.app, &mut *self.window, handle.id), - ); - - self.app - .entities - .get_mut(handle.id) - .unwrap() - .replace(entity); - - result - } -} - -#[derive(Deref, DerefMut)] -pub struct ViewContext<'a, 'w, T> { - #[deref] - #[deref_mut] - window_cx: WindowContext<'a, 'w>, - entity_type: PhantomData, - entity_id: EntityId, -} - -impl<'a, 'w, T: 'static> ViewContext<'a, 'w, T> { - // fn update(&mut self, update: impl FnOnce(&mut T, &mut Self) -> R) -> R { - - // self.window_cx.update_entity(handle, update) - - // let mut entity = self.window_cx.app.entities.remove(&self.entity_id).unwrap(); - // let result = update(entity.downcast_mut::().unwrap(), self); - // self.window_cx - // .app - // .entities - // .insert(self.entity_id, Box::new(entity)); - // result - // } - - fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self { - Self { - window_cx: WindowContext::mutable(app, window), - entity_id, - entity_type: PhantomData, - } - } - - fn immutable(app: &'a AppContext, window: &'w Window, entity_id: EntityId) -> Self { - Self { - window_cx: WindowContext::immutable(app, window), - entity_id, - entity_type: PhantomData, - } - } -} - -impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> { - type EntityContext<'b, 'c, U: 'static> = ViewContext<'b, 'c, U>; - - fn entity( - &mut self, - build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T2>) -> T2, - ) -> Handle { - self.window_cx.entity(build_entity) - } - - fn update_entity( - &mut self, - handle: &Handle, - update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R, - ) -> R { - self.window_cx.update_entity(handle, update) - } -} - -// #[derive(Clone, Copy, Eq, PartialEq, Hash)] -slotmap::new_key_type! { pub struct WindowId; } - -pub struct WindowHandle { - id: WindowId, - state_type: PhantomData, -} - -impl WindowHandle { - pub fn new(id: WindowId) -> Self { - WindowHandle { - id, - state_type: PhantomData, - } - } -} - -pub struct AnyWindowHandle { - id: WindowId, - state_type: TypeId, -} - -#[derive(Clone)] -pub struct Layout { - pub order: u32, - pub bounds: Bounds, -} diff --git a/crates/storybook/src/storybook.rs b/crates/storybook/src/storybook.rs index 1e96a6ec73d54efaed06b9f71c708bedcef4a260..04e1038988fc640d54a2d1d289319af7c832d7c2 100644 --- a/crates/storybook/src/storybook.rs +++ b/crates/storybook/src/storybook.rs @@ -12,7 +12,6 @@ use simplelog::SimpleLogger; mod collab_panel; mod components; mod element_ext; -mod gpui3; mod theme; mod workspace;