Clear active state when drag starts
This commit is contained in:
parent
258fcaea94
commit
239b0c2f71
2 changed files with 79 additions and 22 deletions
|
@ -336,6 +336,34 @@ 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 {
|
||||||
|
@ -398,6 +426,26 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
style.refine(&stateless.hover_style);
|
style.refine(&stateless.hover_style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
&& group_bounds.contains_point(&mouse_position)
|
||||||
|
{
|
||||||
|
style.refine(&group_drag_style.style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (state_type, drag_over_style) in &self.as_stateless().drag_over_styles {
|
||||||
|
if *state_type == drag.state_type && bounds.contains_point(&mouse_position) {
|
||||||
|
style.refine(drag_over_style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cx.active_drag = Some(drag);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(stateful) = self.as_stateful() {
|
if let Some(stateful) = self.as_stateful() {
|
||||||
let active_state = element_state.active_state.lock();
|
let active_state = element_state.active_state.lock();
|
||||||
if active_state.group {
|
if active_state.group {
|
||||||
|
@ -450,11 +498,27 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
.and_then(|group_hover| GroupBounds::get(&group_hover.group, cx));
|
.and_then(|group_hover| GroupBounds::get(&group_hover.group, cx));
|
||||||
|
|
||||||
if let Some(group_bounds) = hover_group_bounds {
|
if let Some(group_bounds) = hover_group_bounds {
|
||||||
paint_hover_listener(group_bounds, cx);
|
let hovered = group_bounds.contains_point(&cx.mouse_position());
|
||||||
|
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
||||||
|
if phase == DispatchPhase::Capture {
|
||||||
|
if group_bounds.contains_point(&event.position) != hovered {
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if stateless.hover_style.is_some() {
|
if stateless.hover_style.is_some()
|
||||||
paint_hover_listener(bounds, cx);
|
|| (cx.active_drag.is_some() && !stateless.drag_over_styles.is_empty())
|
||||||
|
{
|
||||||
|
let hovered = bounds.contains_point(&cx.mouse_position());
|
||||||
|
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
||||||
|
if phase == DispatchPhase::Capture {
|
||||||
|
if bounds.contains_point(&event.position) != hovered {
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(stateful) = self.as_stateful() {
|
if let Some(stateful) = self.as_stateful() {
|
||||||
|
@ -466,6 +530,7 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
let mouse_down = pending_mouse_down.lock().clone();
|
let mouse_down = pending_mouse_down.lock().clone();
|
||||||
if let Some(mouse_down) = mouse_down {
|
if let Some(mouse_down) = mouse_down {
|
||||||
if let Some(drag_listener) = drag_listener {
|
if let Some(drag_listener) = drag_listener {
|
||||||
|
let active_state = element_state.active_state.clone();
|
||||||
cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| {
|
cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| {
|
||||||
if cx.active_drag.is_some() {
|
if cx.active_drag.is_some() {
|
||||||
if phase == DispatchPhase::Capture {
|
if phase == DispatchPhase::Capture {
|
||||||
|
@ -476,6 +541,7 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
{
|
{
|
||||||
let cursor_offset = event.position - bounds.origin;
|
let cursor_offset = event.position - bounds.origin;
|
||||||
let any_drag = drag_listener(view_state, cursor_offset, cx);
|
let any_drag = drag_listener(view_state, cursor_offset, cx);
|
||||||
|
*active_state.lock() = ActiveState::default();
|
||||||
cx.start_drag(any_drag);
|
cx.start_drag(any_drag);
|
||||||
cx.stop_propagation();
|
cx.stop_propagation();
|
||||||
}
|
}
|
||||||
|
@ -570,30 +636,16 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_hover_listener<V>(bounds: Bounds<Pixels>, cx: &mut ViewContext<V>)
|
|
||||||
where
|
|
||||||
V: 'static + Send + Sync,
|
|
||||||
{
|
|
||||||
let hovered = bounds.contains_point(&cx.mouse_position());
|
|
||||||
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
|
||||||
if phase == DispatchPhase::Capture {
|
|
||||||
if bounds.contains_point(&event.position) != hovered {
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deref, DerefMut)]
|
#[derive(Deref, DerefMut)]
|
||||||
pub struct StatefulInteraction<V: 'static + Send + Sync> {
|
pub struct StatefulInteraction<V: 'static + Send + Sync> {
|
||||||
pub id: ElementId,
|
pub id: ElementId,
|
||||||
#[deref]
|
#[deref]
|
||||||
#[deref_mut]
|
#[deref_mut]
|
||||||
stateless: StatelessInteraction<V>,
|
stateless: StatelessInteraction<V>,
|
||||||
pub click_listeners: SmallVec<[ClickListener<V>; 2]>,
|
click_listeners: SmallVec<[ClickListener<V>; 2]>,
|
||||||
pub(crate) drag_listener: Option<DragListener<V>>,
|
active_style: StyleRefinement,
|
||||||
pub active_style: StyleRefinement,
|
group_active_style: Option<GroupStyle>,
|
||||||
pub group_active_style: Option<GroupStyle>,
|
drag_listener: Option<DragListener<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> ElementInteraction<V> for StatefulInteraction<V>
|
impl<V> ElementInteraction<V> for StatefulInteraction<V>
|
||||||
|
@ -642,6 +694,8 @@ pub struct StatelessInteraction<V> {
|
||||||
pub key_listeners: SmallVec<[(TypeId, KeyListener<V>); 32]>,
|
pub key_listeners: SmallVec<[(TypeId, KeyListener<V>); 32]>,
|
||||||
pub hover_style: StyleRefinement,
|
pub hover_style: StyleRefinement,
|
||||||
pub group_hover_style: Option<GroupStyle>,
|
pub group_hover_style: Option<GroupStyle>,
|
||||||
|
drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
|
||||||
|
group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> StatelessInteraction<V>
|
impl<V> StatelessInteraction<V>
|
||||||
|
@ -732,6 +786,8 @@ impl<V> Default for StatelessInteraction<V> {
|
||||||
key_listeners: SmallVec::new(),
|
key_listeners: SmallVec::new(),
|
||||||
hover_style: StyleRefinement::default(),
|
hover_style: StyleRefinement::default(),
|
||||||
group_hover_style: None,
|
group_hover_style: None,
|
||||||
|
drag_over_styles: SmallVec::new(),
|
||||||
|
group_drag_over_styles: SmallVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,7 @@ impl<S: 'static + Send + Sync + Clone> Tab<S> {
|
||||||
.on_drag(move |_view, _cx| {
|
.on_drag(move |_view, _cx| {
|
||||||
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()))
|
||||||
.px_2()
|
.px_2()
|
||||||
.py_0p5()
|
.py_0p5()
|
||||||
.flex()
|
.flex()
|
||||||
|
@ -160,7 +161,7 @@ impl<S: 'static + Send + Sync + Clone> Tab<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use gpui2::{red, Drag, ElementId};
|
use gpui2::{black, red, Drag, ElementId};
|
||||||
#[cfg(feature = "stories")]
|
#[cfg(feature = "stories")]
|
||||||
pub use stories::*;
|
pub use stories::*;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue