Add on_drop listeners
This commit is contained in:
parent
38a7b39070
commit
ec0b2e5430
6 changed files with 112 additions and 70 deletions
|
@ -354,7 +354,7 @@ where
|
||||||
F: ElementFocus<V>,
|
F: ElementFocus<V>,
|
||||||
V: 'static + Send + Sync,
|
V: 'static + Send + Sync,
|
||||||
{
|
{
|
||||||
fn stateless_interactivity(&mut self) -> &mut StatelessInteraction<V> {
|
fn stateless_interaction(&mut self) -> &mut StatelessInteraction<V> {
|
||||||
self.interaction.as_stateless_mut()
|
self.interaction.as_stateless_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,8 +156,8 @@ where
|
||||||
I: ElementInteraction<V>,
|
I: ElementInteraction<V>,
|
||||||
F: ElementFocus<V>,
|
F: ElementFocus<V>,
|
||||||
{
|
{
|
||||||
fn stateless_interactivity(&mut self) -> &mut StatelessInteraction<V> {
|
fn stateless_interaction(&mut self) -> &mut StatelessInteraction<V> {
|
||||||
self.base.stateless_interactivity()
|
self.base.stateless_interaction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,8 +130,8 @@ where
|
||||||
I: ElementInteraction<V>,
|
I: ElementInteraction<V>,
|
||||||
F: ElementFocus<V>,
|
F: ElementFocus<V>,
|
||||||
{
|
{
|
||||||
fn stateless_interactivity(&mut self) -> &mut StatelessInteraction<V> {
|
fn stateless_interaction(&mut self) -> &mut StatelessInteraction<V> {
|
||||||
self.base.stateless_interactivity()
|
self.base.stateless_interaction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, view, Action, AnyDrag, AppContext, BorrowWindow, Bounds, DispatchContext,
|
point, px, view, Action, AnyBox, AnyDrag, AppContext, BorrowWindow, Bounds, DispatchContext,
|
||||||
DispatchPhase, Element, ElementId, FocusHandle, KeyMatch, Keystroke, Modifiers, Overflow,
|
DispatchPhase, Element, ElementId, FocusHandle, KeyMatch, Keystroke, Modifiers, Overflow,
|
||||||
Pixels, Point, SharedString, Size, Style, StyleRefinement, ViewContext,
|
Pixels, Point, SharedString, Size, Style, StyleRefinement, ViewContext,
|
||||||
};
|
};
|
||||||
|
@ -19,13 +19,13 @@ use std::{
|
||||||
const DRAG_THRESHOLD: f64 = 2.;
|
const DRAG_THRESHOLD: f64 = 2.;
|
||||||
|
|
||||||
pub trait StatelessInteractive: Element {
|
pub trait StatelessInteractive: Element {
|
||||||
fn stateless_interactivity(&mut self) -> &mut StatelessInteraction<Self::ViewState>;
|
fn stateless_interaction(&mut self) -> &mut StatelessInteraction<Self::ViewState>;
|
||||||
|
|
||||||
fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity().hover_style = f(StyleRefinement::default());
|
self.stateless_interaction().hover_style = f(StyleRefinement::default());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity().group_hover_style = Some(GroupStyle {
|
self.stateless_interaction().group_hover_style = Some(GroupStyle {
|
||||||
group: group_name.into(),
|
group: group_name.into(),
|
||||||
style: f(StyleRefinement::default()),
|
style: f(StyleRefinement::default()),
|
||||||
});
|
});
|
||||||
|
@ -55,7 +55,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity()
|
self.stateless_interaction()
|
||||||
.mouse_down_listeners
|
.mouse_down_listeners
|
||||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||||
if phase == DispatchPhase::Bubble
|
if phase == DispatchPhase::Bubble
|
||||||
|
@ -79,7 +79,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity()
|
self.stateless_interaction()
|
||||||
.mouse_up_listeners
|
.mouse_up_listeners
|
||||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||||
if phase == DispatchPhase::Bubble
|
if phase == DispatchPhase::Bubble
|
||||||
|
@ -103,7 +103,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity()
|
self.stateless_interaction()
|
||||||
.mouse_down_listeners
|
.mouse_down_listeners
|
||||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||||
if phase == DispatchPhase::Capture
|
if phase == DispatchPhase::Capture
|
||||||
|
@ -127,7 +127,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity()
|
self.stateless_interaction()
|
||||||
.mouse_up_listeners
|
.mouse_up_listeners
|
||||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||||
if phase == DispatchPhase::Capture
|
if phase == DispatchPhase::Capture
|
||||||
|
@ -150,7 +150,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity()
|
self.stateless_interaction()
|
||||||
.mouse_move_listeners
|
.mouse_move_listeners
|
||||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
||||||
|
@ -170,7 +170,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity()
|
self.stateless_interaction()
|
||||||
.scroll_wheel_listeners
|
.scroll_wheel_listeners
|
||||||
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
.push(Arc::new(move |view, event, bounds, phase, cx| {
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
||||||
|
@ -186,7 +186,7 @@ pub trait StatelessInteractive: Element {
|
||||||
C: TryInto<DispatchContext>,
|
C: TryInto<DispatchContext>,
|
||||||
C::Error: Debug,
|
C::Error: Debug,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity().dispatch_context =
|
self.stateless_interaction().dispatch_context =
|
||||||
context.try_into().expect("invalid dispatch context");
|
context.try_into().expect("invalid dispatch context");
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity().key_listeners.push((
|
self.stateless_interaction().key_listeners.push((
|
||||||
TypeId::of::<A>(),
|
TypeId::of::<A>(),
|
||||||
Arc::new(move |view, event, _, phase, cx| {
|
Arc::new(move |view, event, _, phase, cx| {
|
||||||
let event = event.downcast_ref().unwrap();
|
let event = event.downcast_ref().unwrap();
|
||||||
|
@ -226,7 +226,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity().key_listeners.push((
|
self.stateless_interaction().key_listeners.push((
|
||||||
TypeId::of::<KeyDownEvent>(),
|
TypeId::of::<KeyDownEvent>(),
|
||||||
Arc::new(move |view, event, _, phase, cx| {
|
Arc::new(move |view, event, _, phase, cx| {
|
||||||
let event = event.downcast_ref().unwrap();
|
let event = event.downcast_ref().unwrap();
|
||||||
|
@ -247,7 +247,7 @@ pub trait StatelessInteractive: Element {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.stateless_interactivity().key_listeners.push((
|
self.stateless_interaction().key_listeners.push((
|
||||||
TypeId::of::<KeyUpEvent>(),
|
TypeId::of::<KeyUpEvent>(),
|
||||||
Arc::new(move |view, event, _, phase, cx| {
|
Arc::new(move |view, event, _, phase, cx| {
|
||||||
let event = event.downcast_ref().unwrap();
|
let event = event.downcast_ref().unwrap();
|
||||||
|
@ -257,6 +257,53 @@ pub trait StatelessInteractive: Element {
|
||||||
));
|
));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn drag_over<S: 'static>(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.stateless_interaction()
|
||||||
|
.drag_over_styles
|
||||||
|
.push((TypeId::of::<S>(), f(StyleRefinement::default())));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group_drag_over<S: 'static>(
|
||||||
|
mut self,
|
||||||
|
group_name: impl Into<SharedString>,
|
||||||
|
f: impl FnOnce(StyleRefinement) -> StyleRefinement,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.stateless_interaction().group_drag_over_styles.push((
|
||||||
|
TypeId::of::<S>(),
|
||||||
|
GroupStyle {
|
||||||
|
group: group_name.into(),
|
||||||
|
style: f(StyleRefinement::default()),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_drop<S: 'static>(
|
||||||
|
mut self,
|
||||||
|
listener: impl Fn(&mut Self::ViewState, S, &mut ViewContext<Self::ViewState>)
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.stateless_interaction().drop_listeners.push((
|
||||||
|
TypeId::of::<S>(),
|
||||||
|
Arc::new(move |view, drag_state, cx| {
|
||||||
|
listener(view, *drag_state.downcast().unwrap(), cx);
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait StatefulInteractive: StatelessInteractive {
|
pub trait StatefulInteractive: StatelessInteractive {
|
||||||
|
@ -338,34 +385,6 @@ pub trait StatefulInteractive: StatelessInteractive {
|
||||||
}));
|
}));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drag_over<S: 'static>(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateful_interaction()
|
|
||||||
.drag_over_styles
|
|
||||||
.push((TypeId::of::<S>(), f(StyleRefinement::default())));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn group_drag_over<S: 'static>(
|
|
||||||
mut self,
|
|
||||||
group_name: impl Into<SharedString>,
|
|
||||||
f: impl FnOnce(StyleRefinement) -> StyleRefinement,
|
|
||||||
) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.stateful_interaction().group_drag_over_styles.push((
|
|
||||||
TypeId::of::<S>(),
|
|
||||||
GroupStyle {
|
|
||||||
group: group_name.into(),
|
|
||||||
style: f(StyleRefinement::default()),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
|
@ -523,6 +542,29 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cx.active_drag.is_some() {
|
||||||
|
let drop_listeners = stateless.drop_listeners.clone();
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
for (drop_state_type, listener) in &drop_listeners {
|
||||||
|
if *drop_state_type == drag_state_type {
|
||||||
|
let drag = cx
|
||||||
|
.active_drag
|
||||||
|
.take()
|
||||||
|
.expect("checked for type drag state type above");
|
||||||
|
listener(view, drag.state, cx);
|
||||||
|
cx.notify();
|
||||||
|
cx.stop_propagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(stateful) = self.as_stateful() {
|
if let Some(stateful) = self.as_stateful() {
|
||||||
let click_listeners = stateful.click_listeners.clone();
|
let click_listeners = stateful.click_listeners.clone();
|
||||||
let drag_listener = stateful.drag_listener.clone();
|
let drag_listener = stateful.drag_listener.clone();
|
||||||
|
@ -544,10 +586,11 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
&& (event.position - mouse_down.position).magnitude()
|
&& (event.position - mouse_down.position).magnitude()
|
||||||
> DRAG_THRESHOLD
|
> DRAG_THRESHOLD
|
||||||
{
|
{
|
||||||
let cursor_offset = event.position - bounds.origin;
|
|
||||||
let any_drag = drag_listener(view_state, cursor_offset, cx);
|
|
||||||
*active_state.lock() = ActiveState::default();
|
*active_state.lock() = ActiveState::default();
|
||||||
cx.start_drag(any_drag);
|
let cursor_offset = event.position - bounds.origin;
|
||||||
|
let drag = drag_listener(view_state, cursor_offset, cx);
|
||||||
|
cx.active_drag = Some(drag);
|
||||||
|
cx.notify();
|
||||||
cx.stop_propagation();
|
cx.stop_propagation();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -564,10 +607,6 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
listener(view_state, &mouse_click, cx);
|
listener(view_state, &mouse_click, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cx.active_drag.is_some() {
|
|
||||||
cx.end_drag();
|
|
||||||
}
|
|
||||||
*pending_mouse_down.lock() = None;
|
*pending_mouse_down.lock() = None;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -690,6 +729,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DropListener<V> = dyn Fn(&mut V, AnyBox, &mut ViewContext<V>) + Send + Sync;
|
||||||
|
|
||||||
pub struct StatelessInteraction<V> {
|
pub struct StatelessInteraction<V> {
|
||||||
pub dispatch_context: DispatchContext,
|
pub dispatch_context: DispatchContext,
|
||||||
pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
|
pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
|
||||||
|
@ -701,6 +742,7 @@ pub struct StatelessInteraction<V> {
|
||||||
pub group_hover_style: Option<GroupStyle>,
|
pub group_hover_style: Option<GroupStyle>,
|
||||||
drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
|
drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
|
||||||
group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
|
group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
|
||||||
|
drop_listeners: SmallVec<[(TypeId, Arc<DropListener<V>>); 2]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> StatelessInteraction<V>
|
impl<V> StatelessInteraction<V>
|
||||||
|
@ -793,6 +835,7 @@ impl<V> Default for StatelessInteraction<V> {
|
||||||
group_hover_style: None,
|
group_hover_style: None,
|
||||||
drag_over_styles: SmallVec::new(),
|
drag_over_styles: SmallVec::new(),
|
||||||
group_drag_over_styles: SmallVec::new(),
|
group_drag_over_styles: SmallVec::new(),
|
||||||
|
drop_listeners: SmallVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ use crate::{
|
||||||
BorrowAppContext, Bounds, BoxShadow, Context, Corners, DevicePixels, DispatchContext,
|
BorrowAppContext, Bounds, BoxShadow, Context, Corners, DevicePixels, DispatchContext,
|
||||||
DisplayId, Edges, Effect, Element, EntityId, EventEmitter, FocusEvent, FontId, GlobalElementId,
|
DisplayId, Edges, Effect, Element, EntityId, EventEmitter, FocusEvent, FontId, GlobalElementId,
|
||||||
GlyphId, Handle, Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher,
|
GlyphId, Handle, Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher,
|
||||||
Keystroke, LayoutId, MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent, Path,
|
Keystroke, LayoutId, MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent,
|
||||||
Pixels, Platform, PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad, Reference,
|
MouseUpEvent, Path, Pixels, Platform, PlatformAtlas, PlatformWindow, Point, PolychromeSprite,
|
||||||
RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow,
|
Quad, Reference, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels,
|
||||||
SharedString, Size, Style, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle,
|
SceneBuilder, Shadow, SharedString, Size, Style, Subscription, TaffyLayoutEngine, Task,
|
||||||
WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
|
Underline, UnderlineStyle, WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
|
@ -925,6 +925,12 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.app.propagate_event
|
||||||
|
&& any_mouse_event.downcast_ref::<MouseUpEvent>().is_some()
|
||||||
|
{
|
||||||
|
self.active_drag = None;
|
||||||
|
}
|
||||||
|
|
||||||
// Just in case any handlers added new handlers, which is weird, but possible.
|
// Just in case any handlers added new handlers, which is weird, but possible.
|
||||||
handlers.extend(
|
handlers.extend(
|
||||||
self.window
|
self.window
|
||||||
|
@ -1626,16 +1632,6 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn start_drag(&mut self, drag: AnyDrag) {
|
|
||||||
self.app.active_drag = Some(drag);
|
|
||||||
self.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn end_drag(&mut self) {
|
|
||||||
self.app.active_drag = None;
|
|
||||||
self.notify();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'w, V: EventEmitter + Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
impl<'a, 'w, V: EventEmitter + Send + Sync + 'static> ViewContext<'a, 'w, V> {
|
||||||
|
|
|
@ -17,7 +17,7 @@ pub struct Tab<S: 'static + Send + Sync + Clone> {
|
||||||
close_side: IconSide,
|
close_side: IconSide,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
struct TabDragState {
|
struct TabDragState {
|
||||||
title: String,
|
title: String,
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,9 @@ impl<S: 'static + Send + Sync + Clone> Tab<S> {
|
||||||
Drag::new(drag_state.clone(), |view, cx| div().w_8().h_4().bg(red()))
|
Drag::new(drag_state.clone(), |view, cx| div().w_8().h_4().bg(red()))
|
||||||
})
|
})
|
||||||
.drag_over::<TabDragState>(|d| d.bg(black()))
|
.drag_over::<TabDragState>(|d| d.bg(black()))
|
||||||
|
.on_drop(|_view, state: TabDragState, cx| {
|
||||||
|
dbg!(state);
|
||||||
|
})
|
||||||
.px_2()
|
.px_2()
|
||||||
.py_0p5()
|
.py_0p5()
|
||||||
.flex()
|
.flex()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue