Add new drag API

This commit is contained in:
Mikayla
2023-12-13 13:40:19 -08:00
parent bfbbec0b01
commit a807e798ec
8 changed files with 119 additions and 96 deletions
+4
View File
@@ -1138,6 +1138,10 @@ impl AppContext {
pub fn has_active_drag(&self) -> bool {
self.active_drag.is_some()
}
pub fn active_drag(&self) -> Option<AnyView> {
self.active_drag.as_ref().map(|drag| drag.view.clone())
}
}
impl Context for AppContext {
+23 -40
View File
@@ -482,48 +482,31 @@ impl IntoElement for AnyElement {
}
}
// impl<V, E, F> Element for Option<F>
// where
// V: 'static,
// E: Element,
// F: FnOnce(&mut V, &mut WindowContext<'_, V>) -> E + 'static,
// {
// type State = Option<AnyElement>;
/// The empty element, which renders nothing.
pub type Empty = ();
// fn element_id(&self) -> Option<ElementId> {
// None
// }
impl IntoElement for () {
type Element = Self;
// fn layout(
// &mut self,
// _: Option<Self::State>,
// cx: &mut WindowContext,
// ) -> (LayoutId, Self::State) {
// let render = self.take().unwrap();
// let mut element = (render)(view_state, cx).into_any();
// let layout_id = element.layout(view_state, cx);
// (layout_id, Some(element))
// }
fn element_id(&self) -> Option<ElementId> {
None
}
// fn paint(
// self,
// _bounds: Bounds<Pixels>,
// rendered_element: &mut Self::State,
// cx: &mut WindowContext,
// ) {
// rendered_element.take().unwrap().paint(view_state, cx);
// }
// }
fn into_element(self) -> Self::Element {
self
}
}
// impl<V, E, F> RenderOnce for Option<F>
// where
// V: 'static,
// E: Element,
// F: FnOnce(&mut V, &mut WindowContext) -> E + 'static,
// {
// type Element = Self;
impl Element for () {
type State = ();
// fn render(self) -> Self::Element {
// self
// }
// }
fn layout(
&mut self,
_state: Option<Self::State>,
cx: &mut WindowContext,
) -> (LayoutId, Self::State) {
(cx.request_layout(&crate::Style::default(), None), ())
}
fn paint(self, _bounds: Bounds<Pixels>, _state: &mut Self::State, _cx: &mut WindowContext) {}
}
+3 -3
View File
@@ -2,7 +2,7 @@ use refineable::Refineable as _;
use crate::{Bounds, Element, IntoElement, Pixels, Style, StyleRefinement, Styled, WindowContext};
pub fn canvas(callback: impl 'static + FnOnce(Bounds<Pixels>, &mut WindowContext)) -> Canvas {
pub fn canvas(callback: impl 'static + FnOnce(&Bounds<Pixels>, &mut WindowContext)) -> Canvas {
Canvas {
paint_callback: Box::new(callback),
style: StyleRefinement::default(),
@@ -10,7 +10,7 @@ pub fn canvas(callback: impl 'static + FnOnce(Bounds<Pixels>, &mut WindowContext
}
pub struct Canvas {
paint_callback: Box<dyn FnOnce(Bounds<Pixels>, &mut WindowContext)>,
paint_callback: Box<dyn FnOnce(&Bounds<Pixels>, &mut WindowContext)>,
style: StyleRefinement,
}
@@ -41,7 +41,7 @@ impl Element for Canvas {
}
fn paint(self, bounds: Bounds<Pixels>, _: &mut (), cx: &mut WindowContext) {
(self.paint_callback)(bounds, cx)
(self.paint_callback)(&bounds, cx)
}
}
+35 -2
View File
@@ -29,6 +29,11 @@ pub struct GroupStyle {
pub style: Box<StyleRefinement>,
}
pub struct DragMoveEvent<W: Render> {
pub event: MouseMoveEvent,
pub drag: View<W>,
}
pub trait InteractiveElement: Sized {
fn interactivity(&mut self) -> &mut Interactivity;
@@ -192,6 +197,34 @@ pub trait InteractiveElement: Sized {
self
}
fn on_drag_move<W>(
mut self,
listener: impl Fn(&DragMoveEvent<W>, &mut WindowContext) + 'static,
) -> Self
where
W: Render,
{
self.interactivity().mouse_move_listeners.push(Box::new(
move |event, bounds, phase, cx| {
if phase == DispatchPhase::Capture
&& bounds.drag_target_contains(&event.position, cx)
{
if let Some(view) = cx.active_drag().and_then(|view| view.downcast::<W>().ok())
{
(listener)(
&DragMoveEvent {
event: event.clone(),
drag: view,
},
cx,
);
}
}
},
));
self
}
fn on_scroll_wheel(
mut self,
listener: impl Fn(&ScrollWheelEvent, &mut WindowContext) + 'static,
@@ -403,7 +436,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
self
}
fn on_drag<W>(mut self, listener: impl Fn(&mut WindowContext) -> View<W> + 'static) -> Self
fn on_drag<W>(mut self, constructor: impl Fn(&mut WindowContext) -> View<W> + 'static) -> Self
where
Self: Sized,
W: 'static + Render,
@@ -413,7 +446,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
"calling on_drag more than once on the same element is not supported"
);
self.interactivity().drag_listener = Some(Box::new(move |cursor_offset, cx| AnyDrag {
view: listener(cx).into(),
view: constructor(cx).into(),
cursor_offset,
}));
self