mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 10:57:22 +03:00
WIP
This commit is contained in:
parent
488d08b43c
commit
c04171abf6
@ -1,4 +1,4 @@
|
||||
use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, ViewContext};
|
||||
use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, SharedString, ViewContext};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
pub(crate) use smallvec::SmallVec;
|
||||
|
||||
@ -33,12 +33,11 @@ pub trait IdentifiedElement: Element {
|
||||
#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub(crate) struct GlobalElementId(SmallVec<[ElementId; 8]>);
|
||||
|
||||
pub trait ParentElement {
|
||||
type State;
|
||||
pub trait ParentElement: Element {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]>;
|
||||
fn group_mut(&mut self) -> &mut Option<SharedString>;
|
||||
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]>;
|
||||
|
||||
fn child(mut self, child: impl IntoAnyElement<Self::State>) -> Self
|
||||
fn child(mut self, child: impl IntoAnyElement<Self::ViewState>) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
@ -46,7 +45,10 @@ pub trait ParentElement {
|
||||
self
|
||||
}
|
||||
|
||||
fn children(mut self, iter: impl IntoIterator<Item = impl IntoAnyElement<Self::State>>) -> Self
|
||||
fn children(
|
||||
mut self,
|
||||
iter: impl IntoIterator<Item = impl IntoAnyElement<Self::ViewState>>,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
AnyElement, Bounds, DispatchPhase, Element, ElementId, ElementKind, Hoverable,
|
||||
IdentifiedElement, IntoAnyElement, LayoutId, LayoutNode, MouseDownEvent, MouseUpEvent, Pixels,
|
||||
SharedString, StyleRefinement, Styled, ViewContext,
|
||||
AnyElement, Bounds, DispatchPhase, Element, ElementId, Hoverable, IdentifiedElement,
|
||||
IntoAnyElement, LayoutId, MouseDownEvent, MouseUpEvent, ParentElement, Pixels, SharedString,
|
||||
StyleRefinement, Styled, ViewContext,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use refineable::CascadeSlot;
|
||||
@ -53,7 +53,17 @@ pub struct ClickableElement<E: Element> {
|
||||
cascade_slot: CascadeSlot,
|
||||
}
|
||||
|
||||
impl<E: Element> ClickableElement<E> {
|
||||
impl<E: Styled + Element> ClickableElement<E> {
|
||||
pub fn new(mut child: E) -> Self {
|
||||
let cascade_slot = child.style_cascade().reserve();
|
||||
ClickableElement {
|
||||
child,
|
||||
listeners: Default::default(),
|
||||
active_style: Default::default(),
|
||||
cascade_slot,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_child<E2: Element<ViewState = E::ViewState>>(
|
||||
self,
|
||||
replace: impl FnOnce(E) -> E2,
|
||||
@ -171,12 +181,11 @@ where
|
||||
|
||||
impl<E: Styled + IdentifiedElement> IdentifiedElement for ClickableElement<E> {}
|
||||
|
||||
impl<E, K> LayoutNode<E::ViewState, K> for ClickableElement<E>
|
||||
impl<E> ParentElement for ClickableElement<E>
|
||||
where
|
||||
E: Element + LayoutNode<E::ViewState, K>,
|
||||
K: ElementKind,
|
||||
E: Styled + ParentElement,
|
||||
{
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<E::ViewState>; 2]> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
|
||||
self.child.children_mut()
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::{
|
||||
AnonymousElementKind, AnyElement, Bounds, Clickable, ClickableElement, ClickableElementState,
|
||||
Element, ElementId, ElementKind, Hoverable, HoverableElement, IdentifiedElementKind,
|
||||
IntoAnyElement, LayoutId, LayoutNode, LayoutNodeElement, Overflow, Pixels, Point, SharedString,
|
||||
Style, StyleCascade, StyleRefinement, Styled, ViewContext, ClickListeners,
|
||||
AnonymousElementKind, AnyElement, Bounds, ClickListeners, Clickable, ClickableElement,
|
||||
ClickableElementState, Element, ElementId, ElementKind, Hoverable, HoverableElement,
|
||||
IdentifiedElement, IdentifiedElementKind, IntoAnyElement, LayoutId, LayoutNodeElement,
|
||||
Overflow, ParentElement, Pixels, Point, SharedString, Style, StyleCascade, StyleRefinement,
|
||||
Styled, ViewContext,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use smallvec::SmallVec;
|
||||
@ -29,7 +30,16 @@ impl ScrollState {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Div<V: 'static + Send + Sync, K: ElementKind>(
|
||||
pub fn div<S>() -> Div<S, AnonymousElementKind>
|
||||
where
|
||||
S: 'static + Send + Sync,
|
||||
{
|
||||
Div(ClickableElement::new(HoverableElement::new(
|
||||
LayoutNodeElement::new(),
|
||||
)))
|
||||
}
|
||||
|
||||
pub struct Div<V: 'static + Send + Sync, K: ElementKind = AnonymousElementKind>(
|
||||
ClickableElement<HoverableElement<LayoutNodeElement<V, K>>>,
|
||||
);
|
||||
|
||||
@ -95,7 +105,13 @@ impl<V: 'static + Send + Sync> Div<V, AnonymousElementKind> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync, K: ElementKind> LayoutNode<V, K> for Div<V, K> {
|
||||
impl<V: 'static + Send + Sync> IdentifiedElement for Div<V, IdentifiedElementKind> {
|
||||
fn id(&self) -> ElementId {
|
||||
IdentifiedElement::id(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync, K: ElementKind> ParentElement for Div<V, K> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||
self.0.children_mut()
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
group_bounds, AnyElement, Bounds, DispatchPhase, Element, ElementId, ElementKind,
|
||||
IdentifiedElement, IntoAnyElement, LayoutId, LayoutNode, MouseMoveEvent, Pixels, SharedString,
|
||||
Style, StyleCascade, StyleRefinement, Styled, ViewContext,
|
||||
group_bounds, AnyElement, Bounds, DispatchPhase, Element, ElementId, IdentifiedElement,
|
||||
IntoAnyElement, LayoutId, MouseMoveEvent, ParentElement, Pixels, SharedString, Style,
|
||||
StyleCascade, StyleRefinement, Styled, ViewContext,
|
||||
};
|
||||
use refineable::CascadeSlot;
|
||||
use std::sync::{
|
||||
@ -30,6 +30,17 @@ pub struct HoverableElement<E> {
|
||||
}
|
||||
|
||||
impl<E: Styled + Element> HoverableElement<E> {
|
||||
pub fn new(mut child: E) -> Self {
|
||||
let cascade_slot = child.style_cascade().reserve();
|
||||
HoverableElement {
|
||||
hover_style: StyleRefinement::default(),
|
||||
group: None,
|
||||
cascade_slot,
|
||||
hovered: Arc::new(AtomicBool::new(false)),
|
||||
child,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_child<E2: Element<ViewState = E::ViewState>>(
|
||||
self,
|
||||
replace: impl FnOnce(E) -> E2,
|
||||
@ -106,13 +117,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, K, V> LayoutNode<V, K> for HoverableElement<E>
|
||||
impl<E> ParentElement for HoverableElement<E>
|
||||
where
|
||||
E: LayoutNode<V, K>,
|
||||
K: ElementKind,
|
||||
V: 'static + Send + Sync,
|
||||
E: Styled + ParentElement,
|
||||
{
|
||||
fn children_mut(&mut self) -> &mut smallvec::SmallVec<[AnyElement<V>; 2]> {
|
||||
fn children_mut(&mut self) -> &mut smallvec::SmallVec<[AnyElement<E::ViewState>; 2]> {
|
||||
self.child.children_mut()
|
||||
}
|
||||
|
||||
|
@ -1,29 +1,35 @@
|
||||
use crate::{
|
||||
AnyElement, BorrowWindow, Bounds, Element, IntoAnyElement, LayoutId, Pixels, SharedString,
|
||||
Style, Styled, ViewContext,
|
||||
AnonymousElementKind, AnyElement, BorrowWindow, Bounds, ClickListeners, Clickable,
|
||||
ClickableElement, ClickableElementState, Element, ElementId, ElementKind, Hoverable,
|
||||
HoverableElement, IdentifiedElement, IdentifiedElementKind, IntoAnyElement, LayoutId,
|
||||
LayoutNodeElement, Pixels, SharedString, Style, StyleRefinement, Styled, ViewContext,
|
||||
};
|
||||
use futures::FutureExt;
|
||||
use refineable::Cascade;
|
||||
use std::marker::PhantomData;
|
||||
use util::ResultExt;
|
||||
|
||||
pub struct Img<S> {
|
||||
style: Cascade<Style>,
|
||||
pub struct Img<V: 'static + Send + Sync, K: ElementKind = AnonymousElementKind> {
|
||||
layout_node: ClickableElement<HoverableElement<LayoutNodeElement<V, K>>>,
|
||||
uri: Option<SharedString>,
|
||||
grayscale: bool,
|
||||
state_type: PhantomData<S>,
|
||||
}
|
||||
|
||||
pub fn img<S>() -> Img<S> {
|
||||
pub fn img<V>() -> Img<V, AnonymousElementKind>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
Img {
|
||||
style: Cascade::default(),
|
||||
layout_node: ClickableElement::new(HoverableElement::new(LayoutNodeElement::new())),
|
||||
uri: None,
|
||||
grayscale: false,
|
||||
state_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Img<S> {
|
||||
impl<V, K> Img<V, K>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
K: ElementKind,
|
||||
{
|
||||
pub fn uri(mut self, uri: impl Into<SharedString>) -> Self {
|
||||
self.uri = Some(uri.into());
|
||||
self
|
||||
@ -35,47 +41,65 @@ impl<S> Img<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> IntoAnyElement<S> for Img<S>
|
||||
impl<V: 'static + Send + Sync> Img<V, AnonymousElementKind> {
|
||||
pub fn id(self, id: impl Into<ElementId>) -> Img<V, IdentifiedElementKind> {
|
||||
Img {
|
||||
layout_node: self.layout_node.replace_child(|hoverable| {
|
||||
hoverable.replace_child(|layout_node| layout_node.identify(id))
|
||||
}),
|
||||
uri: self.uri,
|
||||
grayscale: self.grayscale,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, K> IntoAnyElement<V> for Img<V, K>
|
||||
where
|
||||
S: 'static + Send + Sync,
|
||||
V: 'static + Send + Sync,
|
||||
K: ElementKind,
|
||||
{
|
||||
fn into_any(self) -> AnyElement<S> {
|
||||
fn into_any(self) -> AnyElement<V> {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Send + Sync + 'static> Element for Img<S> {
|
||||
type ViewState = S;
|
||||
type ElementState = ();
|
||||
impl<V, K> Element for Img<V, K>
|
||||
where
|
||||
V: Send + Sync + 'static,
|
||||
K: ElementKind,
|
||||
{
|
||||
type ViewState = V;
|
||||
type ElementState = ClickableElementState<()>;
|
||||
|
||||
fn id(&self) -> Option<crate::ElementId> {
|
||||
None
|
||||
self.layout_node.id()
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_: &mut Self::ViewState,
|
||||
_: Option<Self::ElementState>,
|
||||
view_state: &mut Self::ViewState,
|
||||
element_state: 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, []);
|
||||
(layout_id, ())
|
||||
self.layout_node.layout(view_state, element_state, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
_: &mut Self::ViewState,
|
||||
_: &mut Self::ElementState,
|
||||
view: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Self::ViewState>,
|
||||
) {
|
||||
cx.stack(1, |cx| {
|
||||
self.layout_node.paint(bounds, view, element_state, cx);
|
||||
});
|
||||
|
||||
let style = self.computed_style();
|
||||
let corner_radii = style.corner_radii;
|
||||
style.paint(bounds, cx);
|
||||
|
||||
if let Some(uri) = self.uri.clone() {
|
||||
let image_future = cx.image_cache.get(uri);
|
||||
@ -101,14 +125,38 @@ impl<S: Send + Sync + 'static> Element for Img<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Styled for Img<S> {
|
||||
impl<V: 'static + Send + Sync> IdentifiedElement for Img<V, IdentifiedElementKind> {
|
||||
fn id(&self) -> ElementId {
|
||||
IdentifiedElement::id(&self.layout_node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, K> Styled for Img<V, K>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
K: ElementKind,
|
||||
{
|
||||
fn style_cascade(&mut self) -> &mut Cascade<Style> {
|
||||
todo!("use layout node")
|
||||
// &mut self.style
|
||||
self.layout_node.style_cascade()
|
||||
}
|
||||
|
||||
fn computed_style(&mut self) -> &Style {
|
||||
todo!("use layout node")
|
||||
// self.style.compute()
|
||||
self.layout_node.computed_style()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync, K: ElementKind> Hoverable for Img<V, K> {
|
||||
fn hover_style(&mut self) -> &mut StyleRefinement {
|
||||
self.layout_node.hover_style()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync> Clickable for Img<V, IdentifiedElementKind> {
|
||||
fn active_style(&mut self) -> &mut StyleRefinement {
|
||||
self.layout_node.active_style()
|
||||
}
|
||||
|
||||
fn listeners(&mut self) -> &mut ClickListeners<V> {
|
||||
self.layout_node.listeners()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
AnyElement, AppContext, BorrowWindow, Bounds, Element, ElementId, IdentifiedElement,
|
||||
IntoAnyElement, LayoutId, Pixels, SharedString, Style, StyleCascade, Styled, ViewContext,
|
||||
IntoAnyElement, LayoutId, ParentElement, Pixels, SharedString, Style, StyleCascade, Styled,
|
||||
ViewContext,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use refineable::Refineable;
|
||||
@ -16,31 +17,6 @@ pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<P
|
||||
.and_then(|bounds_stack| bounds_stack.last().cloned())
|
||||
}
|
||||
|
||||
pub trait LayoutNode<V: 'static + Send + Sync, K: ElementKind> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
|
||||
fn group_mut(&mut self) -> &mut Option<SharedString>;
|
||||
|
||||
fn child(mut self, child: impl IntoAnyElement<V>) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.children_mut().push(child.into_any());
|
||||
self
|
||||
}
|
||||
|
||||
fn children<C, E>(mut self, children: C) -> Self
|
||||
where
|
||||
C: IntoIterator<Item = E>,
|
||||
E: IntoAnyElement<V>,
|
||||
Self: Sized,
|
||||
{
|
||||
for child in children {
|
||||
self.children_mut().push(child.into_any());
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ElementKind: 'static + Send + Sync {
|
||||
fn id(&self) -> Option<ElementId>;
|
||||
}
|
||||
@ -69,6 +45,16 @@ pub struct LayoutNodeElement<V: 'static + Send + Sync, K: ElementKind> {
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync> LayoutNodeElement<V, AnonymousElementKind> {
|
||||
pub fn new() -> LayoutNodeElement<V, AnonymousElementKind> {
|
||||
LayoutNodeElement {
|
||||
style_cascade: StyleCascade::default(),
|
||||
computed_style: None,
|
||||
children: SmallVec::new(),
|
||||
kind: AnonymousElementKind,
|
||||
group: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identify(self, id: impl Into<ElementId>) -> LayoutNodeElement<V, IdentifiedElementKind> {
|
||||
LayoutNodeElement {
|
||||
style_cascade: self.style_cascade,
|
||||
@ -196,7 +182,7 @@ impl<V: 'static + Send + Sync, K: ElementKind> Element for LayoutNodeElement<V,
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync, K: ElementKind> LayoutNode<V, K> for LayoutNodeElement<V, K> {
|
||||
impl<V: 'static + Send + Sync, K: ElementKind> ParentElement for LayoutNodeElement<V, K> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||
&mut self.children
|
||||
}
|
||||
|
@ -1,167 +0,0 @@
|
||||
use crate::{
|
||||
group_bounds, AnyElement, Bounds, DispatchPhase, Element, IdentifiedElement, Interactive,
|
||||
IntoAnyElement, MouseDownEvent, MouseEventListeners, MouseUpEvent, ParentElement, Pixels,
|
||||
SharedString, Styled, ViewContext,
|
||||
};
|
||||
use refineable::{Cascade, CascadeSlot, Refineable};
|
||||
use smallvec::SmallVec;
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering::SeqCst},
|
||||
Arc,
|
||||
};
|
||||
|
||||
pub struct Pressable<E: Styled> {
|
||||
group: Option<SharedString>,
|
||||
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, group: Option<SharedString>) -> Self {
|
||||
Self {
|
||||
group,
|
||||
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 Cascade<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> IntoAnyElement<E::ViewState> for Pressable<E>
|
||||
where
|
||||
E: Styled + IdentifiedElement,
|
||||
<E as Styled>::Style: 'static + Refineable + Send + Sync + Default,
|
||||
<<E as Styled>::Style as Refineable>::Refinement: 'static + Refineable + Send + Sync + Default,
|
||||
{
|
||||
fn into_any(self) -> AnyElement<E::ViewState> {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Element for Pressable<E>
|
||||
where
|
||||
E: Styled + IdentifiedElement,
|
||||
<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 id(&self) -> Option<crate::ElementId> {
|
||||
Some(IdentifiedElement::element_id(&self.child))
|
||||
}
|
||||
|
||||
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 target_bounds = self
|
||||
.group
|
||||
.as_ref()
|
||||
.and_then(|group| group_bounds(group, cx))
|
||||
.unwrap_or(bounds);
|
||||
|
||||
let style = element_state
|
||||
.pressed
|
||||
.load(SeqCst)
|
||||
.then_some(self.pressed_style.clone());
|
||||
let slot = self.cascade_slot;
|
||||
self.style_cascade().set(slot, style);
|
||||
|
||||
let pressed = element_state.pressed.clone();
|
||||
cx.on_mouse_event(move |_, event: &MouseDownEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble {
|
||||
if target_bounds.contains_point(event.position) {
|
||||
pressed.store(true, SeqCst);
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
let pressed = element_state.pressed.clone();
|
||||
cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Capture {
|
||||
if pressed.load(SeqCst) {
|
||||
pressed.store(false, SeqCst);
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
self.child
|
||||
.paint(bounds, state, &mut element_state.child_state, cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ParentElement for Pressable<E>
|
||||
where
|
||||
E: ParentElement + IdentifiedElement + Styled,
|
||||
{
|
||||
type State = E::State;
|
||||
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
|
||||
self.child.children_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> IdentifiedElement for Pressable<E>
|
||||
where
|
||||
E: IdentifiedElement + Styled,
|
||||
<E as Styled>::Style: 'static + Refineable + Send + Sync + Default,
|
||||
<<E as Styled>::Style as Refineable>::Refinement: 'static + Refineable + Send + Sync + Default,
|
||||
{
|
||||
}
|
@ -1,70 +1,93 @@
|
||||
use crate::{
|
||||
AnyElement, Bounds, Element, IntoAnyElement, LayoutId, Pixels, SharedString, Style, Styled,
|
||||
AnonymousElementKind, AnyElement, Bounds, ClickListeners, Clickable, ClickableElement,
|
||||
ClickableElementState, Element, ElementId, ElementKind, Hoverable, HoverableElement,
|
||||
IdentifiedElement, IdentifiedElementKind, IntoAnyElement, LayoutId, LayoutNodeElement, Pixels,
|
||||
SharedString, Style, StyleRefinement, Styled,
|
||||
};
|
||||
use refineable::Cascade;
|
||||
use std::marker::PhantomData;
|
||||
use util::ResultExt;
|
||||
|
||||
pub struct Svg<S> {
|
||||
pub struct Svg<V: 'static + Send + Sync, K: ElementKind = AnonymousElementKind> {
|
||||
layout_node: ClickableElement<HoverableElement<LayoutNodeElement<V, K>>>,
|
||||
path: Option<SharedString>,
|
||||
style: Cascade<Style>,
|
||||
state_type: PhantomData<S>,
|
||||
}
|
||||
|
||||
pub fn svg<S>() -> Svg<S> {
|
||||
pub fn svg<V>() -> Svg<V, AnonymousElementKind>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
{
|
||||
Svg {
|
||||
layout_node: ClickableElement::new(HoverableElement::new(LayoutNodeElement::new())),
|
||||
path: None,
|
||||
style: Cascade::<Style>::default(),
|
||||
state_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Svg<S> {
|
||||
impl<V, K> Svg<V, K>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
K: ElementKind,
|
||||
{
|
||||
pub fn path(mut self, path: impl Into<SharedString>) -> Self {
|
||||
self.path = Some(path.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> IntoAnyElement<S> for Svg<S>
|
||||
impl<V: 'static + Send + Sync> Svg<V, AnonymousElementKind> {
|
||||
pub fn id(self, id: impl Into<ElementId>) -> Svg<V, IdentifiedElementKind> {
|
||||
Svg {
|
||||
layout_node: self.layout_node.replace_child(|hoverable| {
|
||||
hoverable.replace_child(|layout_node| layout_node.identify(id))
|
||||
}),
|
||||
path: self.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, K> IntoAnyElement<V> for Svg<V, K>
|
||||
where
|
||||
S: 'static + Send + Sync,
|
||||
V: 'static + Send + Sync,
|
||||
K: ElementKind,
|
||||
{
|
||||
fn into_any(self) -> AnyElement<S> {
|
||||
fn into_any(self) -> AnyElement<V> {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> Element for Svg<S> {
|
||||
type ViewState = S;
|
||||
type ElementState = ();
|
||||
impl<V, K> Element for Svg<V, K>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
K: ElementKind,
|
||||
{
|
||||
type ViewState = V;
|
||||
type ElementState = ClickableElementState<()>;
|
||||
|
||||
fn id(&self) -> Option<crate::ElementId> {
|
||||
None
|
||||
self.layout_node.id()
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_: &mut S,
|
||||
_: Option<Self::ElementState>,
|
||||
cx: &mut crate::ViewContext<S>,
|
||||
view: &mut V,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut crate::ViewContext<V>,
|
||||
) -> (LayoutId, Self::ElementState)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let style = self.computed_style();
|
||||
(cx.request_layout(&style, []), ())
|
||||
self.layout_node.layout(view, element_state, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
_: &mut Self::ViewState,
|
||||
_: &mut Self::ElementState,
|
||||
cx: &mut crate::ViewContext<S>,
|
||||
view: &mut Self::ViewState,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut crate::ViewContext<V>,
|
||||
) where
|
||||
Self: Sized,
|
||||
{
|
||||
self.layout_node.paint(bounds, view, element_state, cx);
|
||||
let fill_color = self
|
||||
.computed_style()
|
||||
.fill
|
||||
@ -76,12 +99,38 @@ impl<S: 'static + Send + Sync> Element for Svg<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> Styled for Svg<S> {
|
||||
fn style_cascade(&mut self) -> &mut crate::StyleCascade {
|
||||
todo!("use layout node")
|
||||
impl<V: 'static + Send + Sync> IdentifiedElement for Svg<V, IdentifiedElementKind> {
|
||||
fn id(&self) -> ElementId {
|
||||
IdentifiedElement::id(&self.layout_node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, K> Styled for Svg<V, K>
|
||||
where
|
||||
V: 'static + Send + Sync,
|
||||
K: ElementKind,
|
||||
{
|
||||
fn style_cascade(&mut self) -> &mut Cascade<Style> {
|
||||
self.layout_node.style_cascade()
|
||||
}
|
||||
|
||||
fn computed_style(&mut self) -> &Style {
|
||||
todo!("use layout node")
|
||||
self.layout_node.computed_style()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync, K: ElementKind> Hoverable for Svg<V, K> {
|
||||
fn hover_style(&mut self) -> &mut StyleRefinement {
|
||||
self.layout_node.hover_style()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static + Send + Sync> Clickable for Svg<V, IdentifiedElementKind> {
|
||||
fn active_style(&mut self) -> &mut StyleRefinement {
|
||||
self.layout_node.active_style()
|
||||
}
|
||||
|
||||
fn listeners(&mut self) -> &mut ClickListeners<V> {
|
||||
self.layout_node.listeners()
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,7 @@ pub fn derive_element(input: TokenStream) -> TokenStream {
|
||||
type ViewState = #state_type;
|
||||
type ElementState = gpui3::AnyElement<#state_type>;
|
||||
|
||||
fn element_id(&self) -> Option<gpui3::ElementId> {
|
||||
// todo!("What should element_id be here?")
|
||||
fn id(&self) -> Option<gpui3::ElementId> {
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use gpui3::{Element, ParentElement, StyleHelpers, ViewContext};
|
||||
use gpui3::{Element, ParentElement, ViewContext};
|
||||
|
||||
use crate::{
|
||||
h_stack, v_stack, Button, Icon, IconButton, IconElement, Label, ThemeColor, Toast, ToastOrigin,
|
||||
|
@ -140,9 +140,7 @@ impl<S: 'static + Send + Sync> Panel<S> {
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> ParentElement for Panel<S> {
|
||||
type State = S;
|
||||
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
|
||||
&mut self.children
|
||||
}
|
||||
}
|
||||
|
@ -57,9 +57,7 @@ impl<S: 'static + Send + Sync> Pane<S> {
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> ParentElement for Pane<S> {
|
||||
type State = S;
|
||||
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
|
||||
&mut self.children
|
||||
}
|
||||
}
|
||||
|
@ -62,9 +62,7 @@ impl<S: 'static + Send + Sync> Toast<S> {
|
||||
}
|
||||
|
||||
impl<S: 'static + Send + Sync> ParentElement for Toast<S> {
|
||||
type State = S;
|
||||
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
|
||||
&mut self.children
|
||||
}
|
||||
}
|
||||
|
@ -88,11 +88,11 @@ impl<S: 'static + Send + Sync> Input<S> {
|
||||
.border()
|
||||
.border_color(border_color_default)
|
||||
.fill(background_color_default)
|
||||
.hover()
|
||||
.border_color(border_color_hover)
|
||||
// .active()
|
||||
// .border_color(border_color_active)
|
||||
.fill(background_color_active)
|
||||
.hover(|h| {
|
||||
h.border_color(border_color_hover)
|
||||
.fill(background_color_active)
|
||||
})
|
||||
// .active(|a| .border_color(border_color_active))
|
||||
.flex()
|
||||
.items_center()
|
||||
.child(
|
||||
@ -128,7 +128,11 @@ mod stories {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
|
||||
fn render(
|
||||
&mut self,
|
||||
_view: &mut S,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> impl Element<ViewState = S> {
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, Input<S>>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
|
@ -2,7 +2,7 @@ use gpui3::{div, Div};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
pub trait Stack: StyleHelpers {
|
||||
pub trait Stack: Styled + Sized {
|
||||
/// Horizontally stacks elements.
|
||||
fn h_stack(self) -> Self {
|
||||
self.flex().flex_row().items_center()
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub use gpui3::{
|
||||
div, Element, IntoAnyElement, ParentElement, ScrollState, StyleHelpers, Styled, ViewContext,
|
||||
WindowContext,
|
||||
div, Clickable, Element, Hoverable, IntoAnyElement, ParentElement, ScrollState, Styled,
|
||||
ViewContext, WindowContext,
|
||||
};
|
||||
|
||||
pub use crate::{theme, ButtonVariant, ElementExt, Theme};
|
||||
|
Loading…
Reference in New Issue
Block a user