use dioxus::prelude::*;
use super::types::{DragMode, DropEffect, Point, ZoneId};
#[derive(Store, Debug, Clone, PartialEq)]
pub struct DragState<T: 'static> {
pub payload: Option<T>,
pub source: Option<ZoneId>,
pub over: Option<ZoneId>,
pub pointer: Point,
pub grab: Point,
pub effect: DropEffect,
pub mode: DragMode,
}
impl<T> Default for DragState<T> {
fn default() -> Self {
Self {
payload: None,
source: None,
over: None,
pointer: Point::default(),
grab: Point::default(),
effect: DropEffect::default(),
mode: DragMode::default(),
}
}
}
pub struct DndContext<T: Clone + 'static> {
state: Store<DragState<T>>,
announcement: Signal<String>,
}
impl<T: Clone + 'static> Copy for DndContext<T> {}
impl<T: Clone + 'static> Clone for DndContext<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: Clone + 'static> PartialEq for DndContext<T> {
fn eq(&self, other: &Self) -> bool {
self.announcement == other.announcement
}
}
impl<T: Clone + 'static> DndContext<T> {
pub fn from_parts(state: Store<DragState<T>>, announcement: Signal<String>) -> Self {
Self {
state,
announcement,
}
}
pub fn start(
&mut self,
payload: T,
source: Option<ZoneId>,
pointer: Point,
grab: Point,
effect: DropEffect,
mode: DragMode,
) {
self.state.set(DragState {
payload: Some(payload),
source,
over: None,
pointer,
grab,
effect,
mode,
});
}
pub fn update_pointer(&mut self, pointer: Point) {
if pointer.x == 0.0 && pointer.y == 0.0 {
return;
}
self.state.pointer().set(pointer);
}
pub fn enter(&mut self, zone: ZoneId) {
self.state.over().set(Some(zone));
}
pub fn leave(&mut self, zone: ZoneId) {
let mut over = self.state.over();
if *over.peek() == Some(zone) {
over.set(None);
}
}
pub fn take(&mut self) -> Option<(T, Option<ZoneId>)> {
let (payload, source) = {
let mut s = self.state.write();
(s.payload.take(), s.source)
};
let payload = payload?;
self.state.set(DragState::default());
Some((payload, source))
}
pub fn cancel(&mut self) {
self.state.set(DragState::default());
}
pub fn dragging(&self) -> bool {
self.state.payload().is_some()
}
pub fn payload(&self) -> Option<T> {
self.state.payload().cloned()
}
pub fn over(&self) -> Option<ZoneId> {
self.state.over().cloned()
}
pub fn source(&self) -> Option<ZoneId> {
self.state.source().cloned()
}
pub fn pointer(&self) -> Point {
self.state.pointer().cloned()
}
pub fn grab(&self) -> Point {
self.state.grab().cloned()
}
pub fn effect(&self) -> DropEffect {
self.state.effect().cloned()
}
pub fn mode(&self) -> DragMode {
self.state.mode().cloned()
}
pub fn announce(&mut self, msg: impl Into<String>) {
self.announcement.set(msg.into());
}
pub fn announcement(&self) -> String {
self.announcement.read().clone()
}
}