Detailed changes
@@ -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"
@@ -35,6 +35,7 @@ members = [
"crates/gpui_macros",
"crates/gpui2",
"crates/gpui2_macros",
+ "crates/gpui3",
"crates/install_cli",
"crates/journal",
"crates/language",
@@ -8,6 +8,9 @@ publish = false
name = "storybook"
path = "src/storybook.rs"
+[features]
+test-support = []
+
[dependencies]
anyhow.workspace = true
bytemuck = "1.14.0"
@@ -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<dyn Platform>,
- pub(crate) entities: SlotMap<EntityId, Option<Box<dyn Any>>>,
- pub(crate) windows: SlotMap<WindowId, Option<Window>>,
- // We recycle this memory across layout requests.
- pub(crate) layout_id_buffer: Vec<LayoutId>,
-}
-
-impl AppContext {
- pub fn new(platform: Rc<dyn Platform>) -> 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<S: 'static>(
- &mut self,
- build_root_view: impl FnOnce(&mut WindowContext) -> View<S>,
- ) -> WindowHandle<S> {
- 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<R>(
- &mut self,
- window_id: WindowId,
- update: impl FnOnce(&mut WindowContext) -> R,
- ) -> Result<R> {
- 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<T: 'static>(
- &mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
- ) -> Handle<T> {
- 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<T: 'static, R>(
- &mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
- ) -> R {
- let mut entity = self
- .entities
- .get_mut(handle.id)
- .unwrap()
- .take()
- .unwrap()
- .downcast::<T>()
- .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<T>,
- 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<R>(&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::<T>().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<U: 'static>(
- &mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, U>) -> U,
- ) -> Handle<U> {
- self.app.entity(build_entity)
- }
-
- fn update_entity<U: 'static, R>(
- &mut self,
- handle: &Handle<U>,
- update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
- ) -> R {
- self.app.update_entity(handle, update)
- }
-}
-
-pub struct Handle<T> {
- pub(crate) id: EntityId,
- pub(crate) entity_type: PhantomData<T>,
-}
-
-slotmap::new_key_type! { pub struct EntityId; }
-
-impl<T: 'static> Handle<T> {
- 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<C: Context, R>(
- &self,
- cx: &mut C,
- update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
- ) -> R {
- cx.update_entity(self, update)
- }
-}
-
-impl<T> Clone for Handle<T> {
- fn clone(&self) -> Self {
- Self {
- id: self.id,
- entity_type: PhantomData,
- }
- }
-}
@@ -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<C: From<Rgba>>(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<E: de::Error>(self, value: &str) -> Result<Rgba, E> {
- 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<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
- deserializer.deserialize_str(RgbaVisitor)
- }
-}
-
-impl From<Hsla> 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<Self, Self::Error> {
- 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<Rgba> 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<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: Deserializer<'de>,
- {
- // First, deserialize it into Rgba
- let rgba = Rgba::deserialize(deserializer)?;
-
- // Then, use the From<Rgba> for Hsla implementation to convert it
- Ok(Hsla::from(rgba))
- }
-}
@@ -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<Self::State>,
- ) -> Result<(LayoutId, Self::FrameState)>;
-
- fn paint(
- &mut self,
- layout: Layout,
- state: &mut Self::State,
- frame_state: &mut Self::FrameState,
- cx: &mut ViewContext<Self::State>,
- ) -> Result<()>;
-}
-
-pub trait ParentElement<S> {
- fn child(self, child: impl IntoAnyElement<S>) -> Self;
-}
-
-trait ElementObject<S> {
- fn layout(&mut self, state: &mut S, cx: &mut ViewContext<S>) -> Result<LayoutId>;
- fn paint(
- &mut self,
- parent_origin: super::Point<Pixels>,
- state: &mut S,
- cx: &mut ViewContext<S>,
- ) -> Result<()>;
-}
-
-struct RenderedElement<E: Element> {
- element: E,
- phase: ElementRenderPhase<E::FrameState>,
-}
-
-#[derive(Default)]
-enum ElementRenderPhase<S> {
- #[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<E::State> for
-/// improved usability.
-impl<E: Element> RenderedElement<E> {
- fn new(element: E) -> Self {
- RenderedElement {
- element,
- phase: ElementRenderPhase::Rendered,
- }
- }
-}
-
-impl<E: Element> ElementObject<E::State> for RenderedElement<E> {
- fn layout(&mut self, state: &mut E::State, cx: &mut ViewContext<E::State>) -> Result<LayoutId> {
- 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<Pixels>,
- state: &mut E::State,
- cx: &mut ViewContext<E::State>,
- ) -> 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<S>(Box<dyn ElementObject<S>>);
-
-impl<S> AnyElement<S> {
- pub fn layout(&mut self, state: &mut S, cx: &mut ViewContext<S>) -> Result<LayoutId> {
- self.0.layout(state, cx)
- }
-
- pub fn paint(
- &mut self,
- parent_origin: Point<Pixels>,
- state: &mut S,
- cx: &mut ViewContext<S>,
- ) -> Result<()> {
- self.0.paint(parent_origin, state, cx)
- }
-}
-
-pub trait IntoAnyElement<S> {
- fn into_any(self) -> AnyElement<S>;
-}
-
-impl<E: Element> IntoAnyElement<E::State> for E {
- fn into_any(self) -> AnyElement<E::State> {
- AnyElement(Box::new(RenderedElement::new(self)))
- }
-}
-
-impl<S> IntoAnyElement<S> for AnyElement<S> {
- fn into_any(self) -> AnyElement<S> {
- self
- }
-}
-
-#[derive(Clone)]
-pub struct View<S> {
- state: Handle<S>,
- render: Rc<dyn Fn(&mut S, &mut ViewContext<S>) -> AnyElement<S>>,
-}
-
-pub fn view<S: 'static, E: Element<State = S>>(
- state: Handle<S>,
- render: impl 'static + Fn(&mut S, &mut ViewContext<S>) -> E,
-) -> View<S> {
- View {
- state,
- render: Rc::new(move |state, cx| render(state, cx).into_any()),
- }
-}
-
-impl<S: 'static> View<S> {
- pub fn into_any<ParentState>(self) -> AnyView<ParentState> {
- AnyView {
- view: Rc::new(RefCell::new(self)),
- parent_state_type: PhantomData,
- }
- }
-}
-
-impl<S: 'static> Element for View<S> {
- type State = ();
- type FrameState = AnyElement<S>;
-
- fn layout(
- &mut self,
- _: &mut Self::State,
- cx: &mut ViewContext<Self::State>,
- ) -> 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<Self::State>,
- ) -> 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<dyn Any>)>;
- fn paint(
- &mut self,
- layout: Layout,
- element: &mut dyn Any,
- cx: &mut WindowContext,
- ) -> Result<()>;
-}
-
-impl<S: 'static> ViewObject for View<S> {
- fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)> {
- 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<dyn Any>;
- 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::<AnyElement<S>>()
- .unwrap()
- .paint(layout.bounds.origin, state, cx)
- })
- }
-}
-
-pub struct AnyView<S> {
- view: Rc<RefCell<dyn ViewObject>>,
- parent_state_type: PhantomData<S>,
-}
-
-impl<S: 'static> Element for AnyView<S> {
- type State = S;
- type FrameState = Box<dyn Any>;
-
- fn layout(
- &mut self,
- _: &mut Self::State,
- cx: &mut ViewContext<Self::State>,
- ) -> 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<Self::State>,
- ) -> Result<()> {
- self.view.borrow_mut().paint(layout, element, cx)
- }
-}
-
-impl<S> Clone for AnyView<S> {
- fn clone(&self) -> Self {
- Self {
- view: self.view.clone(),
- parent_state_type: PhantomData,
- }
- }
-}
@@ -1,8 +0,0 @@
-pub mod div;
-pub mod editor;
-
-use super::*;
-use std::marker::PhantomData;
-
-pub use div::div;
-pub use editor::field;
@@ -1,38 +0,0 @@
-use super::{
- Element, IntoAnyElement, Layout, LayoutId, ParentElement, PhantomData, Result, ViewContext,
-};
-
-pub struct Div<S>(PhantomData<S>);
-
-impl<S: 'static> Element for Div<S> {
- type State = S;
- type FrameState = ();
-
- fn layout(
- &mut self,
- state: &mut Self::State,
- cx: &mut ViewContext<Self::State>,
- ) -> Result<(LayoutId, Self::FrameState)> {
- todo!()
- }
-
- fn paint(
- &mut self,
- layout: Layout,
- state: &mut Self::State,
- frame_state: &mut Self::FrameState,
- cx: &mut ViewContext<Self::State>,
- ) -> Result<()> {
- todo!()
- }
-}
-
-impl<S> ParentElement<S> for Div<S> {
- fn child(self, child: impl IntoAnyElement<S>) -> Self {
- todo!()
- }
-}
-
-pub fn div<S>() -> Div<S> {
- todo!()
-}
@@ -1,61 +0,0 @@
-use super::{Element, Handle, Layout, LayoutId, Result, SharedString, ViewContext};
-use std::marker::PhantomData;
-
-pub fn field<S>(editor: Handle<Editor>) -> EditorElement<S> {
- EditorElement {
- editor,
- field: true,
- placeholder_text: None,
- parent_state: PhantomData,
- }
-}
-
-pub struct EditorElement<S> {
- editor: Handle<Editor>,
- field: bool,
- placeholder_text: Option<SharedString>,
- parent_state: PhantomData<S>,
-}
-
-impl<S> EditorElement<S> {
- pub fn field(mut self) -> Self {
- self.field = true;
- self
- }
-
- pub fn placeholder_text(mut self, text: impl Into<SharedString>) -> Self {
- self.placeholder_text = Some(text.into());
- self
- }
-}
-
-impl<S: 'static> Element for EditorElement<S> {
- type State = S;
- type FrameState = ();
-
- fn layout(
- &mut self,
- _: &mut Self::State,
- cx: &mut ViewContext<Self::State>,
- ) -> 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<Self::State>,
- ) -> Result<()> {
- self.editor.update(cx, |editor, cx| todo!())
- }
-}
-
-pub struct Editor {}
-
-impl Editor {
- pub fn new(_: &mut ViewContext<Self>) -> Self {
- Editor {}
- }
-}
@@ -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<T: Clone + Debug> {
- pub x: T,
- pub y: T,
-}
-
-impl<T: Clone + Debug> Point<T> {
- pub fn new(x: T, y: T) -> Self {
- Self { x, y }
- }
-}
-
-impl<T: Clone + Debug> Clone for Point<T> {
- fn clone(&self) -> Self {
- Self {
- x: self.x.clone(),
- y: self.y.clone(),
- }
- }
-}
-
-unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Point<T> {}
-
-unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Point<T> {}
-
-#[derive(Refineable, Default, Clone, Copy, Debug, PartialEq)]
-#[refineable(debug)]
-pub struct Size<T: Clone + Debug> {
- pub width: T,
- pub height: T,
-}
-
-impl Size<Length> {
- pub fn full() -> Self {
- Self {
- width: relative(1.),
- height: relative(1.),
- }
- }
-}
-
-impl Size<DefiniteLength> {
- pub fn zero() -> Self {
- Self {
- width: px(0.),
- height: px(0.),
- }
- }
-}
-
-impl Size<Length> {
- pub fn auto() -> Self {
- Self {
- width: Length::Auto,
- height: Length::Auto,
- }
- }
-}
-
-#[derive(Refineable, Clone, Default, Debug, PartialEq)]
-#[refineable(debug)]
-pub struct Bounds<T: Clone + Debug> {
- pub origin: Point<T>,
- pub size: Size<T>,
-}
-
-impl<T: Clone + Debug + Copy> Copy for Bounds<T> {}
-
-#[derive(Refineable, Clone, Default, Debug)]
-#[refineable(debug)]
-pub struct Edges<T: Clone + Debug> {
- pub top: T,
- pub right: T,
- pub bottom: T,
- pub left: T,
-}
-
-impl Edges<Length> {
- 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<DefiniteLength> {
- pub fn zero() -> Self {
- Self {
- top: px(0.),
- right: px(0.),
- bottom: px(0.),
- left: px(0.),
- }
- }
-}
-
-impl Edges<AbsoluteLength> {
- 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<Pixels> {
- 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<Pixels> {
- 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<Pixels> 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<Pixels> 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<Pixels> for AbsoluteLength {
- fn from(pixels: Pixels) -> Self {
- AbsoluteLength::Pixels(pixels)
- }
-}
-
-impl From<Rems> 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<Pixels> for DefiniteLength {
- fn from(pixels: Pixels) -> Self {
- Self::Absolute(pixels.into())
- }
-}
-
-impl From<Rems> for DefiniteLength {
- fn from(rems: Rems) -> Self {
- Self::Absolute(rems.into())
- }
-}
-
-impl From<AbsoluteLength> 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<T: From<DefiniteLength>>(fraction: f32) -> T {
- DefiniteLength::Fraction(fraction).into()
-}
-
-pub fn rems<T: From<Rems>>(rems: f32) -> T {
- Rems(rems).into()
-}
-
-pub fn px<T: From<Pixels>>(pixels: f32) -> T {
- Pixels(pixels).into()
-}
-
-pub fn auto() -> Length {
- Length::Auto
-}
-
-impl From<Pixels> for Length {
- fn from(pixels: Pixels) -> Self {
- Self::Definite(pixels.into())
- }
-}
-
-impl From<Rems> for Length {
- fn from(rems: Rems) -> Self {
- Self::Definite(rems.into())
- }
-}
-
-impl From<DefiniteLength> for Length {
- fn from(length: DefiniteLength) -> Self {
- Self::Definite(length)
- }
-}
-
-impl From<AbsoluteLength> 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())
- }
-}
@@ -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<T: 'static>(
- &mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
- ) -> Handle<T>;
-
- fn update_entity<T: 'static, R>(
- &mut self,
- handle: &Handle<T>,
- 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<T: Into<ArcCow<'static, str>>> From<T> for SharedString {
- fn from(value: T) -> Self {
- Self(value.into())
- }
-}
-
-struct Workspace {
- left_panel: AnyView<Self>,
-}
-
-fn workspace(cx: &mut WindowContext) -> View<Workspace> {
- 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<editor::Editor>,
-}
-
-fn collab_panel(cx: &mut WindowContext) -> View<CollabPanel> {
- 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 {
- 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));
- }
-}
@@ -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<dyn PlatformWindow>;
-}
-
-pub trait PlatformWindow: HasRawWindowHandle + HasRawDisplayHandle {}
-
-#[derive(Debug)]
-pub struct WindowOptions<'a> {
- pub bounds: WindowBounds,
- pub titlebar: Option<TitlebarOptions<'a>>,
- 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<Point<f32>>,
-}
-
-#[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<f32>),
-}
@@ -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<u32>;
-}
-
-impl Renderer {
- pub async fn new<W>(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()));
- }
-}
@@ -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<slotmap::DefaultKey, Primitive>,
- splitter: BspSplitter<slotmap::DefaultKey>,
-}
-
-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<Primitive>, 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<Quad>,
- pub glyphs: Vec<Glyph>,
-}
-
-#[derive(Debug, Clone, Copy)]
-#[repr(C)]
-pub struct Quad {
- pub order: f32,
- pub bounds: Bounds<Pixels>,
- 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<Item = Point<Pixels>> {
- 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<Pixels>,
- pub color: Hsla,
- // ...
-}
-
-impl From<Quad> for Primitive {
- fn from(quad: Quad) -> Self {
- Primitive::Quad(quad)
- }
-}
-
-impl From<Glyph> for Primitive {
- fn from(glyph: Glyph) -> Self {
- Primitive::Glyph(glyph)
- }
-}
@@ -1 +0,0 @@
-
@@ -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<Overflow>,
- /// 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<Length>,
-
- // Size properies
- /// Sets the initial size of the item
- #[refineable]
- pub size: Size<Length>,
- /// Controls the minimum size of the item
- #[refineable]
- pub min_size: Size<Length>,
- /// Controls the maximum size of the item
- #[refineable]
- pub max_size: Size<Length>,
- /// Sets the preferred aspect ratio for the item. The ratio is calculated as width divided by height.
- pub aspect_ratio: Option<f32>,
-
- // Spacing Properties
- /// How large should the margin be on each side?
- #[refineable]
- pub margin: Edges<Length>,
- /// How large should the padding be on each side?
- #[refineable]
- pub padding: Edges<DefiniteLength>,
- /// How large should the border be on each side?
- #[refineable]
- pub border_widths: Edges<AbsoluteLength>,
-
- // Alignment properties
- /// How this node's children aligned in the cross/block axis?
- pub align_items: Option<AlignItems>,
- /// How this node should be aligned in the cross/block axis. Falls back to the parents [`AlignItems`] if not set
- pub align_self: Option<AlignSelf>,
- /// How should content contained within this item be aligned in the cross/block axis
- pub align_content: Option<AlignContent>,
- /// How should contained within this item be aligned in the main/inline axis
- pub justify_content: Option<JustifyContent>,
- /// How large should the gaps between items in a flex container be?
- #[refineable]
- pub gap: Size<DefiniteLength>,
-
- // 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<Fill>,
-
- /// The border color of this element
- pub border_color: Option<Hsla>,
-
- /// 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<Hsla>,
-
- /// The font size in rems.
- pub font_size: Option<Rems>,
-
- pub font_family: Option<SharedString>,
-
- pub font_weight: Option<FontWeight>,
-
- pub font_style: Option<FontStyle>,
-}
-
-#[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<Pixels>,
- pub width: Pixels,
- pub thickness: Pixels,
- pub color: Hsla,
- pub squiggly: bool,
-}
-
-impl Style {
- pub fn text_style(&self, cx: &WindowContext) -> Option<TextStyleRefinement> {
- 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<V: 'static>(&self, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
- 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<V: 'static>(&self, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
- 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::<Length>::zero(),
- padding: Edges::<DefiniteLength>::zero(),
- border_widths: Edges::<AbsoluteLength>::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<Hsla> {
- match self {
- Fill::Color(color) => Some(*color),
- }
- }
-}
-
-impl Default for Fill {
- fn default() -> Self {
- Self::Color(Hsla::default())
- }
-}
-
-impl From<Hsla> 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,
-}
@@ -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<LayoutId> {
- 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<Layout> {
- Ok(self.0.layout(id).map(Into::into)?)
- }
-}
-
-trait ToTaffy<Output> {
- fn to_taffy(&self, rem_size: Pixels) -> Output;
-}
-
-impl ToTaffy<taffy::style::Style> 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<Length> {
-// type Output = taffy::prelude::Bounds<taffy::prelude::LengthPercentageAuto>;
-
-// fn to_taffy(
-// &self,
-// rem_size: Pixels,
-// ) -> taffy::prelude::Bounds<taffy::prelude::LengthPercentageAuto> {
-// taffy::prelude::Bounds {
-// origin: self.origin.to_taffy(rem_size),
-// size: self.size.to_taffy(rem_size),
-// }
-// }
-// }
-
-impl ToTaffy<taffy::style::LengthPercentageAuto> 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<taffy::style::Dimension> 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<taffy::style::LengthPercentage> 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<taffy::style::LengthPercentageAuto> 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<taffy::style::Dimension> 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<taffy::style::LengthPercentage> 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<T, T2: Clone + Debug> From<taffy::geometry::Point<T>> for Point<T2>
-where
- T: Into<T2>,
-{
- fn from(point: taffy::geometry::Point<T>) -> Point<T2> {
- Point {
- x: point.x.into(),
- y: point.y.into(),
- }
- }
-}
-
-impl<T: Clone + Debug, T2> Into<taffy::geometry::Point<T2>> for Point<T>
-where
- T: Into<T2>,
-{
- fn into(self) -> taffy::geometry::Point<T2> {
- taffy::geometry::Point {
- x: self.x.into(),
- y: self.y.into(),
- }
- }
-}
-
-impl<T: ToTaffy<U> + Clone + Debug, U> ToTaffy<taffy::geometry::Size<U>> for Size<T> {
- fn to_taffy(&self, rem_size: Pixels) -> taffy::geometry::Size<U> {
- taffy::geometry::Size {
- width: self.width.to_taffy(rem_size).into(),
- height: self.height.to_taffy(rem_size).into(),
- }
- }
-}
-
-impl<T, U> ToTaffy<taffy::geometry::Rect<U>> for Edges<T>
-where
- T: ToTaffy<U> + Clone + Debug,
-{
- fn to_taffy(&self, rem_size: Pixels) -> taffy::geometry::Rect<U> {
- 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<S, T: Clone + Default + Debug> From<taffy::geometry::Size<S>> for Size<T>
-where
- S: Into<T>,
-{
- fn from(value: taffy::geometry::Size<S>) -> 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<f32> for Pixels {
- fn from(pixels: f32) -> Self {
- Pixels(pixels)
- }
-}
@@ -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<Box<dyn Any>>,
-}
-
-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<Item = LayoutId>,
- ) -> Result<LayoutId> {
- 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<Layout> {
- Ok(self
- .window
- .layout_engine
- .layout(layout_id)
- .map(Into::into)?)
- }
-
- pub fn rem_size(&self) -> Pixels {
- self.window.rem_size
- }
-
- fn update_window<R>(
- &mut self,
- window_id: WindowId,
- update: impl FnOnce(&mut WindowContext) -> R,
- ) -> Result<R> {
- 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<T: 'static>(
- &mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
- ) -> Handle<T> {
- 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<T: 'static, R>(
- &mut self,
- handle: &Handle<T>,
- 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::<T>()
- .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<T>,
- entity_id: EntityId,
-}
-
-impl<'a, 'w, T: 'static> ViewContext<'a, 'w, T> {
- // fn update<R>(&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::<T>().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<T2: 'static>(
- &mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T2>) -> T2,
- ) -> Handle<T2> {
- self.window_cx.entity(build_entity)
- }
-
- fn update_entity<U: 'static, R>(
- &mut self,
- handle: &Handle<U>,
- 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<S> {
- id: WindowId,
- state_type: PhantomData<S>,
-}
-
-impl<S> WindowHandle<S> {
- 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<Pixels>,
-}
@@ -12,7 +12,6 @@ use simplelog::SimpleLogger;
mod collab_panel;
mod components;
mod element_ext;
-mod gpui3;
mod theme;
mod workspace;