Checkpoint
This commit is contained in:
parent
2c6f692c56
commit
afff46b335
4 changed files with 123 additions and 54 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
use std::cell::Cell;
|
||||||
use std::{marker::PhantomData, rc::Rc};
|
use std::{marker::PhantomData, rc::Rc};
|
||||||
|
|
||||||
use crate::element::{AnyElement, PaintContext};
|
use crate::element::{AnyElement, PaintContext};
|
||||||
|
@ -15,20 +16,22 @@ use util::ResultExt;
|
||||||
type LayoutId = gpui::LayoutId;
|
type LayoutId = gpui::LayoutId;
|
||||||
|
|
||||||
#[derive(Deref, DerefMut)]
|
#[derive(Deref, DerefMut)]
|
||||||
pub struct Layout<V, E: Element<V>> {
|
pub struct Layout<V, D> {
|
||||||
id: LayoutId,
|
id: LayoutId,
|
||||||
engine_layout: Option<EngineLayout>,
|
engine_layout: Option<EngineLayout>,
|
||||||
#[deref]
|
#[deref]
|
||||||
#[deref_mut]
|
#[deref_mut]
|
||||||
element_data: E::Layout,
|
element_data: D,
|
||||||
|
view_type: PhantomData<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static, E: Element<V>> Layout<V, E> {
|
impl<V: 'static, D> Layout<V, D> {
|
||||||
pub fn new(id: LayoutId, engine_layout: Option<EngineLayout>, element_data: E::Layout) -> Self {
|
pub fn new(id: LayoutId, engine_layout: Option<EngineLayout>, element_data: D) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
engine_layout,
|
engine_layout,
|
||||||
element_data,
|
element_data,
|
||||||
|
view_type: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +39,10 @@ impl<V: 'static, E: Element<V>> Layout<V, E> {
|
||||||
self.engine_layout(cx).bounds
|
self.engine_layout(cx).bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn order(&mut self, cx: &mut PaintContext<V>) -> u32 {
|
||||||
|
self.engine_layout(cx).order
|
||||||
|
}
|
||||||
|
|
||||||
fn engine_layout(&mut self, cx: &mut PaintContext<'_, '_, '_, '_, V>) -> &mut EngineLayout {
|
fn engine_layout(&mut self, cx: &mut PaintContext<'_, '_, '_, '_, V>) -> &mut EngineLayout {
|
||||||
self.engine_layout
|
self.engine_layout
|
||||||
.get_or_insert_with(|| cx.computed_layout(self.id).log_err().unwrap_or_default())
|
.get_or_insert_with(|| cx.computed_layout(self.id).log_err().unwrap_or_default())
|
||||||
|
@ -45,12 +52,20 @@ impl<V: 'static, E: Element<V>> Layout<V, E> {
|
||||||
pub trait Element<V> {
|
pub trait Element<V> {
|
||||||
type Layout;
|
type Layout;
|
||||||
|
|
||||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<Layout<V, Self>>
|
fn layout(
|
||||||
|
&mut self,
|
||||||
|
view: &mut V,
|
||||||
|
cx: &mut LayoutContext<V>,
|
||||||
|
) -> Result<Layout<V, Self::Layout>>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
fn paint(&mut self, view: &mut V, cx: &mut PaintContext<V>)
|
fn paint(
|
||||||
where
|
&mut self,
|
||||||
|
view: &mut V,
|
||||||
|
layout: &mut Layout<V, Self::Layout>,
|
||||||
|
cx: &mut PaintContext<V>,
|
||||||
|
) where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
/// ## Helpers
|
/// ## Helpers
|
||||||
|
@ -106,7 +121,7 @@ pub fn div<V>() -> Div<V> {
|
||||||
impl<V: 'static> Element<V> for Div<V> {
|
impl<V: 'static> Element<V> for Div<V> {
|
||||||
type Layout = ();
|
type Layout = ();
|
||||||
|
|
||||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<Layout<V, Self>>
|
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<Layout<V, ()>>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -119,7 +134,7 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||||
cx.add_layout_node(self.style(), (), children)
|
cx.add_layout_node(self.style(), (), children)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(&mut self, view: &mut V, cx: &mut PaintContext<V>)
|
fn paint(&mut self, view: &mut V, layout: &mut Layout<V, ()>, cx: &mut PaintContext<V>)
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -128,12 +143,65 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Hoverable<V, E: Element<V> + Styleable> {
|
pub struct Hoverable<V, E: Element<V> + Styleable> {
|
||||||
default_style: Style,
|
hovered: Cell<bool>,
|
||||||
|
child_style: StyleRefinement,
|
||||||
hovered_style: StyleRefinement,
|
hovered_style: StyleRefinement,
|
||||||
child: E,
|
child: E,
|
||||||
view_type: PhantomData<V>,
|
view_type: PhantomData<V>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hoverable<V, E: Element<V> + Styleable>(mut child: E) -> Hoverable<V, E> {
|
||||||
|
Hoverable {
|
||||||
|
hovered: Cell::new(false),
|
||||||
|
child_style: child.declared_style().clone(),
|
||||||
|
hovered_style: Default::default(),
|
||||||
|
child,
|
||||||
|
view_type: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, E: Element<V> + Styleable> Styleable for Hoverable<V, E> {
|
||||||
|
type Style = E::Style;
|
||||||
|
|
||||||
|
fn declared_style(&mut self) -> &mut playground::style::StyleRefinement {
|
||||||
|
self.child.declared_style()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: 'static, E: Element<V> + Styleable> Element<V> for Hoverable<V, E> {
|
||||||
|
type Layout = E::Layout;
|
||||||
|
|
||||||
|
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<Layout<V, Self::Layout>>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
if self.hovered.get() {
|
||||||
|
// If hovered, refine the child's style with this element's style.
|
||||||
|
self.child.declared_style().refine(&self.hovered_style);
|
||||||
|
} else {
|
||||||
|
// Otherwise, set the child's style back to its original style.
|
||||||
|
*self.child.declared_style() = self.child_style.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.child.layout(view, cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(
|
||||||
|
&mut self,
|
||||||
|
view: &mut V,
|
||||||
|
layout: &mut Layout<V, Self::Layout>,
|
||||||
|
cx: &mut PaintContext<V>,
|
||||||
|
) where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let bounds = layout.bounds(cx);
|
||||||
|
let order = layout.order(cx);
|
||||||
|
self.hovered.set(bounds.contains_point(cx.mouse_position()));
|
||||||
|
let hovered = self.hovered.clone();
|
||||||
|
cx.on_event(order, move |view, event: &MouseMovedEvent, cx| {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Interactive<V> {
|
pub trait Interactive<V> {
|
||||||
fn declared_interactions(&mut self) -> &mut Interactions<V>;
|
fn declared_interactions(&mut self) -> &mut Interactions<V>;
|
||||||
|
|
||||||
|
@ -154,41 +222,6 @@ pub struct Interactions<V> {
|
||||||
mouse_moved: Option<Rc<dyn Fn(&mut V, &MouseMovedEvent, &mut EventContext<V>) -> bool>>,
|
mouse_moved: Option<Rc<dyn Fn(&mut V, &MouseMovedEvent, &mut EventContext<V>) -> bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hoverable<V, E: Element<V> + Styleable>(mut child: E) -> Hoverable<V, E> {
|
|
||||||
Hoverable {
|
|
||||||
default_style: child.style(),
|
|
||||||
hovered_style: Default::default(),
|
|
||||||
child,
|
|
||||||
view_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, E: Element<V> + Styleable> Styleable for Hoverable<V, E> {
|
|
||||||
type Style = E::Style;
|
|
||||||
|
|
||||||
fn declared_style(&mut self) -> &mut playground::style::StyleRefinement {
|
|
||||||
self.child.declared_style()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, E: Element<V> + Styleable> Element<V> for Hoverable<V, E> {
|
|
||||||
type Layout = E::Layout;
|
|
||||||
|
|
||||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<Layout<V, Self>>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn paint(&mut self, view: &mut V, cx: &mut PaintContext<V>)
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
// let elt = div().w_auto();
|
// let elt = div().w_auto();
|
||||||
|
|
|
@ -4,10 +4,7 @@ pub use gpui::LayoutContext as LegacyLayoutContext;
|
||||||
use gpui::{RenderContext, ViewContext};
|
use gpui::{RenderContext, ViewContext};
|
||||||
pub use taffy::tree::NodeId;
|
pub use taffy::tree::NodeId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{div::Layout, style::Style};
|
||||||
div::{Element, Layout},
|
|
||||||
style::Style,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Deref, DerefMut)]
|
#[derive(Deref, DerefMut)]
|
||||||
pub struct LayoutContext<'a, 'b, 'c, 'd, V> {
|
pub struct LayoutContext<'a, 'b, 'c, 'd, V> {
|
||||||
|
@ -43,12 +40,12 @@ impl<'a, 'b, 'c, 'd, V: 'static> LayoutContext<'a, 'b, 'c, 'd, V> {
|
||||||
Self { legacy_cx, scene }
|
Self { legacy_cx, scene }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_layout_node<E: Element<V>>(
|
pub fn add_layout_node<D>(
|
||||||
&mut self,
|
&mut self,
|
||||||
style: Style,
|
style: Style,
|
||||||
element_data: E::Layout,
|
element_data: D,
|
||||||
children: impl IntoIterator<Item = NodeId>,
|
children: impl IntoIterator<Item = NodeId>,
|
||||||
) -> Result<Layout<V, E>> {
|
) -> Result<Layout<V, D>> {
|
||||||
let rem_size = self.rem_pixels();
|
let rem_size = self.rem_pixels();
|
||||||
let id = self
|
let id = self
|
||||||
.legacy_cx
|
.legacy_cx
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
geometry::rect::RectF, EngineLayout, EventContext, LayoutId, RenderContext, ViewContext,
|
geometry::rect::RectF, scene::EventHandler, EngineLayout, EventContext, LayoutId,
|
||||||
|
RenderContext, ViewContext,
|
||||||
};
|
};
|
||||||
pub use gpui::{LayoutContext, PaintContext as LegacyPaintContext};
|
pub use gpui::{LayoutContext, PaintContext as LegacyPaintContext};
|
||||||
use std::{any::TypeId, rc::Rc};
|
use std::{any::TypeId, rc::Rc};
|
||||||
|
@ -41,6 +42,25 @@ impl<'a, 'b, 'c, 'd, V: 'static> PaintContext<'a, 'b, 'c, 'd, V> {
|
||||||
Self { legacy_cx, scene }
|
Self { legacy_cx, scene }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_event<E: 'static>(
|
||||||
|
&mut self,
|
||||||
|
order: u32,
|
||||||
|
handler: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
|
||||||
|
) {
|
||||||
|
self.scene.event_handlers.push(EventHandler {
|
||||||
|
order,
|
||||||
|
handler: Rc::new(move |view, event, window_cx, view_id| {
|
||||||
|
let mut view_context = ViewContext::mutable(window_cx, view_id);
|
||||||
|
handler(
|
||||||
|
view.downcast_mut().unwrap(),
|
||||||
|
event.downcast_ref().unwrap(),
|
||||||
|
&mut view_context,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
event_type: TypeId::of::<E>(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw_interactive_region<E: 'static>(
|
pub fn draw_interactive_region<E: 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
order: u32,
|
order: u32,
|
||||||
|
|
|
@ -31,8 +31,10 @@ pub struct SceneBuilder {
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
stacking_contexts: Vec<StackingContext>,
|
stacking_contexts: Vec<StackingContext>,
|
||||||
active_stacking_context_stack: Vec<usize>,
|
active_stacking_context_stack: Vec<usize>,
|
||||||
/// Used by the playground crate.
|
/// Used by the playground crate. I hope to replace it with event_handlers.
|
||||||
pub interactive_regions: Vec<InteractiveRegion>,
|
pub interactive_regions: Vec<InteractiveRegion>,
|
||||||
|
/// Used by the playground crate.
|
||||||
|
pub event_handlers: Vec<EventHandler>,
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
mouse_region_ids: HashSet<MouseRegionId>,
|
mouse_region_ids: HashSet<MouseRegionId>,
|
||||||
}
|
}
|
||||||
|
@ -41,6 +43,7 @@ pub struct Scene {
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
stacking_contexts: Vec<StackingContext>,
|
stacking_contexts: Vec<StackingContext>,
|
||||||
interactive_regions: Vec<InteractiveRegion>,
|
interactive_regions: Vec<InteractiveRegion>,
|
||||||
|
event_handlers: Vec<EventHandler>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StackingContext {
|
struct StackingContext {
|
||||||
|
@ -282,11 +285,17 @@ impl Scene {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: Hoping to replace this with take_event_handlers
|
||||||
pub fn take_interactive_regions(&mut self) -> Vec<InteractiveRegion> {
|
pub fn take_interactive_regions(&mut self) -> Vec<InteractiveRegion> {
|
||||||
self.interactive_regions
|
self.interactive_regions
|
||||||
.sort_by(|a, b| a.order.cmp(&b.order));
|
.sort_by(|a, b| a.order.cmp(&b.order));
|
||||||
std::mem::take(&mut self.interactive_regions)
|
std::mem::take(&mut self.interactive_regions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn take_event_handlers(&mut self) -> Vec<EventHandler> {
|
||||||
|
self.event_handlers.sort_by(|a, b| a.order.cmp(&b.order));
|
||||||
|
std::mem::take(&mut self.event_handlers)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SceneBuilder {
|
impl SceneBuilder {
|
||||||
|
@ -299,6 +308,7 @@ impl SceneBuilder {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
mouse_region_ids: Default::default(),
|
mouse_region_ids: Default::default(),
|
||||||
interactive_regions: Vec::new(),
|
interactive_regions: Vec::new(),
|
||||||
|
event_handlers: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +319,7 @@ impl SceneBuilder {
|
||||||
scale_factor: self.scale_factor,
|
scale_factor: self.scale_factor,
|
||||||
stacking_contexts: self.stacking_contexts,
|
stacking_contexts: self.stacking_contexts,
|
||||||
interactive_regions: self.interactive_regions,
|
interactive_regions: self.interactive_regions,
|
||||||
|
event_handlers: self.event_handlers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,6 +728,14 @@ pub struct InteractiveRegion {
|
||||||
pub view_id: usize,
|
pub view_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct EventHandler {
|
||||||
|
pub order: u32,
|
||||||
|
// First param is a dynamic view reference
|
||||||
|
// Second param is a dynamic event reference
|
||||||
|
pub handler: Rc<dyn Fn(&mut dyn Any, &dyn Any, &mut WindowContext, usize)>,
|
||||||
|
pub event_type: TypeId,
|
||||||
|
}
|
||||||
|
|
||||||
fn can_draw(bounds: RectF) -> bool {
|
fn can_draw(bounds: RectF) -> bool {
|
||||||
let size = bounds.size();
|
let size = bounds.size();
|
||||||
size.x() > 0. && size.y() > 0.
|
size.x() > 0. && size.y() > 0.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue