Checkpoint
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
use crate::{
|
||||
AnyElement, Bounds, Element, Interactive, LayoutId, MouseEventListeners, Overflow,
|
||||
ParentElement, Pixels, Point, Refineable, RefinementCascade, Result, Style, Styled,
|
||||
ViewContext,
|
||||
ParentElement, Pixels, Point, Refineable, RefinementCascade, Style, Styled, ViewContext,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use smallvec::SmallVec;
|
||||
use std::sync::Arc;
|
||||
use util::ResultExt;
|
||||
|
||||
pub struct Div<S: 'static> {
|
||||
styles: RefinementCascade<Style>,
|
||||
@@ -25,27 +23,28 @@ pub fn div<S>() -> Div<S> {
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> Element for Div<S> {
|
||||
type State = S;
|
||||
type FrameState = Vec<LayoutId>;
|
||||
type ViewState = S;
|
||||
type ElementState = Vec<LayoutId>;
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view: &mut S,
|
||||
_: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> Result<(LayoutId, Self::FrameState)> {
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
let style = self.computed_style();
|
||||
let child_layout_ids = style.apply_text_style(cx, |cx| self.layout_children(view, cx))?;
|
||||
let layout_id = cx.request_layout(style.into(), child_layout_ids.clone())?;
|
||||
Ok((layout_id, child_layout_ids))
|
||||
let child_layout_ids = style.apply_text_style(cx, |cx| self.layout_children(view, cx));
|
||||
let layout_id = cx.request_layout(style.into(), child_layout_ids.clone());
|
||||
(layout_id, child_layout_ids)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
state: &mut S,
|
||||
child_layout_ids: &mut Self::FrameState,
|
||||
child_layout_ids: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> Result<()> {
|
||||
) {
|
||||
let style = self.computed_style();
|
||||
cx.stack(0, |cx| style.paint(bounds, cx));
|
||||
|
||||
@@ -57,7 +56,7 @@ impl<S: 'static + Send + Sync> Element for Div<S> {
|
||||
self.paint_children(overflow, state, cx)
|
||||
})
|
||||
})
|
||||
})?;
|
||||
});
|
||||
self.handle_scroll(bounds, style.overflow.clone(), child_layout_ids, cx);
|
||||
|
||||
// todo!("enable inspector")
|
||||
@@ -65,12 +64,10 @@ impl<S: 'static + Send + Sync> Element for Div<S> {
|
||||
// self.paint_inspector(parent_origin, layout, cx);
|
||||
// }
|
||||
//
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static> Div<S> {
|
||||
impl<S: 'static + Send + Sync> Div<S> {
|
||||
pub fn overflow_hidden(mut self) -> Self {
|
||||
self.declared_style().overflow.x = Some(Overflow::Hidden);
|
||||
self.declared_style().overflow.y = Some(Overflow::Hidden);
|
||||
@@ -118,11 +115,11 @@ impl<S: 'static> Div<S> {
|
||||
offset
|
||||
}
|
||||
|
||||
fn layout_children(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> Result<Vec<LayoutId>> {
|
||||
fn layout_children(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> Vec<LayoutId> {
|
||||
self.children
|
||||
.iter_mut()
|
||||
.map(|child| child.layout(view, cx))
|
||||
.collect::<Result<Vec<LayoutId>>>()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn paint_children(
|
||||
@@ -130,12 +127,11 @@ impl<S: 'static> Div<S> {
|
||||
overflow: &Point<Overflow>,
|
||||
state: &mut S,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> Result<()> {
|
||||
) {
|
||||
let scroll_offset = self.scroll_offset(overflow);
|
||||
for child in &mut self.children {
|
||||
child.paint(state, Some(scroll_offset), cx)?;
|
||||
child.paint(state, Some(scroll_offset), cx);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_scroll(
|
||||
@@ -148,9 +144,8 @@ impl<S: 'static> Div<S> {
|
||||
if overflow.y == Overflow::Scroll || overflow.x == Overflow::Scroll {
|
||||
let mut scroll_max = Point::default();
|
||||
for child_layout_id in child_layout_ids {
|
||||
if let Some(child_bounds) = cx.layout_bounds(*child_layout_id).log_err() {
|
||||
scroll_max = scroll_max.max(&child_bounds.lower_right());
|
||||
}
|
||||
let child_bounds = cx.layout_bounds(*child_layout_id);
|
||||
scroll_max = scroll_max.max(&child_bounds.lower_right());
|
||||
}
|
||||
scroll_max -= bounds.size;
|
||||
|
||||
@@ -237,7 +232,7 @@ impl<S: 'static> Div<S> {
|
||||
//
|
||||
}
|
||||
|
||||
impl<V> Styled for Div<V> {
|
||||
impl<V: 'static + Send + Sync> Styled for Div<V> {
|
||||
type Style = Style;
|
||||
|
||||
fn style_cascade(&mut self) -> &mut RefinementCascade<Self::Style> {
|
||||
|
||||
@@ -2,7 +2,6 @@ use crate::{
|
||||
AnyElement, Bounds, DispatchPhase, Element, ElementId, Interactive, MouseEventListeners,
|
||||
MouseMoveEvent, ParentElement, Pixels, StatefulElement, Styled, ViewContext,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use refineable::{CascadeSlot, Refineable, RefinementCascade};
|
||||
use smallvec::SmallVec;
|
||||
use std::sync::{
|
||||
@@ -10,7 +9,10 @@ use std::sync::{
|
||||
Arc,
|
||||
};
|
||||
|
||||
pub struct Hoverable<E: Styled> {
|
||||
pub struct Hoverable<E: Styled>
|
||||
// where
|
||||
// <E::Style as Refineable>::Refinement: 'static + Send + Sync,
|
||||
{
|
||||
hovered: Arc<AtomicBool>,
|
||||
cascade_slot: CascadeSlot,
|
||||
hovered_style: <E::Style as Refineable>::Refinement,
|
||||
@@ -49,9 +51,14 @@ impl<S: 'static + Send + Sync, E: Interactive<S> + Styled> Interactive<S> for Ho
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Element + Styled> Element for Hoverable<E> {
|
||||
type State = E::State;
|
||||
type FrameState = E::FrameState;
|
||||
impl<E> Element for Hoverable<E>
|
||||
where
|
||||
E: Element + Styled,
|
||||
<E as Styled>::Style: 'static + Refineable + Send + Sync + Default,
|
||||
<<E as Styled>::Style as Refineable>::Refinement: 'static + Refineable + Send + Sync + Default,
|
||||
{
|
||||
type ViewState = E::ViewState;
|
||||
type ElementState = E::ElementState;
|
||||
|
||||
fn element_id(&self) -> Option<ElementId> {
|
||||
self.child.element_id()
|
||||
@@ -59,19 +66,20 @@ impl<E: Element + Styled> Element for Hoverable<E> {
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
cx: &mut ViewContext<Self::State>,
|
||||
) -> Result<(crate::LayoutId, Self::FrameState)> {
|
||||
Ok(self.child.layout(state, cx)?)
|
||||
state: &mut Self::ViewState,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> (crate::LayoutId, Self::ElementState) {
|
||||
self.child.layout(state, element_state, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
state: &mut Self::State,
|
||||
frame_state: &mut Self::FrameState,
|
||||
cx: &mut ViewContext<Self::State>,
|
||||
) -> Result<()> {
|
||||
state: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) {
|
||||
let hovered = bounds.contains_point(cx.mouse_position());
|
||||
let slot = self.cascade_slot;
|
||||
let style = hovered.then_some(self.hovered_style.clone());
|
||||
@@ -79,7 +87,7 @@ impl<E: Element + Styled> Element for Hoverable<E> {
|
||||
self.hovered.store(hovered, SeqCst);
|
||||
|
||||
let hovered = self.hovered.clone();
|
||||
cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
|
||||
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Capture {
|
||||
if bounds.contains_point(event.position) != hovered.load(SeqCst) {
|
||||
cx.notify();
|
||||
@@ -87,8 +95,7 @@ impl<E: Element + Styled> Element for Hoverable<E> {
|
||||
}
|
||||
});
|
||||
|
||||
self.child.paint(bounds, state, frame_state, cx)?;
|
||||
Ok(())
|
||||
self.child.paint(bounds, state, element_state, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,4 +107,10 @@ impl<E: ParentElement + Styled> ParentElement for Hoverable<E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: StatefulElement + Styled> StatefulElement for Hoverable<E> {}
|
||||
impl<E> StatefulElement for Hoverable<E>
|
||||
where
|
||||
E: StatefulElement + Styled,
|
||||
<E as Styled>::Style: 'static + Refineable + Send + Sync + Default,
|
||||
<<E as Styled>::Style as Refineable>::Refinement: 'static + Refineable + Send + Sync + Default,
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::{BorrowWindow, Bounds, Element, ElementId, LayoutId, StatefulElement, ViewContext};
|
||||
use anyhow::Result;
|
||||
|
||||
pub struct Identified<E> {
|
||||
pub(crate) element: E,
|
||||
@@ -7,8 +6,8 @@ pub struct Identified<E> {
|
||||
}
|
||||
|
||||
impl<E: Element> Element for Identified<E> {
|
||||
type State = E::State;
|
||||
type FrameState = E::FrameState;
|
||||
type ViewState = E::ViewState;
|
||||
type ElementState = E::ElementState;
|
||||
|
||||
fn element_id(&self) -> Option<ElementId> {
|
||||
Some(self.id.clone())
|
||||
@@ -16,21 +15,22 @@ impl<E: Element> Element for Identified<E> {
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
cx: &mut ViewContext<Self::State>,
|
||||
) -> Result<(LayoutId, Self::FrameState)> {
|
||||
self.element.layout(state, cx)
|
||||
state: &mut Self::ViewState,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
self.element.layout(state, element_state, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<crate::Pixels>,
|
||||
state: &mut Self::State,
|
||||
frame_state: &mut Self::FrameState,
|
||||
cx: &mut ViewContext<Self::State>,
|
||||
) -> Result<()> {
|
||||
state: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) {
|
||||
cx.with_element_id(self.id.clone(), |cx| {
|
||||
self.element.paint(bounds, state, frame_state, cx)
|
||||
self.element.paint(bounds, state, element_state, cx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
BorrowWindow, Bounds, Element, LayoutId, Pixels, Result, SharedString, Style, Styled,
|
||||
ViewContext,
|
||||
BorrowWindow, Bounds, Element, LayoutId, Pixels, SharedString, Style, Styled, ViewContext,
|
||||
};
|
||||
use futures::FutureExt;
|
||||
use refineable::RefinementCascade;
|
||||
@@ -36,29 +35,30 @@ impl<S> Img<S> {
|
||||
}
|
||||
|
||||
impl<S: Send + Sync + 'static> Element for Img<S> {
|
||||
type State = S;
|
||||
type FrameState = ();
|
||||
type ViewState = S;
|
||||
type ElementState = ();
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_: &mut Self::State,
|
||||
cx: &mut ViewContext<Self::State>,
|
||||
) -> anyhow::Result<(LayoutId, Self::FrameState)>
|
||||
_: &mut Self::ViewState,
|
||||
_: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> (LayoutId, Self::ElementState)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let style = self.computed_style();
|
||||
let layout_id = cx.request_layout(style, [])?;
|
||||
Ok((layout_id, ()))
|
||||
let layout_id = cx.request_layout(style, []);
|
||||
(layout_id, ())
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
_: &mut Self::State,
|
||||
_: &mut Self::FrameState,
|
||||
cx: &mut ViewContext<Self::State>,
|
||||
) -> Result<()> {
|
||||
_: &mut Self::ViewState,
|
||||
_: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) {
|
||||
let style = self.computed_style();
|
||||
|
||||
style.paint(bounds, cx);
|
||||
@@ -73,7 +73,8 @@ impl<S: Send + Sync + 'static> Element for Img<S> {
|
||||
let corner_radii = style.corner_radii.to_pixels(bounds.size, cx.rem_size());
|
||||
cx.stack(1, |cx| {
|
||||
cx.paint_image(bounds, corner_radii, data, self.grayscale)
|
||||
})?;
|
||||
.log_err()
|
||||
});
|
||||
} else {
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
if image_future.await.log_err().is_some() {
|
||||
@@ -83,7 +84,6 @@ impl<S: Send + Sync + 'static> Element for Img<S> {
|
||||
.detach()
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,211 +1,237 @@
|
||||
use crate::{
|
||||
AnyElement, Bounds, DispatchPhase, Element, Interactive, MouseDownEvent, MouseEventListeners,
|
||||
MouseUpEvent, ParentElement, Pixels, StatefulElement, Styled, ViewContext,
|
||||
};
|
||||
use refineable::{CascadeSlot, Refineable, RefinementCascade};
|
||||
use smallvec::SmallVec;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering::SeqCst},
|
||||
Arc,
|
||||
};
|
||||
|
||||
pub struct Pressable<E: Styled> {
|
||||
cascade_slot: CascadeSlot,
|
||||
pressed_style: <E::Style as Refineable>::Refinement,
|
||||
child: E,
|
||||
}
|
||||
|
||||
pub struct PressableState<S> {
|
||||
pressed: Arc<AtomicBool>,
|
||||
child_state: S,
|
||||
}
|
||||
|
||||
impl<E: Styled> Pressable<E> {
|
||||
pub fn new(mut child: E) -> Self {
|
||||
Self {
|
||||
cascade_slot: child.style_cascade().reserve(),
|
||||
pressed_style: Default::default(),
|
||||
child,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Styled for Pressable<E>
|
||||
where
|
||||
E: Styled,
|
||||
{
|
||||
type Style = E::Style;
|
||||
|
||||
fn style_cascade(&mut self) -> &mut RefinementCascade<E::Style> {
|
||||
self.child.style_cascade()
|
||||
}
|
||||
|
||||
fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
|
||||
&mut self.pressed_style
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync, E: Interactive<S> + Styled> Interactive<S> for Pressable<E> {
|
||||
fn listeners(&mut self) -> &mut MouseEventListeners<S> {
|
||||
self.child.listeners()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Element for Pressable<E>
|
||||
where
|
||||
E: Styled + StatefulElement,
|
||||
<E as Styled>::Style: 'static + Refineable + Send + Sync + Default,
|
||||
<<E as Styled>::Style as Refineable>::Refinement: 'static + Refineable + Send + Sync + Default,
|
||||
{
|
||||
type ViewState = E::ViewState;
|
||||
type ElementState = PressableState<E::ElementState>;
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
state: &mut Self::ViewState,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) -> (crate::LayoutId, Self::ElementState) {
|
||||
if let Some(element_state) = element_state {
|
||||
let (id, child_state) = self
|
||||
.child
|
||||
.layout(state, Some(element_state.child_state), cx);
|
||||
let element_state = PressableState {
|
||||
pressed: element_state.pressed,
|
||||
child_state,
|
||||
};
|
||||
(id, element_state)
|
||||
} else {
|
||||
let (id, child_state) = self.child.layout(state, None, cx);
|
||||
let element_state = PressableState {
|
||||
pressed: Default::default(),
|
||||
child_state,
|
||||
};
|
||||
(id, element_state)
|
||||
}
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
state: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) {
|
||||
let slot = self.cascade_slot;
|
||||
let style = element_state
|
||||
.pressed
|
||||
.load(SeqCst)
|
||||
.then_some(self.pressed_style.clone());
|
||||
self.style_cascade().set(slot, style);
|
||||
|
||||
let pressed = element_state.pressed.clone();
|
||||
cx.on_mouse_event(move |_, event: &MouseDownEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Capture {
|
||||
if bounds.contains_point(event.position) != pressed.load(SeqCst) {
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
let hovered = element_state.pressed.clone();
|
||||
cx.on_mouse_event(move |_, event: &MouseUpEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Capture {
|
||||
if bounds.contains_point(event.position) != hovered.load(SeqCst) {
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
self.child
|
||||
.paint(bounds, state, &mut element_state.child_state, cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: ParentElement + Styled> ParentElement for Pressable<E> {
|
||||
type State = E::State;
|
||||
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
|
||||
self.child.children_mut()
|
||||
}
|
||||
}
|
||||
|
||||
// use crate::{
|
||||
// AnyElement, Bounds, DispatchPhase, Element, Identified, Interactive, MouseDownEvent,
|
||||
// MouseEventListeners, MouseUpEvent, ParentElement, Pixels, Styled, ViewContext,
|
||||
// element::{AnyElement, Element, IntoElement, Layout, ParentElement},
|
||||
// interactive::{InteractionHandlers, Interactive},
|
||||
// style::{Style, StyleHelpers, Styleable},
|
||||
// ViewContext,
|
||||
// };
|
||||
// use anyhow::Result;
|
||||
// use gpui::{geometry::vector::Vector2F, platform::MouseButtonEvent, LayoutId};
|
||||
// use refineable::{CascadeSlot, Refineable, RefinementCascade};
|
||||
// use smallvec::SmallVec;
|
||||
// use std::sync::{
|
||||
// atomic::{AtomicBool, Ordering::SeqCst},
|
||||
// Arc,
|
||||
// };
|
||||
// use std::{cell::Cell, rc::Rc};
|
||||
|
||||
// pub struct Pressable<E: Styled> {
|
||||
// pressed: Arc<AtomicBool>,
|
||||
// cascade_slot: CascadeSlot,
|
||||
// pub struct Pressable<E: Styleable> {
|
||||
// pressed: Rc<Cell<bool>>,
|
||||
// pressed_style: <E::Style as Refineable>::Refinement,
|
||||
// cascade_slot: CascadeSlot,
|
||||
// child: E,
|
||||
// }
|
||||
|
||||
// impl<E: Identified + Styled> Pressable<E> {
|
||||
// pub fn new(mut child: E) -> Self {
|
||||
// Self {
|
||||
// pressed: Arc::new(AtomicBool::new(false)),
|
||||
// cascade_slot: child.style_cascade().reserve(),
|
||||
// pressed_style: Default::default(),
|
||||
// child,
|
||||
// }
|
||||
// pub fn pressable<E: Styleable>(mut child: E) -> Pressable<E> {
|
||||
// Pressable {
|
||||
// pressed: Rc::new(Cell::new(false)),
|
||||
// pressed_style: Default::default(),
|
||||
// cascade_slot: child.style_cascade().reserve(),
|
||||
// child,
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<E> Styled for Pressable<E>
|
||||
// where
|
||||
// E: Styled,
|
||||
// {
|
||||
// impl<E: Styleable> Styleable for Pressable<E> {
|
||||
// type Style = E::Style;
|
||||
|
||||
// fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
|
||||
// &mut self.pressed_style
|
||||
// }
|
||||
|
||||
// fn style_cascade(&mut self) -> &mut RefinementCascade<E::Style> {
|
||||
// self.child.style_cascade()
|
||||
// }
|
||||
|
||||
// fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
|
||||
// &mut self.pressed_style
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<S: 'static + Send + Sync, E: Interactive<S> + Styled> Interactive<S> for Pressable<E> {
|
||||
// fn listeners(&mut self) -> &mut MouseEventListeners<S> {
|
||||
// self.child.listeners()
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<E: Element + Identified + Styled> Element for Pressable<E> {
|
||||
// type State = E::State;
|
||||
// type FrameState = E::FrameState;
|
||||
// impl<V: 'static, E: Element<V> + Styleable> Element<V> for Pressable<E> {
|
||||
// type PaintState = E::PaintState;
|
||||
|
||||
// fn layout(
|
||||
// &mut self,
|
||||
// state: &mut Self::State,
|
||||
// cx: &mut ViewContext<Self::State>,
|
||||
// ) -> Result<(crate::LayoutId, Self::FrameState)> {
|
||||
// Ok(self.child.layout(state, cx)?)
|
||||
// view: &mut V,
|
||||
// cx: &mut ViewContext<V>,
|
||||
// ) -> Result<(LayoutId, Self::PaintState)>
|
||||
// where
|
||||
// Self: Sized,
|
||||
// {
|
||||
// self.child.layout(view, cx)
|
||||
// }
|
||||
|
||||
// fn paint(
|
||||
// &mut self,
|
||||
// bounds: Bounds<Pixels>,
|
||||
// state: &mut Self::State,
|
||||
// frame_state: &mut Self::FrameState,
|
||||
// cx: &mut ViewContext<Self::State>,
|
||||
// ) -> Result<()> {
|
||||
// let pressed = bounds.contains_point(cx.mouse_position());
|
||||
// view: &mut V,
|
||||
// parent_origin: Vector2F,
|
||||
// layout: &Layout,
|
||||
// paint_state: &mut Self::PaintState,
|
||||
// cx: &mut ViewContext<V>,
|
||||
// ) where
|
||||
// Self: Sized,
|
||||
// {
|
||||
// let slot = self.cascade_slot;
|
||||
// let style = pressed.then_some(self.pressed_style.clone());
|
||||
// let style = self.pressed.get().then_some(self.pressed_style.clone());
|
||||
// self.style_cascade().set(slot, style);
|
||||
// self.pressed.store(pressed, SeqCst);
|
||||
|
||||
// let hovered = self.pressed.clone();
|
||||
// cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
|
||||
// if phase == DispatchPhase::Capture {
|
||||
// if bounds.contains_point(event.position) != hovered.load(SeqCst) {
|
||||
// cx.notify();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
|
||||
// if phase == DispatchPhase::Capture {
|
||||
// if bounds.contains_point(event.position) != hovered.load(SeqCst) {
|
||||
// cx.notify();
|
||||
// let pressed = self.pressed.clone();
|
||||
// let bounds = layout.bounds + parent_origin;
|
||||
// cx.on_event(layout.order, move |_view, event: &MouseButtonEvent, cx| {
|
||||
// if event.is_down {
|
||||
// if bounds.contains_point(event.position) {
|
||||
// pressed.set(true);
|
||||
// cx.repaint();
|
||||
// }
|
||||
// } else if pressed.get() {
|
||||
// pressed.set(false);
|
||||
// cx.repaint();
|
||||
// }
|
||||
// });
|
||||
|
||||
// self.child.paint(bounds, state, frame_state, cx)?;
|
||||
// Ok(())
|
||||
// self.child
|
||||
// .paint(view, parent_origin, layout, paint_state, cx);
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<E: ParentElement + Styled> ParentElement for Pressable<E> {
|
||||
// type State = E::State;
|
||||
// impl<V: 'static, E: Interactive<V> + Styleable> Interactive<V> for Pressable<E> {
|
||||
// fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V> {
|
||||
// self.child.interaction_handlers()
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
|
||||
// impl<V: 'static, E: ParentElement<V> + Styleable> ParentElement<V> for Pressable<E> {
|
||||
// fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||
// self.child.children_mut()
|
||||
// }
|
||||
// }
|
||||
|
||||
// // use crate::{
|
||||
// // element::{AnyElement, Element, IntoElement, Layout, ParentElement},
|
||||
// // interactive::{InteractionHandlers, Interactive},
|
||||
// // style::{Style, StyleHelpers, Styleable},
|
||||
// // ViewContext,
|
||||
// // };
|
||||
// // use anyhow::Result;
|
||||
// // use gpui::{geometry::vector::Vector2F, platform::MouseButtonEvent, LayoutId};
|
||||
// // use refineable::{CascadeSlot, Refineable, RefinementCascade};
|
||||
// // use smallvec::SmallVec;
|
||||
// // use std::{cell::Cell, rc::Rc};
|
||||
// impl<V: 'static, E: Element<V> + Styleable> IntoElement<V> for Pressable<E> {
|
||||
// type Element = Self;
|
||||
|
||||
// // pub struct Pressable<E: Styleable> {
|
||||
// // pressed: Rc<Cell<bool>>,
|
||||
// // pressed_style: <E::Style as Refineable>::Refinement,
|
||||
// // cascade_slot: CascadeSlot,
|
||||
// // child: E,
|
||||
// // }
|
||||
|
||||
// // pub fn pressable<E: Styleable>(mut child: E) -> Pressable<E> {
|
||||
// // Pressable {
|
||||
// // pressed: Rc::new(Cell::new(false)),
|
||||
// // pressed_style: Default::default(),
|
||||
// // cascade_slot: child.style_cascade().reserve(),
|
||||
// // child,
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // impl<E: Styleable> Styleable for Pressable<E> {
|
||||
// // type Style = E::Style;
|
||||
|
||||
// // fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
|
||||
// // &mut self.pressed_style
|
||||
// // }
|
||||
|
||||
// // fn style_cascade(&mut self) -> &mut RefinementCascade<E::Style> {
|
||||
// // self.child.style_cascade()
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // impl<V: 'static, E: Element<V> + Styleable> Element<V> for Pressable<E> {
|
||||
// // type PaintState = E::PaintState;
|
||||
|
||||
// // fn layout(
|
||||
// // &mut self,
|
||||
// // view: &mut V,
|
||||
// // cx: &mut ViewContext<V>,
|
||||
// // ) -> Result<(LayoutId, Self::PaintState)>
|
||||
// // where
|
||||
// // Self: Sized,
|
||||
// // {
|
||||
// // self.child.layout(view, cx)
|
||||
// // }
|
||||
|
||||
// // fn paint(
|
||||
// // &mut self,
|
||||
// // view: &mut V,
|
||||
// // parent_origin: Vector2F,
|
||||
// // layout: &Layout,
|
||||
// // paint_state: &mut Self::PaintState,
|
||||
// // cx: &mut ViewContext<V>,
|
||||
// // ) where
|
||||
// // Self: Sized,
|
||||
// // {
|
||||
// // let slot = self.cascade_slot;
|
||||
// // let style = self.pressed.get().then_some(self.pressed_style.clone());
|
||||
// // self.style_cascade().set(slot, style);
|
||||
|
||||
// // let pressed = self.pressed.clone();
|
||||
// // let bounds = layout.bounds + parent_origin;
|
||||
// // cx.on_event(layout.order, move |_view, event: &MouseButtonEvent, cx| {
|
||||
// // if event.is_down {
|
||||
// // if bounds.contains_point(event.position) {
|
||||
// // pressed.set(true);
|
||||
// // cx.repaint();
|
||||
// // }
|
||||
// // } else if pressed.get() {
|
||||
// // pressed.set(false);
|
||||
// // cx.repaint();
|
||||
// // }
|
||||
// // });
|
||||
|
||||
// // self.child
|
||||
// // .paint(view, parent_origin, layout, paint_state, cx);
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // impl<V: 'static, E: Interactive<V> + Styleable> Interactive<V> for Pressable<E> {
|
||||
// // fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V> {
|
||||
// // self.child.interaction_handlers()
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // impl<V: 'static, E: ParentElement<V> + Styleable> ParentElement<V> for Pressable<E> {
|
||||
// // fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||
// // self.child.children_mut()
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // impl<V: 'static, E: Element<V> + Styleable> IntoElement<V> for Pressable<E> {
|
||||
// // type Element = Self;
|
||||
|
||||
// // fn into_element(self) -> Self::Element {
|
||||
// // self
|
||||
// // }
|
||||
// // }
|
||||
// fn into_element(self) -> Self::Element {
|
||||
// self
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{Bounds, Element, LayoutId, Pixels, Result, SharedString, Style, Styled};
|
||||
use crate::{Bounds, Element, LayoutId, Pixels, SharedString, Style, Styled};
|
||||
use refineable::RefinementCascade;
|
||||
use std::marker::PhantomData;
|
||||
use util::ResultExt;
|
||||
|
||||
pub struct Svg<S> {
|
||||
path: Option<SharedString>,
|
||||
@@ -23,41 +24,40 @@ impl<S> Svg<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static> Element for Svg<S> {
|
||||
type State = S;
|
||||
type FrameState = ();
|
||||
impl<S: 'static + Send + Sync> Element for Svg<S> {
|
||||
type ViewState = S;
|
||||
type ElementState = ();
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_: &mut S,
|
||||
_: Option<Self::ElementState>,
|
||||
cx: &mut crate::ViewContext<S>,
|
||||
) -> anyhow::Result<(LayoutId, Self::FrameState)>
|
||||
) -> (LayoutId, Self::ElementState)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let style = self.computed_style();
|
||||
Ok((cx.request_layout(style, [])?, ()))
|
||||
(cx.request_layout(style, []), ())
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
_: &mut Self::State,
|
||||
_: &mut Self::FrameState,
|
||||
_: &mut Self::ViewState,
|
||||
_: &mut Self::ElementState,
|
||||
cx: &mut crate::ViewContext<S>,
|
||||
) -> Result<()>
|
||||
where
|
||||
) where
|
||||
Self: Sized,
|
||||
{
|
||||
let fill_color = self.computed_style().fill.and_then(|fill| fill.color());
|
||||
if let Some((path, fill_color)) = self.path.as_ref().zip(fill_color) {
|
||||
cx.paint_svg(bounds, path.clone(), fill_color)?;
|
||||
cx.paint_svg(bounds, path.clone(), fill_color).log_err();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Styled for Svg<S> {
|
||||
impl<S: 'static + Send + Sync> Styled for Svg<S> {
|
||||
type Style = Style;
|
||||
|
||||
fn style_cascade(&mut self) -> &mut refineable::RefinementCascade<Self::Style> {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::{
|
||||
AnyElement, Bounds, Element, IntoAnyElement, LayoutId, Line, Pixels, Result, Size, ViewContext,
|
||||
AnyElement, Bounds, Element, IntoAnyElement, LayoutId, Line, Pixels, Size, ViewContext,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
use util::{arc_cow::ArcCow, ResultExt};
|
||||
|
||||
impl<S: 'static> IntoAnyElement<S> for ArcCow<'static, str> {
|
||||
impl<S: 'static + Send + Sync> IntoAnyElement<S> for ArcCow<'static, str> {
|
||||
fn into_any(self) -> AnyElement<S> {
|
||||
Text {
|
||||
text: self,
|
||||
@@ -15,7 +15,7 @@ impl<S: 'static> IntoAnyElement<S> for ArcCow<'static, str> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> IntoAnyElement<V> for &'static str {
|
||||
impl<V: 'static + Send + Sync> IntoAnyElement<V> for &'static str {
|
||||
fn into_any(self) -> AnyElement<V> {
|
||||
Text {
|
||||
text: ArcCow::from(self),
|
||||
@@ -30,15 +30,16 @@ pub struct Text<S> {
|
||||
state_type: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S: 'static> Element for Text<S> {
|
||||
type State = S;
|
||||
type FrameState = Arc<Mutex<Option<TextFrameState>>>;
|
||||
impl<S: 'static + Send + Sync> Element for Text<S> {
|
||||
type ViewState = S;
|
||||
type ElementState = Arc<Mutex<Option<TextElementState>>>;
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_view: &mut S,
|
||||
_element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> Result<(LayoutId, Self::FrameState)> {
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
let text_system = cx.text_system().clone();
|
||||
let text_style = cx.text_style();
|
||||
let font_size = text_style.font_size * cx.rem_size();
|
||||
@@ -46,11 +47,11 @@ impl<S: 'static> Element for Text<S> {
|
||||
.line_height
|
||||
.to_pixels(font_size.into(), cx.rem_size());
|
||||
let text = self.text.clone();
|
||||
let frame_state = Arc::new(Mutex::new(None));
|
||||
let element_state = Arc::new(Mutex::new(None));
|
||||
|
||||
let rem_size = cx.rem_size();
|
||||
let layout_id = cx.request_measured_layout(Default::default(), rem_size, {
|
||||
let frame_state = frame_state.clone();
|
||||
let element_state = element_state.clone();
|
||||
move |_, _| {
|
||||
let Some(line_layout) = text_system
|
||||
.layout_line(
|
||||
@@ -68,7 +69,7 @@ impl<S: 'static> Element for Text<S> {
|
||||
height: line_height,
|
||||
};
|
||||
|
||||
frame_state.lock().replace(TextFrameState {
|
||||
element_state.lock().replace(TextElementState {
|
||||
line: Arc::new(line_layout),
|
||||
line_height,
|
||||
});
|
||||
@@ -77,35 +78,32 @@ impl<S: 'static> Element for Text<S> {
|
||||
}
|
||||
});
|
||||
|
||||
Ok((layout_id?, frame_state))
|
||||
(layout_id, element_state)
|
||||
}
|
||||
|
||||
fn paint<'a>(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
_: &mut Self::State,
|
||||
frame_state: &mut Self::FrameState,
|
||||
_: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> Result<()> {
|
||||
) {
|
||||
let line;
|
||||
let line_height;
|
||||
{
|
||||
let frame_state = frame_state.lock();
|
||||
let frame_state = frame_state
|
||||
let element_state = element_state.lock();
|
||||
let element_state = element_state
|
||||
.as_ref()
|
||||
.expect("measurement has not been performed");
|
||||
line = frame_state.line.clone();
|
||||
line_height = frame_state.line_height;
|
||||
line = element_state.line.clone();
|
||||
line_height = element_state.line_height;
|
||||
}
|
||||
|
||||
// todo!("We haven't added visible bounds to the new element system yet, so this is a placeholder.");
|
||||
line.paint(bounds, bounds, line_height, cx)?;
|
||||
|
||||
Ok(())
|
||||
line.paint(bounds, bounds, line_height, cx).log_err();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TextFrameState {
|
||||
pub struct TextElementState {
|
||||
line: Arc<Line>,
|
||||
line_height: Pixels,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user