Detailed changes
@@ -631,7 +631,7 @@ impl AnyWindowHandle {
pub struct EmptyView {}
impl Render for EmptyView {
- type Element = Div<Self>;
+ type Element = Div;
fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> Self::Element {
div()
@@ -1,37 +1,34 @@
use crate::{
- AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, ViewContext,
+ AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, WindowContext,
};
use derive_more::{Deref, DerefMut};
pub(crate) use smallvec::SmallVec;
use std::{any::Any, fmt::Debug, mem};
-pub trait Element<V: 'static> {
+pub trait Element {
type ElementState: 'static;
fn element_id(&self) -> Option<ElementId>;
fn layout(
&mut self,
- view_state: &mut V,
element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState);
fn paint(
&mut self,
bounds: Bounds<Pixels>,
- view_state: &mut V,
element_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
);
fn draw<T, R>(
self,
origin: Point<Pixels>,
available_space: Size<T>,
- view_state: &mut V,
- cx: &mut ViewContext<V>,
- f: impl FnOnce(&Self::ElementState, &mut ViewContext<V>) -> R,
+ cx: &mut WindowContext,
+ f: impl FnOnce(&Self::ElementState, &mut WindowContext) -> R,
) -> R
where
Self: Sized,
@@ -41,7 +38,7 @@ pub trait Element<V: 'static> {
element: self,
phase: ElementRenderPhase::Start,
};
- element.draw(origin, available_space.map(Into::into), view_state, cx);
+ element.draw(origin, available_space.map(Into::into), cx);
if let ElementRenderPhase::Painted { frame_state } = &element.phase {
if let Some(frame_state) = frame_state.as_ref() {
f(&frame_state, cx)
@@ -65,10 +62,10 @@ pub trait Element<V: 'static> {
#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
-pub trait ParentComponent<V: 'static> {
- fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
+pub trait ParentComponent {
+ fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>;
- fn child(mut self, child: impl Component<V>) -> Self
+ fn child(mut self, child: impl Component) -> Self
where
Self: Sized,
{
@@ -76,7 +73,7 @@ pub trait ParentComponent<V: 'static> {
self
}
- fn children(mut self, iter: impl IntoIterator<Item = impl Component<V>>) -> Self
+ fn children(mut self, iter: impl IntoIterator<Item = impl Component>) -> Self
where
Self: Sized,
{
@@ -86,26 +83,24 @@ pub trait ParentComponent<V: 'static> {
}
}
-trait ElementObject<V> {
+trait ElementObject {
fn element_id(&self) -> Option<ElementId>;
- fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
- fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
+ fn layout(&mut self, cx: &mut WindowContext) -> LayoutId;
+ fn paint(&mut self, cx: &mut WindowContext);
fn measure(
&mut self,
available_space: Size<AvailableSpace>,
- view_state: &mut V,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> Size<Pixels>;
fn draw(
&mut self,
origin: Point<Pixels>,
available_space: Size<AvailableSpace>,
- view_state: &mut V,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
);
}
-struct RenderedElement<V: 'static, E: Element<V>> {
+struct RenderedElement<E: Element> {
element: E,
phase: ElementRenderPhase<E::ElementState>,
}
@@ -131,7 +126,7 @@ enum ElementRenderPhase<V> {
/// Internal struct that wraps an element to store Layout and ElementState 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<V, E: Element<V>> RenderedElement<V, E> {
+impl<E: Element> RenderedElement<E> {
fn new(element: E) -> Self {
RenderedElement {
element,
@@ -140,25 +135,25 @@ impl<V, E: Element<V>> RenderedElement<V, E> {
}
}
-impl<V, E> ElementObject<V> for RenderedElement<V, E>
+impl<E> ElementObject for RenderedElement<E>
where
- E: Element<V>,
+ E: Element,
E::ElementState: 'static,
{
fn element_id(&self) -> Option<ElementId> {
self.element.element_id()
}
- fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
+ fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
let (layout_id, frame_state) = match mem::take(&mut self.phase) {
ElementRenderPhase::Start => {
if let Some(id) = self.element.element_id() {
let layout_id = cx.with_element_state(id, |element_state, cx| {
- self.element.layout(state, element_state, cx)
+ self.element.layout(element_state, cx)
});
(layout_id, None)
} else {
- let (layout_id, frame_state) = self.element.layout(state, None, cx);
+ let (layout_id, frame_state) = self.element.layout(None, cx);
(layout_id, Some(frame_state))
}
}
@@ -176,7 +171,7 @@ where
layout_id
}
- fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
+ fn paint(&mut self, cx: &mut WindowContext) {
self.phase = match mem::take(&mut self.phase) {
ElementRenderPhase::LayoutRequested {
layout_id,
@@ -191,13 +186,12 @@ where
if let Some(id) = self.element.element_id() {
cx.with_element_state(id, |element_state, cx| {
let mut element_state = element_state.unwrap();
- self.element
- .paint(bounds, view_state, &mut element_state, cx);
+ self.element.paint(bounds, &mut element_state, cx);
((), element_state)
});
} else {
self.element
- .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
+ .paint(bounds, frame_state.as_mut().unwrap(), cx);
}
ElementRenderPhase::Painted { frame_state }
}
@@ -209,11 +203,10 @@ where
fn measure(
&mut self,
available_space: Size<AvailableSpace>,
- view_state: &mut V,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> Size<Pixels> {
if matches!(&self.phase, ElementRenderPhase::Start) {
- self.layout(view_state, cx);
+ self.layout(cx);
}
let layout_id = match &mut self.phase {
@@ -251,21 +244,19 @@ where
&mut self,
origin: Point<Pixels>,
available_space: Size<AvailableSpace>,
- view_state: &mut V,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) {
- self.measure(available_space, view_state, cx);
- cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx))
+ self.measure(available_space, cx);
+ cx.with_absolute_element_offset(origin, |cx| self.paint(cx))
}
}
-pub struct AnyElement<V>(Box<dyn ElementObject<V>>);
+pub struct AnyElement(Box<dyn ElementObject>);
-impl<V> AnyElement<V> {
+impl AnyElement {
pub fn new<E>(element: E) -> Self
where
- V: 'static,
- E: 'static + Element<V>,
+ E: 'static + Element,
E::ElementState: Any,
{
AnyElement(Box::new(RenderedElement::new(element)))
@@ -275,22 +266,21 @@ impl<V> AnyElement<V> {
self.0.element_id()
}
- pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
- self.0.layout(view_state, cx)
+ pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
+ self.0.layout(cx)
}
- pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
- self.0.paint(view_state, cx)
+ pub fn paint(&mut self, cx: &mut WindowContext) {
+ self.0.paint(cx)
}
/// Initializes this element and performs layout within the given available space to determine its size.
pub fn measure(
&mut self,
available_space: Size<AvailableSpace>,
- view_state: &mut V,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> Size<Pixels> {
- self.0.measure(available_space, view_state, cx)
+ self.0.measure(available_space, cx)
}
/// Initializes this element and performs layout in the available space, then paints it at the given origin.
@@ -298,20 +288,19 @@ impl<V> AnyElement<V> {
&mut self,
origin: Point<Pixels>,
available_space: Size<AvailableSpace>,
- view_state: &mut V,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) {
- self.0.draw(origin, available_space, view_state, cx)
+ self.0.draw(origin, available_space, cx)
}
}
-pub trait Component<V> {
- fn render(self) -> AnyElement<V>;
+pub trait Component {
+ fn render(self) -> AnyElement;
fn map<U>(self, f: impl FnOnce(Self) -> U) -> U
where
Self: Sized,
- U: Component<V>,
+ U: Component,
{
f(self)
}
@@ -337,19 +326,18 @@ pub trait Component<V> {
}
}
-impl<V> Component<V> for AnyElement<V> {
- fn render(self) -> AnyElement<V> {
+impl Component for AnyElement {
+ fn render(self) -> AnyElement {
self
}
}
-impl<V, E, F> Element<V> for Option<F>
+impl<E, F> Element for Option<F>
where
- V: 'static,
- E: 'static + Component<V>,
- F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
+ E: 'static + Component,
+ F: FnOnce(&mut WindowContext) -> E + 'static,
{
- type ElementState = AnyElement<V>;
+ type ElementState = AnyElement;
fn element_id(&self) -> Option<ElementId> {
None
@@ -357,45 +345,41 @@ where
fn layout(
&mut self,
- view_state: &mut V,
_: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
let render = self.take().unwrap();
- let mut rendered_element = (render)(view_state, cx).render();
- let layout_id = rendered_element.layout(view_state, cx);
+ let mut rendered_element = (render)(cx).render();
+ let layout_id = rendered_element.layout(cx);
(layout_id, rendered_element)
}
fn paint(
&mut self,
_bounds: Bounds<Pixels>,
- view_state: &mut V,
rendered_element: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) {
- rendered_element.paint(view_state, cx)
+ rendered_element.paint(cx)
}
}
-impl<V, E, F> Component<V> for Option<F>
+impl<E, F> Component for Option<F>
where
- V: 'static,
- E: 'static + Component<V>,
- F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
+ E: 'static + Component,
+ F: FnOnce(&mut WindowContext) -> E + 'static,
{
- fn render(self) -> AnyElement<V> {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
-impl<V, E, F> Component<V> for F
+impl<E, F> Component for F
where
- V: 'static,
- E: 'static + Component<V>,
- F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
+ E: 'static + Component,
+ F: FnOnce(&mut WindowContext) -> E + 'static,
{
- fn render(self) -> AnyElement<V> {
+ fn render(self) -> AnyElement {
AnyElement::new(Some(self))
}
}
@@ -1,9 +1,10 @@
use crate::{
point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext,
- BorrowWindow, Bounds, ClickEvent, Component, DispatchPhase, Element, ElementId, FocusEvent,
- FocusHandle, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent,
- MouseMoveEvent, MouseUpEvent, ParentComponent, Pixels, Point, Render, ScrollWheelEvent,
- SharedString, Size, Style, StyleRefinement, Styled, Task, View, ViewContext, Visibility,
+ BorrowWindow, Bounds, CallbackHandle, ClickEvent, Component, ConstructorHandle, DispatchPhase,
+ Element, ElementId, FocusEvent, FocusHandle, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId,
+ MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentComponent, Pixels, Point,
+ Render, ScrollWheelEvent, SharedString, Size, Style, StyleRefinement, Styled, Task, View,
+ Visibility, WindowContext,
};
use collections::HashMap;
use refineable::Refineable;
@@ -12,7 +13,6 @@ use std::{
any::{Any, TypeId},
cell::RefCell,
fmt::Debug,
- marker::PhantomData,
mem,
rc::Rc,
time::Duration,
@@ -28,30 +28,24 @@ pub struct GroupStyle {
pub style: StyleRefinement,
}
-pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
- fn interactivity(&mut self) -> &mut Interactivity<V>;
+pub trait InteractiveComponent: Sized + Element {
+ fn interactivity(&mut self) -> &mut Interactivity;
fn group(mut self, group: impl Into<SharedString>) -> Self {
self.interactivity().group = Some(group.into());
self
}
- fn id(mut self, id: impl Into<ElementId>) -> Stateful<V, Self> {
+ fn id(mut self, id: impl Into<ElementId>) -> Stateful<Self> {
self.interactivity().element_id = Some(id.into());
- Stateful {
- element: self,
- view_type: PhantomData,
- }
+ Stateful { element: self }
}
- fn track_focus(mut self, focus_handle: &FocusHandle) -> Focusable<V, Self> {
+ fn track_focus(mut self, focus_handle: &FocusHandle) -> Focusable<Self> {
self.interactivity().focusable = true;
self.interactivity().tracked_focus_handle = Some(focus_handle.clone());
- Focusable {
- element: self,
- view_type: PhantomData,
- }
+ Focusable { element: self }
}
fn key_context<C, E>(mut self, key_context: C) -> Self
@@ -85,29 +79,28 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
fn on_mouse_down(
mut self,
button: MouseButton,
- handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext<V>) + 'static,
+ handler: impl Into<CallbackHandle<MouseDownEvent>>,
) -> Self {
+ let handler = handler.into();
self.interactivity().mouse_down_listeners.push(Box::new(
- move |view, event, bounds, phase, cx| {
+ move |event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble
&& event.button == button
&& bounds.contains_point(&event.position)
{
- handler(view, event, cx)
+ (handler.callback)(event, cx)
}
},
));
self
}
- fn on_any_mouse_down(
- mut self,
- handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ fn on_any_mouse_down(mut self, handler: impl Into<CallbackHandle<MouseDownEvent>>) -> Self {
+ let handler = handler.into();
self.interactivity().mouse_down_listeners.push(Box::new(
- move |view, event, bounds, phase, cx| {
+ move |event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
- handler(view, event, cx)
+ (handler.callback)(event, cx)
}
},
));
@@ -117,43 +110,40 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
fn on_mouse_up(
mut self,
button: MouseButton,
- handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext<V>) + 'static,
+ handler: impl Into<CallbackHandle<MouseUpEvent>>,
) -> Self {
- self.interactivity().mouse_up_listeners.push(Box::new(
- move |view, event, bounds, phase, cx| {
+ let handler = handler.into();
+ self.interactivity()
+ .mouse_up_listeners
+ .push(Box::new(move |event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble
&& event.button == button
&& bounds.contains_point(&event.position)
{
- handler(view, event, cx)
+ (handler.callback)(event, cx)
}
- },
- ));
+ }));
self
}
- fn on_any_mouse_up(
- mut self,
- handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext<V>) + 'static,
- ) -> Self {
- self.interactivity().mouse_up_listeners.push(Box::new(
- move |view, event, bounds, phase, cx| {
+ fn on_any_mouse_up(mut self, handler: impl Into<CallbackHandle<MouseUpEvent>>) -> Self {
+ let handler = handler.into();
+ self.interactivity()
+ .mouse_up_listeners
+ .push(Box::new(move |event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
- handler(view, event, cx)
+ (handler.callback)(event, cx)
}
- },
- ));
+ }));
self
}
- fn on_mouse_down_out(
- mut self,
- handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ fn on_mouse_down_out(mut self, handler: impl Into<CallbackHandle<MouseDownEvent>>) -> Self {
+ let handler = handler.into();
self.interactivity().mouse_down_listeners.push(Box::new(
- move |view, event, bounds, phase, cx| {
+ move |event, bounds, phase, cx| {
if phase == DispatchPhase::Capture && !bounds.contains_point(&event.position) {
- handler(view, event, cx)
+ (handler.callback)(event, cx)
}
},
));
@@ -163,60 +153,55 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
fn on_mouse_up_out(
mut self,
button: MouseButton,
- handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext<V>) + 'static,
+ handler: impl Into<CallbackHandle<MouseUpEvent>>,
) -> Self {
- self.interactivity().mouse_up_listeners.push(Box::new(
- move |view, event, bounds, phase, cx| {
+ let handler = handler.into();
+ self.interactivity()
+ .mouse_up_listeners
+ .push(Box::new(move |event, bounds, phase, cx| {
if phase == DispatchPhase::Capture
&& event.button == button
&& !bounds.contains_point(&event.position)
{
- handler(view, event, cx);
+ (handler.callback)(event, cx);
}
- },
- ));
+ }));
self
}
- fn on_mouse_move(
- mut self,
- handler: impl Fn(&mut V, &MouseMoveEvent, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ fn on_mouse_move(mut self, handler: impl Into<CallbackHandle<MouseMoveEvent>>) -> Self {
+ let handler = handler.into();
self.interactivity().mouse_move_listeners.push(Box::new(
- move |view, event, bounds, phase, cx| {
+ move |event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
- handler(view, event, cx);
+ (handler.callback)(event, cx);
}
},
));
self
}
- fn on_scroll_wheel(
- mut self,
- handler: impl Fn(&mut V, &ScrollWheelEvent, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ fn on_scroll_wheel(mut self, handler: impl Into<CallbackHandle<ScrollWheelEvent>>) -> Self {
+ let handler = handler.into();
self.interactivity().scroll_wheel_listeners.push(Box::new(
- move |view, event, bounds, phase, cx| {
+ move |event, bounds, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
- handler(view, event, cx);
+ (handler.callback)(event, cx);
}
},
));
self
}
- /// Capture the given action, fires during the capture phase
- fn capture_action<A: Action>(
- mut self,
- listener: impl Fn(&mut V, &A, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ /// Capture the given action, before normal action dispatch can fire
+ fn capture_action<A: Action>(mut self, listener: impl Into<CallbackHandle<A>>) -> Self {
+ let listener = listener.into();
self.interactivity().action_listeners.push((
TypeId::of::<A>(),
- Box::new(move |view, action, phase, cx| {
+ Box::new(move |action, phase, cx| {
let action = action.downcast_ref().unwrap();
if phase == DispatchPhase::Capture {
- listener(view, action, cx)
+ (listener.callback)(action, cx)
}
}),
));
@@ -224,10 +209,8 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
}
/// Add a listener for the given action, fires during the bubble event phase
- fn on_action<A: Action>(
- mut self,
- listener: impl Fn(&mut V, &A, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ fn on_action<A: Action>(mut self, listener: impl Into<CallbackHandle<A>> + 'static) -> Self {
+ let handle = listener.into();
// NOTE: this debug assert has the side-effect of working around
// a bug where a crate consisting only of action definitions does
// not register the actions in debug builds:
@@ -244,36 +227,60 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
// );
self.interactivity().action_listeners.push((
TypeId::of::<A>(),
- Box::new(move |view, action, phase, cx| {
+ Box::new(move |action, phase, cx| {
let action = action.downcast_ref().unwrap();
if phase == DispatchPhase::Bubble {
- listener(view, action, cx)
+ (handle.callback)(action, cx)
}
}),
));
self
}
- fn on_key_down(
- mut self,
- listener: impl Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ fn on_key_down(mut self, listener: impl Into<CallbackHandle<KeyDownEvent>>) -> Self {
+ let listener = listener.into();
self.interactivity()
.key_down_listeners
- .push(Box::new(move |view, event, phase, cx| {
- listener(view, event, phase, cx)
+ .push(Box::new(move |event, phase, cx| {
+ if phase == DispatchPhase::Bubble {
+ (listener.callback)(event, cx)
+ }
}));
self
}
- fn on_key_up(
- mut self,
- listener: impl Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ fn capture_key_down(mut self, listener: impl Into<CallbackHandle<KeyDownEvent>>) -> Self {
+ let listener = listener.into();
+ self.interactivity()
+ .key_down_listeners
+ .push(Box::new(move |event, phase, cx| {
+ if phase == DispatchPhase::Capture {
+ (listener.callback)(event, cx)
+ }
+ }));
+ self
+ }
+
+ fn on_key_up(mut self, listener: impl Into<CallbackHandle<KeyUpEvent>>) -> Self {
+ let listener = listener.into();
self.interactivity()
.key_up_listeners
- .push(Box::new(move |view, event, phase, cx| {
- listener(view, event, phase, cx)
+ .push(Box::new(move |event, phase, cx| {
+ if phase == DispatchPhase::Bubble {
+ (listener.callback)(event, cx)
+ }
+ }));
+ self
+ }
+
+ fn capture_key_up(mut self, listener: impl Into<CallbackHandle<KeyUpEvent>>) -> Self {
+ let listener = listener.into();
+ self.interactivity()
+ .key_up_listeners
+ .push(Box::new(move |event, phase, cx| {
+ if phase == DispatchPhase::Capture {
+ (listener.callback)(event, cx)
+ }
}));
self
}
@@ -300,27 +307,22 @@ pub trait InteractiveComponent<V: 'static>: Sized + Element<V> {
self
}
- fn on_drop<W: 'static>(
- mut self,
- listener: impl Fn(&mut V, View<W>, &mut ViewContext<V>) + 'static,
- ) -> Self {
+ fn on_drop<W: 'static>(mut self, listener: impl Into<CallbackHandle<View<W>>>) -> Self {
+ let listener = listener.into();
self.interactivity().drop_listeners.push((
TypeId::of::<W>(),
- Box::new(move |view, dragged_view, cx| {
- listener(view, dragged_view.downcast().unwrap(), cx);
+ Box::new(move |dragged_view, cx| {
+ (listener.callback)(&dragged_view.downcast().unwrap(), cx);
}),
));
self
}
}
-pub trait StatefulInteractiveComponent<V: 'static, E: Element<V>>: InteractiveComponent<V> {
- fn focusable(mut self) -> Focusable<V, Self> {
+pub trait StatefulInteractiveComponent: InteractiveComponent {
+ fn focusable(mut self) -> Focusable<Self> {
self.interactivity().focusable = true;
- Focusable {
- element: self,
- view_type: PhantomData,
- }
+ Focusable { element: self }
}
fn overflow_scroll(mut self) -> Self {
@@ -362,70 +364,64 @@ pub trait StatefulInteractiveComponent<V: 'static, E: Element<V>>: InteractiveCo
self
}
- fn on_click(
- mut self,
- listener: impl Fn(&mut V, &ClickEvent, &mut ViewContext<V>) + 'static,
- ) -> Self
+ fn on_click(mut self, listener: impl Into<CallbackHandle<ClickEvent>>) -> Self
where
Self: Sized,
{
+ let listener = listener.into();
self.interactivity()
.click_listeners
- .push(Box::new(move |view, event, cx| listener(view, event, cx)));
+ .push(Box::new(move |event, cx| (listener.callback)(event, cx)));
self
}
- fn on_drag<W>(
- mut self,
- listener: impl Fn(&mut V, &mut ViewContext<V>) -> View<W> + 'static,
- ) -> Self
+ fn on_drag<W>(mut self, listener: impl Into<ConstructorHandle<View<W>>>) -> Self
where
Self: Sized,
W: 'static + Render,
{
+ let listener = listener.into();
debug_assert!(
self.interactivity().drag_listener.is_none(),
"calling on_drag more than once on the same element is not supported"
);
- self.interactivity().drag_listener =
- Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag {
- view: listener(view_state, cx).into(),
- cursor_offset,
- }));
+ self.interactivity().drag_listener = Some(Box::new(move |cursor_offset, cx| AnyDrag {
+ view: (listener.callback)(cx).into(),
+ cursor_offset,
+ }));
self
}
- fn on_hover(mut self, listener: impl 'static + Fn(&mut V, bool, &mut ViewContext<V>)) -> Self
+ fn on_hover(mut self, listener: impl Into<CallbackHandle<bool>>) -> Self
where
Self: Sized,
{
+ let listener = listener.into();
debug_assert!(
self.interactivity().hover_listener.is_none(),
"calling on_hover more than once on the same element is not supported"
);
- self.interactivity().hover_listener = Some(Box::new(listener));
+ self.interactivity().hover_listener = Some(listener);
self
}
- fn tooltip(
- mut self,
- build_tooltip: impl Fn(&mut V, &mut ViewContext<V>) -> AnyView + 'static,
- ) -> Self
+ fn tooltip(mut self, build_tooltip: impl Into<ConstructorHandle<AnyView>>) -> Self
where
Self: Sized,
{
+ let build_tooltip = build_tooltip.into();
debug_assert!(
self.interactivity().tooltip_builder.is_none(),
"calling tooltip more than once on the same element is not supported"
);
self.interactivity().tooltip_builder =
- Some(Rc::new(move |view_state, cx| build_tooltip(view_state, cx)));
+ Some(Rc::new(move |cx| (build_tooltip.callback)(cx)));
self
}
}
-pub trait FocusableComponent<V: 'static>: InteractiveComponent<V> {
+pub trait FocusableComponent: InteractiveComponent {
fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
where
Self: Sized,
@@ -442,49 +438,44 @@ pub trait FocusableComponent<V: 'static>: InteractiveComponent<V> {
self
}
- fn on_focus(
- mut self,
- listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
- ) -> Self
+ fn on_focus(mut self, listener: impl Into<CallbackHandle<FocusEvent>>) -> Self
where
Self: Sized,
{
- self.interactivity().focus_listeners.push(Box::new(
- move |view, focus_handle, event, cx| {
+ let listener = listener.into();
+ self.interactivity()
+ .focus_listeners
+ .push(Box::new(move |focus_handle, event, cx| {
if event.focused.as_ref() == Some(focus_handle) {
- listener(view, event, cx)
+ (listener.callback)(event, cx)
}
- },
- ));
+ }));
self
}
- fn on_blur(
- mut self,
- listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
- ) -> Self
+ fn on_blur(mut self, listener: impl Into<CallbackHandle<FocusEvent>>) -> Self
where
Self: Sized,
{
- self.interactivity().focus_listeners.push(Box::new(
- move |view, focus_handle, event, cx| {
+ let listener = listener.into();
+ self.interactivity()
+ .focus_listeners
+ .push(Box::new(move |focus_handle, event, cx| {
if event.blurred.as_ref() == Some(focus_handle) {
- listener(view, event, cx)
+ (listener.callback)(event, cx)
}
- },
- ));
+ }));
self
}
- fn on_focus_in(
- mut self,
- listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
- ) -> Self
+ fn on_focus_in(mut self, listener: impl Into<CallbackHandle<FocusEvent>>) -> Self
where
Self: Sized,
{
- self.interactivity().focus_listeners.push(Box::new(
- move |view, focus_handle, event, cx| {
+ let listener = listener.into();
+ self.interactivity()
+ .focus_listeners
+ .push(Box::new(move |focus_handle, event, cx| {
let descendant_blurred = event
.blurred
.as_ref()
@@ -495,22 +486,20 @@ pub trait FocusableComponent<V: 'static>: InteractiveComponent<V> {
.map_or(false, |focused| focus_handle.contains(focused, cx));
if !descendant_blurred && descendant_focused {
- listener(view, event, cx)
+ (listener.callback)(event, cx)
}
- },
- ));
+ }));
self
}
- fn on_focus_out(
- mut self,
- listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
- ) -> Self
+ fn on_focus_out(mut self, listener: impl Into<CallbackHandle<FocusEvent>>) -> Self
where
Self: Sized,
{
- self.interactivity().focus_listeners.push(Box::new(
- move |view, focus_handle, event, cx| {
+ let listener = listener.into();
+ self.interactivity()
+ .focus_listeners
+ .push(Box::new(move |focus_handle, event, cx| {
let descendant_blurred = event
.blurred
.as_ref()
@@ -520,86 +509,73 @@ pub trait FocusableComponent<V: 'static>: InteractiveComponent<V> {
.as_ref()
.map_or(false, |focused| focus_handle.contains(focused, cx));
if descendant_blurred && !descendant_focused {
- listener(view, event, cx)
+ (listener.callback)(event, cx)
}
- },
- ));
+ }));
self
}
}
-pub type FocusListeners<V> = SmallVec<[FocusListener<V>; 2]>;
+pub type FocusListeners = SmallVec<[FocusListener; 2]>;
-pub type FocusListener<V> =
- Box<dyn Fn(&mut V, &FocusHandle, &FocusEvent, &mut ViewContext<V>) + 'static>;
+pub type FocusListener = Box<dyn Fn(&FocusHandle, &FocusEvent, &mut WindowContext) + 'static>;
-pub type MouseDownListener<V> = Box<
- dyn Fn(&mut V, &MouseDownEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>) + 'static,
->;
-pub type MouseUpListener<V> = Box<
- dyn Fn(&mut V, &MouseUpEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>) + 'static,
->;
+pub type MouseDownListener =
+ Box<dyn Fn(&MouseDownEvent, &Bounds<Pixels>, DispatchPhase, &mut WindowContext) + 'static>;
+pub type MouseUpListener =
+ Box<dyn Fn(&MouseUpEvent, &Bounds<Pixels>, DispatchPhase, &mut WindowContext) + 'static>;
-pub type MouseMoveListener<V> = Box<
- dyn Fn(&mut V, &MouseMoveEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>) + 'static,
->;
+pub type MouseMoveListener =
+ Box<dyn Fn(&MouseMoveEvent, &Bounds<Pixels>, DispatchPhase, &mut WindowContext) + 'static>;
-pub type ScrollWheelListener<V> = Box<
- dyn Fn(&mut V, &ScrollWheelEvent, &Bounds<Pixels>, DispatchPhase, &mut ViewContext<V>)
- + 'static,
->;
+pub type ScrollWheelListener =
+ Box<dyn Fn(&ScrollWheelEvent, &Bounds<Pixels>, DispatchPhase, &mut WindowContext) + 'static>;
-pub type ClickListener<V> = Box<dyn Fn(&mut V, &ClickEvent, &mut ViewContext<V>) + 'static>;
+pub type ClickListener = Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>;
-pub type DragListener<V> =
- Box<dyn Fn(&mut V, Point<Pixels>, &mut ViewContext<V>) -> AnyDrag + 'static>;
+pub type DragListener = Box<dyn Fn(Point<Pixels>, &mut WindowContext) -> AnyDrag + 'static>;
-type DropListener<V> = dyn Fn(&mut V, AnyView, &mut ViewContext<V>) + 'static;
+type DropListener = dyn Fn(AnyView, &mut WindowContext) + 'static;
-pub type HoverListener<V> = Box<dyn Fn(&mut V, bool, &mut ViewContext<V>) + 'static>;
+pub type TooltipBuilder = Rc<dyn Fn(&mut WindowContext) -> AnyView + 'static>;
-pub type TooltipBuilder<V> = Rc<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyView + 'static>;
+pub type KeyDownListener = Box<dyn Fn(&KeyDownEvent, DispatchPhase, &mut WindowContext) + 'static>;
-pub type KeyDownListener<V> =
- Box<dyn Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext<V>) + 'static>;
+pub type KeyUpListener = Box<dyn Fn(&KeyUpEvent, DispatchPhase, &mut WindowContext) + 'static>;
-pub type KeyUpListener<V> =
- Box<dyn Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext<V>) + 'static>;
+pub type ActionListener = Box<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static>;
-pub type ActionListener<V> =
- Box<dyn Fn(&mut V, &dyn Any, DispatchPhase, &mut ViewContext<V>) + 'static>;
-
-pub fn div<V: 'static>() -> Div<V> {
+pub fn div() -> Div {
Div {
interactivity: Interactivity::default(),
children: SmallVec::default(),
}
}
-pub struct Div<V> {
- interactivity: Interactivity<V>,
- children: SmallVec<[AnyElement<V>; 2]>,
+pub struct Div {
+ interactivity: Interactivity,
+ children: SmallVec<[AnyElement; 2]>,
}
-impl<V> Styled for Div<V> {
+impl Styled for Div {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.interactivity.base_style
}
}
-impl<V: 'static> InteractiveComponent<V> for Div<V> {
- fn interactivity(&mut self) -> &mut Interactivity<V> {
+impl InteractiveComponent for Div {
+ fn interactivity(&mut self) -> &mut Interactivity {
&mut self.interactivity
}
}
-impl<V: 'static> ParentComponent<V> for Div<V> {
- fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
+impl ParentComponent for Div {
+ fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
&mut self.children
}
}
-impl<V: 'static> Element<V> for Div<V> {
+impl Element for Div {
type ElementState = DivState;
fn element_id(&self) -> Option<ElementId> {
@@ -608,9 +584,8 @@ impl<V: 'static> Element<V> for Div<V> {
fn layout(
&mut self,
- view_state: &mut V,
element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
let mut child_layout_ids = SmallVec::new();
let mut interactivity = mem::take(&mut self.interactivity);
@@ -622,7 +597,7 @@ impl<V: 'static> Element<V> for Div<V> {
child_layout_ids = self
.children
.iter_mut()
- .map(|child| child.layout(view_state, cx))
+ .map(|child| child.layout(cx))
.collect::<SmallVec<_>>();
cx.request_layout(&style, child_layout_ids.iter().copied())
})
@@ -641,9 +616,8 @@ impl<V: 'static> Element<V> for Div<V> {
fn paint(
&mut self,
bounds: Bounds<Pixels>,
- view_state: &mut V,
element_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) {
let mut child_min = point(Pixels::MAX, Pixels::MAX);
let mut child_max = Point::default();
@@ -680,7 +654,7 @@ impl<V: 'static> Element<V> for Div<V> {
cx.with_content_mask(style.overflow_mask(bounds), |cx| {
cx.with_element_offset(scroll_offset, |cx| {
for child in &mut self.children {
- child.paint(view_state, cx);
+ child.paint(cx);
}
})
})
@@ -693,8 +667,8 @@ impl<V: 'static> Element<V> for Div<V> {
}
}
-impl<V: 'static> Component<V> for Div<V> {
- fn render(self) -> AnyElement<V> {
+impl Component for Div {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
@@ -710,12 +684,12 @@ impl DivState {
}
}
-pub struct Interactivity<V> {
+pub struct Interactivity {
pub element_id: Option<ElementId>,
pub key_context: KeyContext,
pub focusable: bool,
pub tracked_focus_handle: Option<FocusHandle>,
- pub focus_listeners: FocusListeners<V>,
+ pub focus_listeners: FocusListeners,
pub group: Option<SharedString>,
pub base_style: StyleRefinement,
pub focus_style: StyleRefinement,
@@ -726,29 +700,26 @@ pub struct Interactivity<V> {
pub group_active_style: Option<GroupStyle>,
pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
- pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
- pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
- pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
- pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
- pub key_down_listeners: SmallVec<[KeyDownListener<V>; 2]>,
- pub key_up_listeners: SmallVec<[KeyUpListener<V>; 2]>,
- pub action_listeners: SmallVec<[(TypeId, ActionListener<V>); 8]>,
- pub drop_listeners: SmallVec<[(TypeId, Box<DropListener<V>>); 2]>,
- pub click_listeners: SmallVec<[ClickListener<V>; 2]>,
- pub drag_listener: Option<DragListener<V>>,
- pub hover_listener: Option<HoverListener<V>>,
- pub tooltip_builder: Option<TooltipBuilder<V>>,
+ pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>,
+ pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>,
+ pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>,
+ pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>,
+ pub key_down_listeners: SmallVec<[KeyDownListener; 2]>,
+ pub key_up_listeners: SmallVec<[KeyUpListener; 2]>,
+ pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>,
+ pub drop_listeners: SmallVec<[(TypeId, Box<DropListener>); 2]>,
+ pub click_listeners: SmallVec<[ClickListener; 2]>,
+ pub drag_listener: Option<DragListener>,
+ pub hover_listener: Option<CallbackHandle<bool>>,
+ pub tooltip_builder: Option<TooltipBuilder>,
}
-impl<V> Interactivity<V>
-where
- V: 'static,
-{
+impl Interactivity {
pub fn layout(
&mut self,
element_state: Option<InteractiveElementState>,
- cx: &mut ViewContext<V>,
- f: impl FnOnce(Style, &mut ViewContext<V>) -> LayoutId,
+ cx: &mut WindowContext,
+ f: impl FnOnce(Style, &mut WindowContext) -> LayoutId,
) -> (LayoutId, InteractiveElementState) {
let mut element_state = element_state.unwrap_or_default();
@@ -774,8 +745,8 @@ where
bounds: Bounds<Pixels>,
content_size: Size<Pixels>,
element_state: &mut InteractiveElementState,
- cx: &mut ViewContext<V>,
- f: impl FnOnce(Style, Point<Pixels>, &mut ViewContext<V>),
+ cx: &mut WindowContext,
+ f: impl FnOnce(Style, Point<Pixels>, &mut WindowContext),
) {
let style = self.compute_style(Some(bounds), element_state, cx);
@@ -787,26 +758,26 @@ where
}
for listener in self.mouse_down_listeners.drain(..) {
- cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
- listener(state, event, &bounds, phase, cx);
+ cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
+ listener(event, &bounds, phase, cx);
})
}
for listener in self.mouse_up_listeners.drain(..) {
- cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
- listener(state, event, &bounds, phase, cx);
+ cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
+ listener(event, &bounds, phase, cx);
})
}
for listener in self.mouse_move_listeners.drain(..) {
- cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
- listener(state, event, &bounds, phase, cx);
+ cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
+ listener(event, &bounds, phase, cx);
})
}
for listener in self.scroll_wheel_listeners.drain(..) {
- cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
- listener(state, event, &bounds, phase, cx);
+ cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| {
+ listener(event, &bounds, phase, cx);
})
}
@@ -817,7 +788,7 @@ where
if let Some(group_bounds) = hover_group_bounds {
let hovered = group_bounds.contains_point(&cx.mouse_position());
- cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
+ cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
if phase == DispatchPhase::Capture {
if group_bounds.contains_point(&event.position) != hovered {
cx.notify();
@@ -830,7 +801,7 @@ where
|| (cx.active_drag.is_some() && !self.drag_over_styles.is_empty())
{
let hovered = bounds.contains_point(&cx.mouse_position());
- 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 {
cx.notify();
@@ -841,7 +812,7 @@ where
if cx.active_drag.is_some() {
let drop_listeners = mem::take(&mut self.drop_listeners);
- cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| {
+ cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
if let Some(drag_state_type) =
cx.active_drag.as_ref().map(|drag| drag.view.entity_type())
@@ -852,7 +823,7 @@ where
.active_drag
.take()
.expect("checked for type drag state type above");
- listener(view, drag.view.clone(), cx);
+ listener(drag.view.clone(), cx);
cx.notify();
cx.stop_propagation();
}
@@ -872,7 +843,7 @@ where
if let Some(drag_listener) = drag_listener {
let active_state = element_state.clicked_state.clone();
- cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| {
+ cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
if cx.active_drag.is_some() {
if phase == DispatchPhase::Capture {
cx.notify();
@@ -883,7 +854,7 @@ where
{
*active_state.borrow_mut() = ElementClickedState::default();
let cursor_offset = event.position - bounds.origin;
- let drag = drag_listener(view_state, cursor_offset, cx);
+ let drag = drag_listener(cursor_offset, cx);
cx.active_drag = Some(drag);
cx.notify();
cx.stop_propagation();
@@ -891,21 +862,21 @@ where
});
}
- cx.on_mouse_event(move |view_state, event: &MouseUpEvent, phase, cx| {
+ cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
let mouse_click = ClickEvent {
down: mouse_down.clone(),
up: event.clone(),
};
for listener in &click_listeners {
- listener(view_state, &mouse_click, cx);
+ listener(&mouse_click, cx);
}
}
*pending_mouse_down.borrow_mut() = None;
cx.notify();
});
} else {
- cx.on_mouse_event(move |_view_state, event: &MouseDownEvent, phase, cx| {
+ cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
*pending_mouse_down.borrow_mut() = Some(event.clone());
cx.notify();
@@ -918,7 +889,7 @@ where
let was_hovered = element_state.hover_state.clone();
let has_mouse_down = element_state.pending_mouse_down.clone();
- cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| {
+ cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
if phase != DispatchPhase::Bubble {
return;
}
@@ -930,7 +901,7 @@ where
*was_hovered = is_hovered;
drop(was_hovered);
- hover_listener(view_state, is_hovered, cx);
+ (hover_listener.callback)(&is_hovered, cx);
}
});
}
@@ -939,7 +910,7 @@ where
let active_tooltip = element_state.active_tooltip.clone();
let pending_mouse_down = element_state.pending_mouse_down.clone();
- cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
+ cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
if phase != DispatchPhase::Bubble {
return;
}
@@ -956,12 +927,12 @@ where
let active_tooltip = active_tooltip.clone();
let tooltip_builder = tooltip_builder.clone();
- move |view, mut cx| async move {
+ move |mut cx| async move {
cx.background_executor().timer(TOOLTIP_DELAY).await;
- view.update(&mut cx, move |view_state, cx| {
+ cx.update(|_, cx| {
active_tooltip.borrow_mut().replace(ActiveTooltip {
tooltip: Some(AnyTooltip {
- view: tooltip_builder(view_state, cx),
+ view: tooltip_builder(cx),
cursor_offset: cx.mouse_position(),
}),
_task: None,
@@ -979,7 +950,7 @@ where
});
let active_tooltip = element_state.active_tooltip.clone();
- cx.on_mouse_event(move |_, _: &MouseDownEvent, _, _| {
+ cx.on_mouse_event(move |_: &MouseDownEvent, _, _| {
active_tooltip.borrow_mut().take();
});
@@ -992,7 +963,7 @@ where
let active_state = element_state.clicked_state.clone();
if !active_state.borrow().is_clicked() {
- cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| {
+ cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| {
if phase == DispatchPhase::Capture {
*active_state.borrow_mut() = ElementClickedState::default();
cx.notify();
@@ -1003,7 +974,7 @@ where
.group_active_style
.as_ref()
.and_then(|group_active| GroupBounds::get(&group_active.group, cx));
- cx.on_mouse_event(move |_view, down: &MouseDownEvent, phase, cx| {
+ cx.on_mouse_event(move |down: &MouseDownEvent, phase, cx| {
if phase == DispatchPhase::Bubble {
let group = active_group_bounds
.map_or(false, |bounds| bounds.contains_point(&down.position));
@@ -1025,7 +996,7 @@ where
let line_height = cx.line_height();
let scroll_max = (content_size - bounds.size).max(&Size::default());
- cx.on_mouse_event(move |_, event: &ScrollWheelEvent, phase, cx| {
+ cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
let mut scroll_offset = scroll_offset.borrow_mut();
let old_scroll_offset = *scroll_offset;
@@ -1063,14 +1034,14 @@ where
element_state.focus_handle.clone(),
|_, cx| {
for listener in self.key_down_listeners.drain(..) {
- cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| {
- listener(state, event, phase, cx);
+ cx.on_key_event(move |event: &KeyDownEvent, phase, cx| {
+ listener(event, phase, cx);
})
}
for listener in self.key_up_listeners.drain(..) {
- cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| {
- listener(state, event, phase, cx);
+ cx.on_key_event(move |event: &KeyUpEvent, phase, cx| {
+ listener(event, phase, cx);
})
}
@@ -1081,9 +1052,7 @@ where
if let Some(focus_handle) = element_state.focus_handle.as_ref() {
for listener in self.focus_listeners.drain(..) {
let focus_handle = focus_handle.clone();
- cx.on_focus_changed(move |view, event, cx| {
- listener(view, &focus_handle, event, cx)
- });
+ cx.on_focus_changed(move |event, cx| listener(&focus_handle, event, cx));
}
}
@@ -1,18 +1,17 @@
use crate::{
- AnyElement, BorrowWindow, Bounds, Component, Element, InteractiveComponent,
- InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement,
- Styled, ViewContext,
+ AnyElement, Bounds, Component, Element, InteractiveComponent, InteractiveElementState,
+ Interactivity, LayoutId, Pixels, SharedString, StyleRefinement, Styled, WindowContext,
};
use futures::FutureExt;
use util::ResultExt;
-pub struct Img<V: 'static> {
- interactivity: Interactivity<V>,
+pub struct Img {
+ interactivity: Interactivity,
uri: Option<SharedString>,
grayscale: bool,
}
-pub fn img<V: 'static>() -> Img<V> {
+pub fn img() -> Img {
Img {
interactivity: Interactivity::default(),
uri: None,
@@ -20,10 +19,7 @@ pub fn img<V: 'static>() -> Img<V> {
}
}
-impl<V> Img<V>
-where
- V: 'static,
-{
+impl Img {
pub fn uri(mut self, uri: impl Into<SharedString>) -> Self {
self.uri = Some(uri.into());
self
@@ -35,13 +31,13 @@ where
}
}
-impl<V> Component<V> for Img<V> {
- fn render(self) -> AnyElement<V> {
+impl Component for Img {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
-impl<V> Element<V> for Img<V> {
+impl Element for Img {
type ElementState = InteractiveElementState;
fn element_id(&self) -> Option<crate::ElementId> {
@@ -50,9 +46,8 @@ impl<V> Element<V> for Img<V> {
fn layout(
&mut self,
- _view_state: &mut V,
element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
self.interactivity.layout(element_state, cx, |style, cx| {
cx.request_layout(&style, None)
@@ -62,9 +57,8 @@ impl<V> Element<V> for Img<V> {
fn paint(
&mut self,
bounds: Bounds<Pixels>,
- _view_state: &mut V,
element_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) {
self.interactivity.paint(
bounds,
@@ -89,7 +83,7 @@ impl<V> Element<V> for Img<V> {
.log_err()
});
} else {
- cx.spawn(|_, mut cx| async move {
+ cx.spawn(|mut cx| async move {
if image_future.await.ok().is_some() {
cx.on_next_frame(|cx| cx.notify());
}
@@ -102,14 +96,14 @@ impl<V> Element<V> for Img<V> {
}
}
-impl<V> Styled for Img<V> {
+impl Styled for Img {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.interactivity.base_style
}
}
-impl<V> InteractiveComponent<V> for Img<V> {
- fn interactivity(&mut self) -> &mut Interactivity<V> {
+impl InteractiveComponent for Img {
+ fn interactivity(&mut self) -> &mut Interactivity {
&mut self.interactivity
}
}
@@ -3,15 +3,15 @@ use taffy::style::{Display, Position};
use crate::{
point, AnyElement, BorrowWindow, Bounds, Component, Element, LayoutId, ParentComponent, Pixels,
- Point, Size, Style,
+ Point, Size, Style, WindowContext,
};
pub struct OverlayState {
child_layout_ids: SmallVec<[LayoutId; 4]>,
}
-pub struct Overlay<V> {
- children: SmallVec<[AnyElement<V>; 2]>,
+pub struct Overlay {
+ children: SmallVec<[AnyElement; 2]>,
anchor_corner: AnchorCorner,
fit_mode: OverlayFitMode,
// todo!();
@@ -21,7 +21,7 @@ pub struct Overlay<V> {
/// overlay gives you a floating element that will avoid overflowing the window bounds.
/// Its children should have no margin to avoid measurement issues.
-pub fn overlay<V: 'static>() -> Overlay<V> {
+pub fn overlay() -> Overlay {
Overlay {
children: SmallVec::new(),
anchor_corner: AnchorCorner::TopLeft,
@@ -30,7 +30,7 @@ pub fn overlay<V: 'static>() -> Overlay<V> {
}
}
-impl<V> Overlay<V> {
+impl Overlay {
/// Sets which corner of the overlay should be anchored to the current position.
pub fn anchor(mut self, anchor: AnchorCorner) -> Self {
self.anchor_corner = anchor;
@@ -51,19 +51,19 @@ impl<V> Overlay<V> {
}
}
-impl<V: 'static> ParentComponent<V> for Overlay<V> {
- fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
+impl ParentComponent for Overlay {
+ fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
&mut self.children
}
}
-impl<V: 'static> Component<V> for Overlay<V> {
- fn render(self) -> AnyElement<V> {
+impl Component for Overlay {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
-impl<V: 'static> Element<V> for Overlay<V> {
+impl Element for Overlay {
type ElementState = OverlayState;
fn element_id(&self) -> Option<crate::ElementId> {
@@ -72,14 +72,13 @@ impl<V: 'static> Element<V> for Overlay<V> {
fn layout(
&mut self,
- view_state: &mut V,
_: Option<Self::ElementState>,
- cx: &mut crate::ViewContext<V>,
+ cx: &mut WindowContext,
) -> (crate::LayoutId, Self::ElementState) {
let child_layout_ids = self
.children
.iter_mut()
- .map(|child| child.layout(view_state, cx))
+ .map(|child| child.layout(cx))
.collect::<SmallVec<_>>();
let mut overlay_style = Style::default();
@@ -94,9 +93,8 @@ impl<V: 'static> Element<V> for Overlay<V> {
fn paint(
&mut self,
bounds: crate::Bounds<crate::Pixels>,
- view_state: &mut V,
element_state: &mut Self::ElementState,
- cx: &mut crate::ViewContext<V>,
+ cx: &mut WindowContext,
) {
if element_state.child_layout_ids.is_empty() {
return;
@@ -157,7 +155,7 @@ impl<V: 'static> Element<V> for Overlay<V> {
cx.with_element_offset(desired.origin - bounds.origin, |cx| {
for child in &mut self.children {
- child.paint(view_state, cx);
+ child.paint(cx);
}
})
}
@@ -1,36 +1,36 @@
use crate::{
AnyElement, Bounds, Component, Element, ElementId, InteractiveComponent,
InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement,
- Styled, ViewContext,
+ Styled, WindowContext,
};
use util::ResultExt;
-pub struct Svg<V: 'static> {
- interactivity: Interactivity<V>,
+pub struct Svg {
+ interactivity: Interactivity,
path: Option<SharedString>,
}
-pub fn svg<V: 'static>() -> Svg<V> {
+pub fn svg() -> Svg {
Svg {
interactivity: Interactivity::default(),
path: None,
}
}
-impl<V> Svg<V> {
+impl Svg {
pub fn path(mut self, path: impl Into<SharedString>) -> Self {
self.path = Some(path.into());
self
}
}
-impl<V> Component<V> for Svg<V> {
- fn render(self) -> AnyElement<V> {
+impl Component for Svg {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
-impl<V> Element<V> for Svg<V> {
+impl Element for Svg {
type ElementState = InteractiveElementState;
fn element_id(&self) -> Option<ElementId> {
@@ -39,9 +39,8 @@ impl<V> Element<V> for Svg<V> {
fn layout(
&mut self,
- _view_state: &mut V,
element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
self.interactivity.layout(element_state, cx, |style, cx| {
cx.request_layout(&style, None)
@@ -51,9 +50,8 @@ impl<V> Element<V> for Svg<V> {
fn paint(
&mut self,
bounds: Bounds<Pixels>,
- _view_state: &mut V,
element_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) where
Self: Sized,
{
@@ -66,14 +64,14 @@ impl<V> Element<V> for Svg<V> {
}
}
-impl<V> Styled for Svg<V> {
+impl Styled for Svg {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.interactivity.base_style
}
}
-impl<V> InteractiveComponent<V> for Svg<V> {
- fn interactivity(&mut self) -> &mut Interactivity<V> {
+impl InteractiveComponent for Svg {
+ fn interactivity(&mut self) -> &mut Interactivity {
&mut self.interactivity
}
}
@@ -1,6 +1,6 @@
use crate::{
- AnyElement, BorrowWindow, Bounds, Component, Element, ElementId, LayoutId, Pixels,
- SharedString, Size, TextRun, ViewContext, WrappedLine,
+ AnyElement, Bounds, Component, Element, ElementId, LayoutId, Pixels, SharedString, Size,
+ TextRun, WindowContext, WrappedLine,
};
use parking_lot::{Mutex, MutexGuard};
use smallvec::SmallVec;
@@ -26,13 +26,13 @@ impl Text {
}
}
-impl<V: 'static> Component<V> for Text {
- fn render(self) -> AnyElement<V> {
+impl Component for Text {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
-impl<V: 'static> Element<V> for Text {
+impl Element for Text {
type ElementState = TextState;
fn element_id(&self) -> Option<crate::ElementId> {
@@ -41,9 +41,8 @@ impl<V: 'static> Element<V> for Text {
fn layout(
&mut self,
- _view: &mut V,
element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
let element_state = element_state.unwrap_or_default();
let text_system = cx.text_system().clone();
@@ -120,9 +119,8 @@ impl<V: 'static> Element<V> for Text {
fn paint(
&mut self,
bounds: Bounds<Pixels>,
- _: &mut V,
element_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) {
let element_state = element_state.lock();
let element_state = element_state
@@ -165,7 +163,7 @@ struct InteractiveTextState {
clicked_range_ixs: Rc<Cell<SmallVec<[usize; 1]>>>,
}
-impl<V: 'static> Element<V> for InteractiveText {
+impl Element for InteractiveText {
type ElementState = InteractiveTextState;
fn element_id(&self) -> Option<ElementId> {
@@ -174,23 +172,22 @@ impl<V: 'static> Element<V> for InteractiveText {
fn layout(
&mut self,
- view_state: &mut V,
element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
if let Some(InteractiveTextState {
text_state,
clicked_range_ixs,
}) = element_state
{
- let (layout_id, text_state) = self.text.layout(view_state, Some(text_state), cx);
+ let (layout_id, text_state) = self.text.layout(Some(text_state), cx);
let element_state = InteractiveTextState {
text_state,
clicked_range_ixs,
};
(layout_id, element_state)
} else {
- let (layout_id, text_state) = self.text.layout(view_state, None, cx);
+ let (layout_id, text_state) = self.text.layout(None, cx);
let element_state = InteractiveTextState {
text_state,
clicked_range_ixs: Rc::default(),
@@ -202,17 +199,15 @@ impl<V: 'static> Element<V> for InteractiveText {
fn paint(
&mut self,
bounds: Bounds<Pixels>,
- view_state: &mut V,
element_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) {
- self.text
- .paint(bounds, view_state, &mut element_state.text_state, cx)
+ self.text.paint(bounds, &mut element_state.text_state, cx)
}
}
-impl<V: 'static> Component<V> for SharedString {
- fn render(self) -> AnyElement<V> {
+impl Component for SharedString {
+ fn render(self) -> AnyElement {
Text {
text: self,
runs: None,
@@ -221,8 +216,8 @@ impl<V: 'static> Component<V> for SharedString {
}
}
-impl<V: 'static> Component<V> for &'static str {
- fn render(self) -> AnyElement<V> {
+impl Component for &'static str {
+ fn render(self) -> AnyElement {
Text {
text: self.into(),
runs: None,
@@ -233,8 +228,8 @@ impl<V: 'static> Component<V> for &'static str {
// TODO: Figure out how to pass `String` to `child` without this.
// This impl doesn't exist in the `gpui2` crate.
-impl<V: 'static> Component<V> for String {
- fn render(self) -> AnyElement<V> {
+impl Component for String {
+ fn render(self) -> AnyElement {
Text {
text: self.into(),
runs: None,
@@ -1,7 +1,7 @@
use crate::{
- point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element,
- ElementId, InteractiveComponent, InteractiveElementState, Interactivity, LayoutId, Pixels,
- Point, Size, StyleRefinement, Styled, ViewContext,
+ point, px, size, AnyElement, AvailableSpace, Bounds, Component, Element, ElementId,
+ InteractiveComponent, InteractiveElementState, Interactivity, LayoutId, Pixels, Point, Size,
+ StyleRefinement, Styled, WindowContext,
};
use smallvec::SmallVec;
use std::{cell::RefCell, cmp, mem, ops::Range, rc::Rc};
@@ -10,15 +10,14 @@ use taffy::style::Overflow;
/// uniform_list provides lazy rendering for a set of items that are of uniform height.
/// When rendered into a container with overflow-y: hidden and a fixed (or max) height,
/// uniform_list will only render the visibile subset of items.
-pub fn uniform_list<I, V, C>(
+pub fn uniform_list<I, C>(
id: I,
item_count: usize,
- f: impl 'static + Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> Vec<C>,
-) -> UniformList<V>
+ f: impl 'static + Fn(Range<usize>, &mut WindowContext) -> Vec<C>,
+) -> UniformList
where
I: Into<ElementId>,
- V: 'static,
- C: Component<V>,
+ C: Component,
{
let id = id.into();
let mut style = StyleRefinement::default();
@@ -29,8 +28,8 @@ where
style,
item_count,
item_to_measure_index: 0,
- render_items: Box::new(move |view, visible_range, cx| {
- f(view, visible_range, cx)
+ render_items: Box::new(move |visible_range, cx| {
+ f(visible_range, cx)
.into_iter()
.map(|component| component.render())
.collect()
@@ -43,19 +42,14 @@ where
}
}
-pub struct UniformList<V: 'static> {
+pub struct UniformList {
id: ElementId,
style: StyleRefinement,
item_count: usize,
item_to_measure_index: usize,
- render_items: Box<
- dyn for<'a> Fn(
- &'a mut V,
- Range<usize>,
- &'a mut ViewContext<V>,
- ) -> SmallVec<[AnyElement<V>; 64]>,
- >,
- interactivity: Interactivity<V>,
+ render_items:
+ Box<dyn for<'a> Fn(Range<usize>, &'a mut WindowContext) -> SmallVec<[AnyElement; 64]>>,
+ interactivity: Interactivity,
scroll_handle: Option<UniformListScrollHandle>,
}
@@ -89,7 +83,7 @@ impl UniformListScrollHandle {
}
}
-impl<V: 'static> Styled for UniformList<V> {
+impl Styled for UniformList {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.style
}
@@ -101,7 +95,7 @@ pub struct UniformListState {
item_size: Size<Pixels>,
}
-impl<V: 'static> Element<V> for UniformList<V> {
+impl Element for UniformList {
type ElementState = UniformListState;
fn element_id(&self) -> Option<crate::ElementId> {
@@ -110,16 +104,15 @@ impl<V: 'static> Element<V> for UniformList<V> {
fn layout(
&mut self,
- view_state: &mut V,
element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
let max_items = self.item_count;
let rem_size = cx.rem_size();
let item_size = element_state
.as_ref()
.map(|s| s.item_size)
- .unwrap_or_else(|| self.measure_item(view_state, None, cx));
+ .unwrap_or_else(|| self.measure_item(None, cx));
let (layout_id, interactive) =
self.interactivity
@@ -161,9 +154,8 @@ impl<V: 'static> Element<V> for UniformList<V> {
fn paint(
&mut self,
bounds: Bounds<crate::Pixels>,
- view_state: &mut V,
element_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
+ cx: &mut WindowContext,
) {
let style =
self.interactivity
@@ -209,9 +201,8 @@ impl<V: 'static> Element<V> for UniformList<V> {
style.paint(bounds, cx);
if self.item_count > 0 {
- let item_height = self
- .measure_item(view_state, Some(padded_bounds.size.width), cx)
- .height;
+ let item_height =
+ self.measure_item(Some(padded_bounds.size.width), cx).height;
if let Some(scroll_handle) = self.scroll_handle.clone() {
scroll_handle.0.borrow_mut().replace(ScrollHandleState {
item_height,
@@ -233,7 +224,7 @@ impl<V: 'static> Element<V> for UniformList<V> {
self.item_count,
);
- let mut items = (self.render_items)(view_state, visible_range.clone(), cx);
+ let mut items = (self.render_items)(visible_range.clone(), cx);
cx.with_z_index(1, |cx| {
for (item, ix) in items.iter_mut().zip(visible_range) {
let item_origin = padded_bounds.origin
@@ -242,7 +233,7 @@ impl<V: 'static> Element<V> for UniformList<V> {
AvailableSpace::Definite(padded_bounds.size.width),
AvailableSpace::Definite(item_height),
);
- item.draw(item_origin, available_space, view_state, cx);
+ item.draw(item_origin, available_space, cx);
}
});
}
@@ -253,24 +244,19 @@ impl<V: 'static> Element<V> for UniformList<V> {
}
}
-impl<V> UniformList<V> {
+impl UniformList {
pub fn with_width_from_item(mut self, item_index: Option<usize>) -> Self {
self.item_to_measure_index = item_index.unwrap_or(0);
self
}
- fn measure_item(
- &self,
- view_state: &mut V,
- list_width: Option<Pixels>,
- cx: &mut ViewContext<V>,
- ) -> Size<Pixels> {
+ fn measure_item(&self, list_width: Option<Pixels>, cx: &mut WindowContext) -> Size<Pixels> {
if self.item_count == 0 {
return Size::default();
}
let item_ix = cmp::min(self.item_to_measure_index, self.item_count - 1);
- let mut items = (self.render_items)(view_state, item_ix..item_ix + 1, cx);
+ let mut items = (self.render_items)(item_ix..item_ix + 1, cx);
let mut item_to_measure = items.pop().unwrap();
let available_space = size(
list_width.map_or(AvailableSpace::MinContent, |width| {
@@ -278,7 +264,7 @@ impl<V> UniformList<V> {
}),
AvailableSpace::MinContent,
);
- item_to_measure.measure(available_space, view_state, cx)
+ item_to_measure.measure(available_space, cx)
}
pub fn track_scroll(mut self, handle: UniformListScrollHandle) -> Self {
@@ -287,14 +273,14 @@ impl<V> UniformList<V> {
}
}
-impl<V> InteractiveComponent<V> for UniformList<V> {
- fn interactivity(&mut self) -> &mut crate::Interactivity<V> {
+impl InteractiveComponent for UniformList {
+ fn interactivity(&mut self) -> &mut crate::Interactivity {
&mut self.interactivity
}
}
-impl<V: 'static> Component<V> for UniformList<V> {
- fn render(self) -> AnyElement<V> {
+impl Component for UniformList {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
@@ -196,6 +196,30 @@ where
}
}
+pub struct CallbackHandle<E> {
+ callback: Box<dyn Fn(&E, &mut WindowContext) + 'static>,
+}
+
+impl<E, F: Fn(&E, &mut WindowContext) + 'static> From<F> for CallbackHandle<E> {
+ fn from(value: F) -> Self {
+ CallbackHandle {
+ callback: Box::new(value),
+ }
+ }
+}
+
+pub struct ConstructorHandle<R> {
+ callback: Box<dyn Fn(&mut WindowContext) -> R + 'static>,
+}
+
+impl<R, F: Fn(&mut WindowContext) -> R + 'static> From<F> for ConstructorHandle<R> {
+ fn from(value: F) -> Self {
+ ConstructorHandle {
+ callback: Box::new(value),
+ }
+ }
+}
+
pub trait Flatten<T> {
fn flatten(self) -> Result<T>;
}
@@ -1,9 +1,8 @@
use crate::{
- div, point, Component, Div, FocusHandle, Keystroke, Modifiers, Pixels, Point, Render,
- ViewContext,
+ div, point, Div, FocusHandle, Keystroke, Modifiers, Pixels, Point, Render, ViewContext,
};
use smallvec::SmallVec;
-use std::{any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf};
+use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyDownEvent {
@@ -60,32 +59,6 @@ pub struct ClickEvent {
pub up: MouseUpEvent,
}
-pub struct Drag<S, R, V, E>
-where
- R: Fn(&mut V, &mut ViewContext<V>) -> E,
- V: 'static,
- E: Component<()>,
-{
- pub state: S,
- pub render_drag_handle: R,
- view_type: PhantomData<V>,
-}
-
-impl<S, R, V, E> Drag<S, R, V, E>
-where
- R: Fn(&mut V, &mut ViewContext<V>) -> E,
- V: 'static,
- E: Component<()>,
-{
- pub fn new(state: S, render_drag_handle: R) -> Self {
- Drag {
- state,
- render_drag_handle,
- view_type: PhantomData,
- }
- }
-}
-
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
pub enum MouseButton {
Left,
@@ -194,7 +167,7 @@ impl Deref for MouseExitEvent {
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
impl Render for ExternalPaths {
- type Element = Div<Self>;
+ type Element = Div;
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
div() // Intentionally left empty because the platform will render icons for the dragged files
@@ -287,7 +260,7 @@ pub struct FocusEvent {
mod test {
use crate::{
self as gpui, div, Component, Div, FocusHandle, InteractiveComponent, KeyBinding,
- Keystroke, ParentComponent, Render, Stateful, TestAppContext, ViewContext, VisualContext,
+ Keystroke, ParentComponent, Render, Stateful, TestAppContext, VisualContext,
};
struct TestView {
@@ -299,20 +272,24 @@ mod test {
actions!(TestAction);
impl Render for TestView {
- type Element = Stateful<Self, Div<Self>>;
+ type Element = Stateful<Div>;
- fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> Self::Element {
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
div().id("testview").child(
div()
.key_context("parent")
- .on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true)
- .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true)
- .child(|this: &mut Self, _cx: &mut ViewContext<Self>| {
+ .on_key_down(cx.callback(|this, _, _| this.saw_key_down = true))
+ .on_action(
+ cx.callback(|this: &mut TestView, _: &TestAction, _| {
+ this.saw_action = true
+ }),
+ )
+ .child(
div()
.key_context("nested")
- .track_focus(&this.focus_handle)
- .render()
- }),
+ .track_focus(&self.focus_handle)
+ .render(),
+ ),
)
}
}
@@ -2,7 +2,7 @@ use crate::{
black, phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask,
Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, Font,
FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba,
- SharedString, Size, SizeRefinement, Styled, TextRun, ViewContext,
+ SharedString, Size, SizeRefinement, Styled, TextRun, WindowContext,
};
use refineable::{Cascade, Refineable};
use smallvec::SmallVec;
@@ -313,7 +313,7 @@ impl Style {
}
/// Paints the background of an element styled with this style.
- pub fn paint<V: 'static>(&self, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
+ pub fn paint(&self, bounds: Bounds<Pixels>, cx: &mut WindowContext) {
let rem_size = cx.rem_size();
cx.with_z_index(0, |cx| {
@@ -11,7 +11,7 @@ use std::{
};
pub trait Render: 'static + Sized {
- type Element: Element<Self> + 'static;
+ type Element: Element + 'static;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element;
}
@@ -67,7 +67,7 @@ impl<V: 'static> View<V> {
pub fn render_with<C>(&self, component: C) -> RenderViewWith<C, V>
where
- C: 'static + Component<V>,
+ C: 'static + Component,
{
RenderViewWith {
view: self.clone(),
@@ -105,8 +105,8 @@ impl<V> PartialEq for View<V> {
impl<V> Eq for View<V> {}
-impl<V: Render, ParentViewState: 'static> Component<ParentViewState> for View<V> {
- fn render(self) -> AnyElement<ParentViewState> {
+impl<V: Render> Component for View<V> {
+ fn render(self) -> AnyElement {
AnyElement::new(AnyView::from(self))
}
}
@@ -211,8 +211,8 @@ impl AnyView {
}
}
-impl<V: 'static> Component<V> for AnyView {
- fn render(self) -> AnyElement<V> {
+impl Component for AnyView {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
@@ -227,7 +227,7 @@ impl<V: Render> From<View<V>> for AnyView {
}
}
-impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
+impl Element for AnyView {
type ElementState = Box<dyn Any>;
fn element_id(&self) -> Option<ElementId> {
@@ -236,9 +236,8 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
fn layout(
&mut self,
- _view_state: &mut ParentViewState,
_element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<ParentViewState>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
(self.layout)(self, cx)
}
@@ -246,9 +245,8 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
fn paint(
&mut self,
_bounds: Bounds<Pixels>,
- _view_state: &mut ParentViewState,
rendered_element: &mut Self::ElementState,
- cx: &mut ViewContext<ParentViewState>,
+ cx: &mut WindowContext,
) {
(self.paint)(self, rendered_element, cx)
}
@@ -281,41 +279,39 @@ impl<V: Render> From<WeakView<V>> for AnyWeakView {
}
}
-// impl<T, E> Render for T
-// where
-// T: 'static + FnMut(&mut WindowContext) -> E,
-// E: 'static + Send + Element<T>,
-// {
-// type Element = E;
+impl<T, E> Render for T
+where
+ T: 'static + FnMut(&mut WindowContext) -> E,
+ E: 'static + Send + Element,
+{
+ type Element = E;
-// fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
-// (self)(cx)
-// }
-// }
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ (self)(cx)
+ }
+}
pub struct RenderViewWith<C, V> {
view: View<V>,
component: Option<C>,
}
-impl<C, ParentViewState, ViewState> Component<ParentViewState> for RenderViewWith<C, ViewState>
+impl<C, V> Component for RenderViewWith<C, V>
where
- C: 'static + Component<ViewState>,
- ParentViewState: 'static,
- ViewState: 'static,
+ V: 'static + Render,
+ C: 'static + Component,
{
- fn render(self) -> AnyElement<ParentViewState> {
+ fn render(self) -> AnyElement {
AnyElement::new(self)
}
}
-impl<C, ParentViewState, ViewState> Element<ParentViewState> for RenderViewWith<C, ViewState>
+impl<C, V> Element for RenderViewWith<C, V>
where
- C: 'static + Component<ViewState>,
- ParentViewState: 'static,
- ViewState: 'static,
+ V: 'static + Render,
+ C: 'static + Component,
{
- type ElementState = AnyElement<ViewState>;
+ type ElementState = AnyElement;
fn element_id(&self) -> Option<ElementId> {
Some(self.view.entity_id().into())
@@ -323,25 +319,21 @@ where
fn layout(
&mut self,
- _: &mut ParentViewState,
_: Option<Self::ElementState>,
- cx: &mut ViewContext<ParentViewState>,
+ cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) {
- self.view.update(cx, |view, cx| {
- let mut element = self.component.take().unwrap().render();
- let layout_id = element.layout(view, cx);
- (layout_id, element)
- })
+ let mut element = self.component.take().unwrap().render();
+ let layout_id = element.layout(cx);
+ (layout_id, element)
}
fn paint(
&mut self,
_: Bounds<Pixels>,
- _: &mut ParentViewState,
element: &mut Self::ElementState,
- cx: &mut ViewContext<ParentViewState>,
+ cx: &mut WindowContext,
) {
- self.view.update(cx, |view, cx| element.paint(view, cx))
+ element.paint(cx)
}
}
@@ -357,7 +349,7 @@ mod any_view {
let view = view.clone().downcast::<V>().unwrap();
view.update(cx, |view, cx| {
let mut element = AnyElement::new(view.render(cx));
- let layout_id = element.layout(view, cx);
+ let layout_id = element.layout(cx);
(layout_id, Box::new(element) as Box<dyn Any>)
})
})
@@ -369,9 +361,8 @@ mod any_view {
cx: &mut WindowContext,
) {
cx.with_element_id(Some(view.model.entity_id), |cx| {
- let view = view.clone().downcast::<V>().unwrap();
- let element = element.downcast_mut::<AnyElement<V>>().unwrap();
- view.update(cx, |view, cx| element.paint(view, cx))
+ let element = element.downcast_mut::<AnyElement>().unwrap();
+ element.paint(cx);
})
}
}
@@ -1,15 +1,15 @@
use crate::{
key_dispatch::DispatchActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext,
- AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
- DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId,
- EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla,
- ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model,
- ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent,
- MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler,
- PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,
- RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size,
- Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View,
- VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
+ AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, CallbackHandle, ConstructorHandle,
+ Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges,
+ Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId,
+ GlobalElementId, GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyBinding, KeyContext,
+ KeyDownEvent, LayoutId, Model, ModelContext, Modifiers, MonochromeSprite, MouseButton,
+ MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay,
+ PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render,
+ RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow,
+ SharedString, Size, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline,
+ UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
};
use anyhow::{anyhow, Context as _, Result};
use collections::HashMap;
@@ -1436,6 +1436,47 @@ impl<'a> WindowContext<'a> {
.dispatch_tree
.bindings_for_action(action)
}
+
+ ///========== ELEMENT RELATED FUNCTIONS ===========
+ pub fn with_key_dispatch<R>(
+ &mut self,
+ context: KeyContext,
+ focus_handle: Option<FocusHandle>,
+ f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
+ ) -> R {
+ let window = &mut self.window;
+ window
+ .current_frame
+ .dispatch_tree
+ .push_node(context.clone());
+ if let Some(focus_handle) = focus_handle.as_ref() {
+ window
+ .current_frame
+ .dispatch_tree
+ .make_focusable(focus_handle.id);
+ }
+ let result = f(focus_handle, self);
+
+ self.window.current_frame.dispatch_tree.pop_node();
+
+ result
+ }
+
+ /// Register a focus listener for the current frame only. It will be cleared
+ /// on the next frame render. You should use this method only from within elements,
+ /// and we may want to enforce that better via a different context type.
+ // todo!() Move this to `FrameContext` to emphasize its individuality?
+ pub fn on_focus_changed(
+ &mut self,
+ listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static,
+ ) {
+ self.window
+ .current_frame
+ .focus_listeners
+ .push(Box::new(move |event, cx| {
+ listener(event, cx);
+ }));
+ }
}
impl Context for WindowContext<'_> {
@@ -2124,49 +2165,6 @@ impl<'a, V: 'static> ViewContext<'a, V> {
)
}
- /// Register a focus listener for the current frame only. It will be cleared
- /// on the next frame render. You should use this method only from within elements,
- /// and we may want to enforce that better via a different context type.
- // todo!() Move this to `FrameContext` to emphasize its individuality?
- pub fn on_focus_changed(
- &mut self,
- listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
- ) {
- let handle = self.view().downgrade();
- self.window
- .current_frame
- .focus_listeners
- .push(Box::new(move |event, cx| {
- handle
- .update(cx, |view, cx| listener(view, event, cx))
- .log_err();
- }));
- }
-
- pub fn with_key_dispatch<R>(
- &mut self,
- context: KeyContext,
- focus_handle: Option<FocusHandle>,
- f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
- ) -> R {
- let window = &mut self.window;
- window
- .current_frame
- .dispatch_tree
- .push_node(context.clone());
- if let Some(focus_handle) = focus_handle.as_ref() {
- window
- .current_frame
- .dispatch_tree
- .make_focusable(focus_handle.id);
- }
- let result = f(focus_handle, self);
-
- self.window.current_frame.dispatch_tree.pop_node();
-
- result
- }
-
pub fn spawn<Fut, R>(
&mut self,
f: impl FnOnce(WeakView<V>, AsyncWindowContext) -> Fut,
@@ -2284,6 +2282,25 @@ impl<'a, V: 'static> ViewContext<'a, V> {
{
self.defer(|_, cx| cx.emit(Manager::Dismiss))
}
+
+ pub fn callback<E>(
+ &self,
+ f: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
+ ) -> CallbackHandle<E> {
+ let view = self.view().clone();
+ (move |e: &E, cx: &mut WindowContext| {
+ view.update(cx, |view, cx| f(view, e, cx));
+ })
+ .into()
+ }
+
+ pub fn constructor<R>(
+ &self,
+ f: impl Fn(&mut V, &mut ViewContext<V>) -> R + 'static,
+ ) -> ConstructorHandle<R> {
+ let view = self.view().clone();
+ (move |cx: &mut WindowContext| view.update(cx, |view, cx| f(view, cx))).into()
+ }
}
impl<V> Context for ViewContext<'_, V> {