Introduce a Render trait, make views implement it
Don't pass a render function separately from the view. Co-authored-by: Nathan Sobo <nathan@zed.dev> Co-authored-by: Mikayla <mikayla@zed.dev> Co-authored-by: Antonio <as-cii@zed.dev>
This commit is contained in:
parent
0128079de0
commit
30dffbb409
49 changed files with 616 additions and 612 deletions
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
point, px, Action, AnyBox, AnyDrag, AppContext, BorrowWindow, Bounds, Component,
|
||||
DispatchContext, DispatchPhase, Element, ElementId, FocusHandle, KeyMatch, Keystroke,
|
||||
Modifiers, Overflow, Pixels, Point, SharedString, Size, Style, StyleRefinement, View,
|
||||
div, point, px, Action, AnyDrag, AnyView, AppContext, BorrowWindow, Bounds, Component,
|
||||
DispatchContext, DispatchPhase, Div, Element, ElementId, FocusHandle, KeyMatch, Keystroke,
|
||||
Modifiers, Overflow, Pixels, Point, Render, SharedString, Size, Style, StyleRefinement, View,
|
||||
ViewContext,
|
||||
};
|
||||
use collections::HashMap;
|
||||
|
@ -258,17 +258,17 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
|
|||
self
|
||||
}
|
||||
|
||||
fn on_drop<S: 'static>(
|
||||
fn on_drop<W: 'static + Send>(
|
||||
mut self,
|
||||
listener: impl Fn(&mut V, S, &mut ViewContext<V>) + Send + 'static,
|
||||
listener: impl Fn(&mut V, View<W>, &mut ViewContext<V>) + Send + 'static,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.stateless_interaction().drop_listeners.push((
|
||||
TypeId::of::<S>(),
|
||||
Box::new(move |view, drag_state, cx| {
|
||||
listener(view, *drag_state.downcast().unwrap(), cx);
|
||||
TypeId::of::<W>(),
|
||||
Box::new(move |view, dragged_view, cx| {
|
||||
listener(view, dragged_view.downcast().unwrap(), cx);
|
||||
}),
|
||||
));
|
||||
self
|
||||
|
@ -314,43 +314,22 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
|
|||
self
|
||||
}
|
||||
|
||||
fn on_drag<S, R, E>(
|
||||
fn on_drag<W>(
|
||||
mut self,
|
||||
listener: impl Fn(&mut V, &mut ViewContext<V>) -> Drag<S, R, V, E> + Send + 'static,
|
||||
listener: impl Fn(&mut V, &mut ViewContext<V>) -> View<W> + Send + 'static,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
S: Any + Send,
|
||||
R: Fn(&mut V, &mut ViewContext<V>) -> E,
|
||||
R: 'static + Send,
|
||||
E: Component<V>,
|
||||
W: 'static + Send + Render,
|
||||
{
|
||||
debug_assert!(
|
||||
self.stateful_interaction().drag_listener.is_none(),
|
||||
"calling on_drag more than once on the same element is not supported"
|
||||
);
|
||||
self.stateful_interaction().drag_listener =
|
||||
Some(Box::new(move |view_state, cursor_offset, cx| {
|
||||
let drag = listener(view_state, cx);
|
||||
let drag_handle_view = Some(
|
||||
cx.build_view(|cx| DragView {
|
||||
model: cx.model().upgrade().unwrap(),
|
||||
drag,
|
||||
})
|
||||
.into_any(),
|
||||
);
|
||||
AnyDrag {
|
||||
render: {
|
||||
let view = cx.view();
|
||||
Box::new(move |cx| {
|
||||
view.update(cx, |view, cx| drag.render_drag_handle(view, cx))
|
||||
})
|
||||
},
|
||||
drag_handle_view,
|
||||
cursor_offset,
|
||||
state: Box::new(drag.state),
|
||||
state_type: TypeId::of::<S>(),
|
||||
}
|
||||
Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag {
|
||||
view: listener(view_state, cx).into_any(),
|
||||
cursor_offset,
|
||||
}));
|
||||
self
|
||||
}
|
||||
|
@ -419,7 +398,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
|
|||
if let Some(drag) = cx.active_drag.take() {
|
||||
for (state_type, group_drag_style) in &self.as_stateless().group_drag_over_styles {
|
||||
if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) {
|
||||
if *state_type == drag.state_type
|
||||
if *state_type == drag.view.entity_type()
|
||||
&& group_bounds.contains_point(&mouse_position)
|
||||
{
|
||||
style.refine(&group_drag_style.style);
|
||||
|
@ -428,7 +407,8 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
|
|||
}
|
||||
|
||||
for (state_type, drag_over_style) in &self.as_stateless().drag_over_styles {
|
||||
if *state_type == drag.state_type && bounds.contains_point(&mouse_position) {
|
||||
if *state_type == drag.view.entity_type() && bounds.contains_point(&mouse_position)
|
||||
{
|
||||
style.refine(drag_over_style);
|
||||
}
|
||||
}
|
||||
|
@ -516,7 +496,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
|
|||
cx.on_mouse_event(move |view, 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.state_type)
|
||||
cx.active_drag.as_ref().map(|drag| drag.view.entity_type())
|
||||
{
|
||||
for (drop_state_type, listener) in &drop_listeners {
|
||||
if *drop_state_type == drag_state_type {
|
||||
|
@ -524,7 +504,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
|
|||
.active_drag
|
||||
.take()
|
||||
.expect("checked for type drag state type above");
|
||||
listener(view, drag.state, cx);
|
||||
listener(view, drag.view.clone(), cx);
|
||||
cx.notify();
|
||||
cx.stop_propagation();
|
||||
}
|
||||
|
@ -692,7 +672,7 @@ impl<V> From<ElementId> for StatefulInteraction<V> {
|
|||
}
|
||||
}
|
||||
|
||||
type DropListener<V> = dyn Fn(&mut V, AnyBox, &mut ViewContext<V>) + 'static + Send;
|
||||
type DropListener<V> = dyn Fn(&mut V, AnyView, &mut ViewContext<V>) + 'static + Send;
|
||||
|
||||
pub struct StatelessInteraction<V> {
|
||||
pub dispatch_context: DispatchContext,
|
||||
|
@ -873,7 +853,7 @@ pub struct Drag<S, R, V, E>
|
|||
where
|
||||
R: Fn(&mut V, &mut ViewContext<V>) -> E,
|
||||
V: 'static,
|
||||
E: Component<V>,
|
||||
E: Component<()>,
|
||||
{
|
||||
pub state: S,
|
||||
pub render_drag_handle: R,
|
||||
|
@ -884,7 +864,7 @@ impl<S, R, V, E> Drag<S, R, V, E>
|
|||
where
|
||||
R: Fn(&mut V, &mut ViewContext<V>) -> E,
|
||||
V: 'static,
|
||||
E: Component<V>,
|
||||
E: Component<()>,
|
||||
{
|
||||
pub fn new(state: S, render_drag_handle: R) -> Self {
|
||||
Drag {
|
||||
|
@ -1006,6 +986,14 @@ impl Deref for MouseExitEvent {
|
|||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
|
||||
|
||||
impl Render for ExternalPaths {
|
||||
type Element = Div<Self>;
|
||||
|
||||
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
|
||||
div() // Intentionally left empty because the platform will render icons for the dragged files
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FileDropEvent {
|
||||
Entered {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue