Skip to main content

DragController

Struct DragController 

pub struct DragController<Id = ()> { /* private fields */ }
Expand description

A single-axis drag-to-reorder controller. Construct one per reorderable list (DragController::vertical / DragController::horizontal) and drive it from the owner’s event handler:

ⓘ
let grab = cursor.y - metrics.slot_lead(i);      // press on item i
ctrl.begin(item_id, i, grab, cursor);
if ctrl.pointer_moved(cursor, &metrics) { /* mark dirty */ }
for (i, item) in items { let dy = ctrl.item_shift(i, &metrics); }
if let Some(g) = ctrl.ghost_rect(list_x0, list_x1) { /* paint ghost */ }
if let Some((from, to)) = ctrl.commit() { model.move_item(from, to); }
ctrl.cancel(); // Escape / drop outside

Implementations§

§

impl<Id> DragController<Id>
where Id: Clone,

pub fn vertical() -> DragController<Id>

A vertical reorderable list (items stack top-to-bottom, ghost slides along Y).

pub fn horizontal() -> DragController<Id>

A horizontal reorderable list (items run left-to-right, ghost slides along X).

pub fn axis(&self) -> Axis

pub fn begin(&mut self, id: Id, from: usize, grab_offset: f64, start: Point)

Begin a (pending) drag of the item at index from, carrying id. grab_offset is the pointer’s offset within the grabbed item (cursor_axis - item_leading_edge). Not yet “active” — promotes to a live reorder only once the pointer clears the threshold.

pub fn pointer_moved(&mut self, cursor: Point, metrics: &ListMetrics) -> bool

Feed the latest pointer position. Promotes the drag to active once it clears the threshold. Returns true when the visible state changed (activation or a moved gap) so the owner can redraw only on an edge.

pub fn sync_insertion(&mut self, metrics: &ListMetrics)

Recompute the live target index from the freshest metrics without a pointer move — call once per frame in draw so the gap stays pinned to the ghost while the list scrolls under a held drag.

pub fn commit(&mut self) -> Option<(usize, usize)>

End the drag, yielding (from, to) to apply to the model, or None when the drag never became active or the item didn’t move. Clears the session either way. to is the final index after removal-and-reinsertion (Vec::remove(from) + insert(to, _)).

pub fn cancel(&mut self) -> bool

Abort the drag (Escape, or a drop outside the list). The model is only mutated on commit, so this simply forgets the session. Returns true if a drag was in progress.

pub fn is_pending(&self) -> bool

Whether a press has latched (active or not). Wire this to Widget::wants_pointer_capture so the drag keeps receiving events after the cursor leaves the item.

pub fn is_active(&self) -> bool

Whether the drag has crossed the threshold and is live (ghost + gap showing).

pub fn from_index(&self) -> Option<usize>

The original index of the item being dragged, once the drag is active.

pub fn insertion(&self) -> Option<usize>

The live target index the dragged item would land at, once active — the to a drop would commit. Paint the insertion caret at this slot so the caret and the reflowed gap coincide.

pub fn dragged_id(&self) -> Option<&Id>

The identity payload attached to the dragged item, once active.

pub fn item_shift(&self, index: usize, metrics: &ListMetrics) -> f64

How far the non-dragged item at original index index must slide (signed) to open a one-slot gap at the live target index. 0 for the dragged item, and 0 for every item during the dead-zone. Models “remove the dragged item, then open a gap where it will land”: an item collapses into the vacated slot, then shifts past the gap if the drop lands before it.

pub fn ghost_lead(&self) -> Option<f64>

The leading-edge coordinate of the floating ghost along the axis (cursor_axis - grab_offset), once active. Combine with the list’s cross-axis bounds via ghost_rect.

pub fn ghost_rect( &self, cross_lo: f64, cross_hi: f64, metrics: &ListMetrics, ) -> Option<Rect>

The floating ghost rect: one item-extent long along the axis, pinned to the list’s cross-axis span [cross_lo, cross_hi], positioned so the grab point stays under the cursor. None unless the drag is active.

pub fn ghost_rect_sized(&self, cross_lo: f64, size: Size) -> Option<Rect>

Convenience ghost rect from an explicit item size (for callers whose item cross-extent differs from the list metrics), anchored so the grab point tracks the cursor. None unless active.

Auto Trait Implementations§

§

impl<Id> Freeze for DragController<Id>
where Id: Freeze,

§

impl<Id> RefUnwindSafe for DragController<Id>
where Id: RefUnwindSafe,

§

impl<Id> Send for DragController<Id>
where Id: Send,

§

impl<Id> Sync for DragController<Id>
where Id: Sync,

§

impl<Id> Unpin for DragController<Id>
where Id: Unpin,

§

impl<Id> UnsafeUnpin for DragController<Id>
where Id: UnsafeUnpin,

§

impl<Id> UnwindSafe for DragController<Id>
where Id: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

§

fn simd_from(_simd: S, value: T) -> T

§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

§

fn simd_into(self, simd: S) -> T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,

§

impl<T> Fruit for T
where T: Send + Downcast,

§

impl<T> MaybeSendSync for T
where T: Send + Sync + ?Sized,

§

impl<T> WasmNotSend for T
where T: Send,

§

impl<T> WasmNotSendSync for T

§

impl<T> WasmNotSync for T
where T: Sync,