mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-26 10:40:54 +00:00
Checkpoint
This commit is contained in:
parent
f4d8763d2b
commit
ff7b25c538
6 changed files with 146 additions and 133 deletions
|
@ -1,70 +1,78 @@
|
|||
// use crate::element::{LayoutContext, PaintContext};
|
||||
// use gpui::{geometry::rect::RectF, LayoutEngine};
|
||||
// use util::ResultExt;
|
||||
use crate::{layout_context::LayoutContext, paint_context::PaintContext};
|
||||
use gpui::{geometry::rect::RectF, LayoutEngine, LayoutId};
|
||||
use util::ResultExt;
|
||||
|
||||
// use crate::element::AnyElement;
|
||||
/// Makes a new, playground-style element into a legacy element.
|
||||
pub struct AdapterElement<V>(pub(crate) crate::element::AnyElement<V>);
|
||||
|
||||
// pub struct Adapter<V>(pub(crate) AnyElement<V>);
|
||||
impl<V: 'static> gpui::Element<V> for AdapterElement<V> {
|
||||
type LayoutState = Option<(LayoutEngine, LayoutId)>;
|
||||
type PaintState = ();
|
||||
|
||||
// impl<V: 'static> gpui::Element<V> for Adapter<V> {
|
||||
// type LayoutState = Option<LayoutEngine>;
|
||||
// type PaintState = ();
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: gpui::SizeConstraint,
|
||||
view: &mut V,
|
||||
cx: &mut gpui::LayoutContext<V>,
|
||||
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
|
||||
cx.push_layout_engine(LayoutEngine::new());
|
||||
|
||||
// fn layout(
|
||||
// &mut self,
|
||||
// constraint: gpui::SizeConstraint,
|
||||
// view: &mut V,
|
||||
// cx: &mut LayoutContext<V>,
|
||||
// ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
|
||||
// cx.push_layout_engine(LayoutEngine::new());
|
||||
// let node = self.0.layout(view, cx).log_err();
|
||||
let size = constraint.max;
|
||||
let mut cx = LayoutContext::new(cx);
|
||||
let layout_id = self.0.layout(view, &mut cx).log_err();
|
||||
if let Some(layout_id) = layout_id {
|
||||
cx.layout_engine()
|
||||
.unwrap()
|
||||
.compute_layout(layout_id, constraint.max)
|
||||
.log_err();
|
||||
}
|
||||
|
||||
// if let Some(node) = node {
|
||||
// let layout_engine = cx.layout_engine().unwrap();
|
||||
// layout_engine.compute_layout(node, constraint.max).log_err();
|
||||
// }
|
||||
// let layout_engine = cx.pop_layout_engine();
|
||||
// debug_assert!(layout_engine.is_some());
|
||||
// (constraint.max, layout_engine)
|
||||
// }
|
||||
let layout_engine = cx.pop_layout_engine();
|
||||
debug_assert!(layout_engine.is_some(),
|
||||
"unexpected layout stack state. is there an unmatched pop_layout_engine in the called code?"
|
||||
);
|
||||
|
||||
// fn paint(
|
||||
// &mut self,
|
||||
// scene: &mut gpui::SceneBuilder,
|
||||
// bounds: RectF,
|
||||
// visible_bounds: RectF,
|
||||
// layout_engine: &mut Option<LayoutEngine>,
|
||||
// view: &mut V,
|
||||
// legacy_cx: &mut gpui::PaintContext<V>,
|
||||
// ) -> Self::PaintState {
|
||||
// legacy_cx.push_layout_engine(layout_engine.take().unwrap());
|
||||
// let mut cx = PaintContext::new(legacy_cx, scene);
|
||||
// self.0.paint(view, &mut cx).log_err();
|
||||
// *layout_engine = legacy_cx.pop_layout_engine();
|
||||
// debug_assert!(layout_engine.is_some());
|
||||
// }
|
||||
(constraint.max, layout_engine.zip(layout_id))
|
||||
}
|
||||
|
||||
// fn rect_for_text_range(
|
||||
// &self,
|
||||
// range_utf16: std::ops::Range<usize>,
|
||||
// bounds: RectF,
|
||||
// visible_bounds: RectF,
|
||||
// layout: &Self::LayoutState,
|
||||
// paint: &Self::PaintState,
|
||||
// view: &V,
|
||||
// cx: &gpui::ViewContext<V>,
|
||||
// ) -> Option<RectF> {
|
||||
// todo!("implement before merging to main")
|
||||
// }
|
||||
fn paint(
|
||||
&mut self,
|
||||
scene: &mut gpui::SceneBuilder,
|
||||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
layout_data: &mut Option<(LayoutEngine, LayoutId)>,
|
||||
view: &mut V,
|
||||
legacy_cx: &mut gpui::PaintContext<V>,
|
||||
) -> Self::PaintState {
|
||||
let (layout_engine, layout_id) = layout_data.take().unwrap();
|
||||
legacy_cx.push_layout_engine(layout_engine);
|
||||
let mut cx = PaintContext::new(legacy_cx, scene);
|
||||
self.0.paint(view, layout_id, &mut cx);
|
||||
*layout_data = legacy_cx.pop_layout_engine().zip(Some(layout_id));
|
||||
debug_assert!(layout_data.is_some());
|
||||
}
|
||||
|
||||
// fn debug(
|
||||
// &self,
|
||||
// bounds: RectF,
|
||||
// layout: &Self::LayoutState,
|
||||
// paint: &Self::PaintState,
|
||||
// view: &V,
|
||||
// cx: &gpui::ViewContext<V>,
|
||||
// ) -> gpui::serde_json::Value {
|
||||
// todo!("implement before merging to main")
|
||||
// }
|
||||
// }
|
||||
fn rect_for_text_range(
|
||||
&self,
|
||||
range_utf16: std::ops::Range<usize>,
|
||||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
layout: &Self::LayoutState,
|
||||
paint: &Self::PaintState,
|
||||
view: &V,
|
||||
cx: &gpui::ViewContext<V>,
|
||||
) -> Option<RectF> {
|
||||
todo!("implement before merging to main")
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
bounds: RectF,
|
||||
layout: &Self::LayoutState,
|
||||
paint: &Self::PaintState,
|
||||
view: &V,
|
||||
cx: &gpui::ViewContext<V>,
|
||||
) -> gpui::serde_json::Value {
|
||||
todo!("implement before merging to main")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ impl<V: 'static, D> Layout<V, D> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Element<V> {
|
||||
pub trait Element<V: 'static>: 'static {
|
||||
type Layout;
|
||||
|
||||
fn layout(
|
||||
|
@ -63,30 +63,33 @@ pub trait Element<V> {
|
|||
) where
|
||||
Self: Sized;
|
||||
|
||||
fn into_any(mut self) -> AnyElement<V>
|
||||
fn into_any(self) -> AnyElement<V>
|
||||
where
|
||||
Self: Sized,
|
||||
Self: 'static + Sized,
|
||||
{
|
||||
AnyElement(Box::new(ElementWithLayout {
|
||||
AnyElement(Box::new(ElementState {
|
||||
element: self,
|
||||
layout: None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
trait ElementTraitObject<V> {
|
||||
/// Used to make ElementState<V, E> into a trait object, so we can wrap it in AnyElement<V>.
|
||||
trait ElementStateObject<V> {
|
||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<LayoutId>;
|
||||
fn paint(&mut self, view: &mut V, layout_id: LayoutId, cx: &mut PaintContext<V>);
|
||||
}
|
||||
|
||||
struct ElementWithLayout<V, E: Element<V>> {
|
||||
/// A wrapper around an element that stores its layout state.
|
||||
struct ElementState<V: 'static, E: Element<V>> {
|
||||
element: E,
|
||||
layout: Option<Layout<V, E::Layout>>,
|
||||
}
|
||||
|
||||
impl<V, E: Element<V>> ElementTraitObject<V> for ElementWithLayout<V, E> {
|
||||
/// We blanket-implement the object-safe ElementStateObject interface to make ElementStates into trait objects
|
||||
impl<V, E: Element<V>> ElementStateObject<V> for ElementState<V, E> {
|
||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<LayoutId> {
|
||||
let layout = Element::layout(self, view, cx)?;
|
||||
let layout = self.element.layout(view, cx)?;
|
||||
let layout_id = layout.id;
|
||||
self.layout = Some(layout);
|
||||
Ok(layout_id)
|
||||
|
@ -94,23 +97,24 @@ impl<V, E: Element<V>> ElementTraitObject<V> for ElementWithLayout<V, E> {
|
|||
|
||||
fn paint(&mut self, view: &mut V, layout_id: LayoutId, cx: &mut PaintContext<V>) {
|
||||
let layout = self.layout.as_mut().expect("paint called before layout");
|
||||
Element::paint(self, view, layout, cx);
|
||||
self.element.paint(view, layout, cx)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AnyElement<V>(Box<dyn ElementTraitObject<V>>);
|
||||
/// A dynamic element.
|
||||
pub struct AnyElement<V>(Box<dyn ElementStateObject<V>>);
|
||||
|
||||
impl<V> AnyElement<V> {
|
||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<LayoutId> {
|
||||
pub fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<LayoutId> {
|
||||
self.0.layout(view, cx)
|
||||
}
|
||||
|
||||
fn paint(&mut self, view: &mut V, layout_id: LayoutId, cx: &mut PaintContext<V>) {
|
||||
pub fn paint(&mut self, view: &mut V, layout_id: LayoutId, cx: &mut PaintContext<V>) {
|
||||
self.0.paint(view, layout_id, cx)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ParentElement<V> {
|
||||
pub trait ParentElement<V: 'static> {
|
||||
fn children_mut(&mut self) -> &mut Vec<AnyElement<V>>;
|
||||
|
||||
fn child(mut self, child: impl IntoElement<V>) -> Self
|
||||
|
@ -136,7 +140,7 @@ pub trait ParentElement<V> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait IntoElement<V> {
|
||||
pub trait IntoElement<V: 'static> {
|
||||
type Element: Element<V>;
|
||||
|
||||
fn into_element(self) -> Self::Element;
|
||||
|
|
|
@ -9,7 +9,7 @@ use gpui::platform::MouseMovedEvent;
|
|||
use refineable::Refineable;
|
||||
use std::{cell::Cell, marker::PhantomData};
|
||||
|
||||
pub struct Hoverable<V, E: Element<V> + Styleable> {
|
||||
pub struct Hoverable<V: 'static, E: Element<V> + Styleable> {
|
||||
hovered: Cell<bool>,
|
||||
child_style: StyleRefinement,
|
||||
hovered_style: StyleRefinement,
|
||||
|
|
|
@ -11,7 +11,6 @@ pub struct LayoutContext<'a, 'b, 'c, 'd, V> {
|
|||
#[deref]
|
||||
#[deref_mut]
|
||||
pub(crate) legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>,
|
||||
pub(crate) scene: &'d mut gpui::SceneBuilder,
|
||||
}
|
||||
|
||||
impl<'a, 'b, V> RenderContext<'a, 'b, V> for LayoutContext<'a, 'b, '_, '_, V> {
|
||||
|
@ -33,11 +32,8 @@ impl<'a, 'b, V> RenderContext<'a, 'b, V> for LayoutContext<'a, 'b, '_, '_, V> {
|
|||
}
|
||||
|
||||
impl<'a, 'b, 'c, 'd, V: 'static> LayoutContext<'a, 'b, 'c, 'd, V> {
|
||||
pub fn new(
|
||||
legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>,
|
||||
scene: &'d mut gpui::SceneBuilder,
|
||||
) -> Self {
|
||||
Self { legacy_cx, scene }
|
||||
pub fn new(legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>) -> Self {
|
||||
Self { legacy_cx }
|
||||
}
|
||||
|
||||
pub fn add_layout_node<D>(
|
||||
|
|
|
@ -2,12 +2,10 @@ use crate::{
|
|||
element::{Element, IntoElement, Layout},
|
||||
layout_context::LayoutContext,
|
||||
paint_context::PaintContext,
|
||||
style::Style,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use gpui::{geometry::Size, text_layout::LineLayout, RenderContext};
|
||||
use gpui::text_layout::LineLayout;
|
||||
use parking_lot::Mutex;
|
||||
use refineable::Refineable;
|
||||
use std::sync::Arc;
|
||||
|
||||
impl<V: 'static, S: Into<ArcCow<'static, str>>> IntoElement<V> for S {
|
||||
|
@ -30,39 +28,40 @@ impl<V: 'static> Element<V> for Text {
|
|||
view: &mut V,
|
||||
cx: &mut LayoutContext<V>,
|
||||
) -> Result<Layout<V, Self::Layout>> {
|
||||
let rem_size = cx.rem_pixels();
|
||||
let fonts = cx.platform().fonts();
|
||||
let text_style = cx.text_style();
|
||||
let line_height = cx.font_cache().line_height(text_style.font_size);
|
||||
let layout_engine = cx.layout_engine().expect("no layout engine present");
|
||||
let text = self.text.clone();
|
||||
let layout = Arc::new(Mutex::new(None));
|
||||
// let rem_size = cx.rem_pixels();
|
||||
// let fonts = cx.platform().fonts();
|
||||
// let text_style = cx.text_style();
|
||||
// let line_height = cx.font_cache().line_height(text_style.font_size);
|
||||
// let layout_engine = cx.layout_engine().expect("no layout engine present");
|
||||
// let text = self.text.clone();
|
||||
// let layout = Arc::new(Mutex::new(None));
|
||||
|
||||
let style: Style = Style::default().refined(&self.metadata.style);
|
||||
let node_id = layout_engine.add_measured_node(style.to_taffy(rem_size), {
|
||||
let layout = layout.clone();
|
||||
move |params| {
|
||||
let line_layout = fonts.layout_line(
|
||||
text.as_ref(),
|
||||
text_style.font_size,
|
||||
&[(text.len(), text_style.to_run())],
|
||||
);
|
||||
// let style: Style = Style::default().refined(&self.metadata.style);
|
||||
// let node_id = layout_engine.add_measured_node(style.to_taffy(rem_size), {
|
||||
// let layout = layout.clone();
|
||||
// move |params| {
|
||||
// let line_layout = fonts.layout_line(
|
||||
// text.as_ref(),
|
||||
// text_style.font_size,
|
||||
// &[(text.len(), text_style.to_run())],
|
||||
// );
|
||||
|
||||
let size = Size {
|
||||
width: line_layout.width,
|
||||
height: line_height,
|
||||
};
|
||||
// let size = Size {
|
||||
// width: line_layout.width,
|
||||
// height: line_height,
|
||||
// };
|
||||
|
||||
layout.lock().replace(TextLayout {
|
||||
line_layout: Arc::new(line_layout),
|
||||
line_height,
|
||||
});
|
||||
// layout.lock().replace(TextLayout {
|
||||
// line_layout: Arc::new(line_layout),
|
||||
// line_height,
|
||||
// });
|
||||
|
||||
size
|
||||
}
|
||||
})?;
|
||||
// size
|
||||
// }
|
||||
// })?;
|
||||
|
||||
Ok((node_id, layout))
|
||||
// Ok((node_id, layout))
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn paint<'a>(
|
||||
|
@ -71,24 +70,26 @@ impl<V: 'static> Element<V> for Text {
|
|||
layout: &mut Layout<V, Self::Layout>,
|
||||
cx: &mut PaintContext<V>,
|
||||
) {
|
||||
let element_layout_lock = layout.from_element.lock();
|
||||
let element_layout = element_layout_lock
|
||||
.as_ref()
|
||||
.expect("layout has not been performed");
|
||||
let line_layout = element_layout.line_layout.clone();
|
||||
let line_height = element_layout.line_height;
|
||||
drop(element_layout_lock);
|
||||
// ) {
|
||||
// let element_layout_lock = layout.from_element.lock();
|
||||
// let element_layout = element_layout_lock
|
||||
// .as_ref()
|
||||
// .expect("layout has not been performed");
|
||||
// let line_layout = element_layout.line_layout.clone();
|
||||
// let line_height = element_layout.line_height;
|
||||
// drop(element_layout_lock);
|
||||
|
||||
let text_style = cx.text_style();
|
||||
let line =
|
||||
gpui::text_layout::Line::new(line_layout, &[(self.text.len(), text_style.to_run())]);
|
||||
line.paint(
|
||||
cx.scene,
|
||||
layout.from_engine.bounds.origin(),
|
||||
layout.from_engine.bounds,
|
||||
line_height,
|
||||
cx.legacy_cx,
|
||||
);
|
||||
// let text_style = cx.text_style();
|
||||
// let line =
|
||||
// gpui::text_layout::Line::new(line_layout, &[(self.text.len(), text_style.to_run())]);
|
||||
// line.paint(
|
||||
// cx.scene,
|
||||
// layout.from_engine.bounds.origin(),
|
||||
// layout.from_engine.bounds,
|
||||
// line_height,
|
||||
// cx.legacy_cx,
|
||||
// );
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use crate::element::{AnyElement, Element};
|
||||
use crate::{
|
||||
adapter::AdapterElement,
|
||||
element::{AnyElement, Element},
|
||||
};
|
||||
use gpui::ViewContext;
|
||||
|
||||
pub fn view<F, E>(mut render: F) -> ViewFn
|
||||
|
@ -17,6 +20,7 @@ impl gpui::Entity for ViewFn {
|
|||
|
||||
impl gpui::View for ViewFn {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> gpui::AnyElement<Self> {
|
||||
(self.0)(cx).adapt().into_any()
|
||||
use gpui::Element as _;
|
||||
AdapterElement((self.0)(cx)).into_any()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue