use std::fmt::{self, Debug};
use std::time::Duration;
use inset_embedder::{Offset, PointerDeviceKind};
use inset_foundation::ValueChanged;
use crate::gesture_details::PositionedGestureDetails;
use crate::velocity::Velocity;
#[derive(Clone)]
pub struct DragDownDetails {
pub global_position: Offset,
pub local_position: Offset,
}
impl DragDownDetails {
pub fn new(global_position: Offset, local_position: Option<Offset>) -> DragDownDetails {
DragDownDetails {
global_position,
local_position: local_position.unwrap_or(global_position),
}
}
}
impl Default for DragDownDetails {
fn default() -> DragDownDetails {
DragDownDetails::new(Offset::ZERO, None)
}
}
impl PositionedGestureDetails for DragDownDetails {
fn global_position(&self) -> Offset {
self.global_position
}
fn local_position(&self) -> Offset {
self.local_position
}
}
impl Debug for DragDownDetails {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DragDownDetails")
.field("globalPosition", &self.global_position)
.field("localPosition", &self.local_position)
.finish()
}
}
pub type GestureDragDownCallback = ValueChanged<DragDownDetails>;
#[derive(Clone)]
pub struct DragStartDetails {
pub global_position: Offset,
pub local_position: Offset,
pub source_time_stamp: Option<Duration>,
pub kind: Option<PointerDeviceKind>,
}
impl DragStartDetails {
pub fn new(
global_position: Offset,
local_position: Option<Offset>,
source_time_stamp: Option<Duration>,
kind: Option<PointerDeviceKind>,
) -> DragStartDetails {
DragStartDetails {
global_position,
local_position: local_position.unwrap_or(global_position),
source_time_stamp,
kind,
}
}
}
impl Default for DragStartDetails {
fn default() -> DragStartDetails {
DragStartDetails::new(Offset::ZERO, None, None, None)
}
}
impl PositionedGestureDetails for DragStartDetails {
fn global_position(&self) -> Offset {
self.global_position
}
fn local_position(&self) -> Offset {
self.local_position
}
}
impl Debug for DragStartDetails {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DragStartDetails")
.field("globalPosition", &self.global_position)
.field("localPosition", &self.local_position)
.field("sourceTimeStamp", &self.source_time_stamp)
.field("kind", &self.kind)
.finish()
}
}
pub type GestureDragStartCallback = ValueChanged<DragStartDetails>;
#[derive(Clone)]
pub struct DragUpdateDetails {
pub global_position: Offset,
pub local_position: Offset,
pub source_time_stamp: Option<Duration>,
pub delta: Offset,
pub primary_delta: Option<f64>,
pub kind: Option<PointerDeviceKind>,
}
impl DragUpdateDetails {
pub fn new(
global_position: Offset,
local_position: Option<Offset>,
source_time_stamp: Option<Duration>,
delta: Offset,
primary_delta: Option<f64>,
kind: Option<PointerDeviceKind>,
) -> DragUpdateDetails {
debug_assert!(
primary_delta.is_none()
|| (primary_delta == Some(delta.dx()) && delta.dy() == 0.0)
|| (primary_delta == Some(delta.dy()) && delta.dx() == 0.0)
);
DragUpdateDetails {
global_position,
local_position: local_position.unwrap_or(global_position),
source_time_stamp,
delta,
primary_delta,
kind,
}
}
}
impl PositionedGestureDetails for DragUpdateDetails {
fn global_position(&self) -> Offset {
self.global_position
}
fn local_position(&self) -> Offset {
self.local_position
}
}
impl Debug for DragUpdateDetails {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DragUpdateDetails")
.field("globalPosition", &self.global_position)
.field("localPosition", &self.local_position)
.field("sourceTimeStamp", &self.source_time_stamp)
.field("delta", &self.delta)
.field("primaryDelta", &self.primary_delta)
.finish()
}
}
pub type GestureDragUpdateCallback = ValueChanged<DragUpdateDetails>;
#[derive(Clone)]
pub struct DragEndDetails {
pub global_position: Offset,
pub local_position: Offset,
pub velocity: Velocity,
pub primary_velocity: Option<f64>,
}
impl DragEndDetails {
pub fn new(
global_position: Offset,
local_position: Option<Offset>,
velocity: Velocity,
primary_velocity: Option<f64>,
) -> DragEndDetails {
debug_assert!(
primary_velocity.is_none()
|| (primary_velocity == Some(velocity.pixels_per_second.dx())
&& velocity.pixels_per_second.dy() == 0.0)
|| (primary_velocity == Some(velocity.pixels_per_second.dy())
&& velocity.pixels_per_second.dx() == 0.0)
);
DragEndDetails {
global_position,
local_position: local_position.unwrap_or(global_position),
velocity,
primary_velocity,
}
}
}
impl Default for DragEndDetails {
fn default() -> DragEndDetails {
DragEndDetails::new(Offset::ZERO, None, Velocity::ZERO, None)
}
}
impl PositionedGestureDetails for DragEndDetails {
fn global_position(&self) -> Offset {
self.global_position
}
fn local_position(&self) -> Offset {
self.local_position
}
}
impl Debug for DragEndDetails {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DragEndDetails")
.field("globalPosition", &self.global_position)
.field("localPosition", &self.local_position)
.field("velocity", &self.velocity)
.field("primaryVelocity", &self.primary_velocity)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn local_position_defaults_to_global() {
let down = DragDownDetails::new(Offset::new(3.0, 4.0), None);
assert_eq!(down.local_position, Offset::new(3.0, 4.0));
let start = DragStartDetails::new(Offset::new(1.0, 2.0), None, None, None);
assert_eq!(start.local_position, Offset::new(1.0, 2.0));
let update = DragUpdateDetails::new(
Offset::new(5.0, 6.0),
None,
None,
Offset::new(0.0, 1.0),
Some(1.0),
None,
);
assert_eq!(update.local_position, Offset::new(5.0, 6.0));
assert_eq!(update.primary_delta, Some(1.0));
let end = DragEndDetails::new(
Offset::new(7.0, 8.0),
None,
Velocity::new(Offset::new(0.0, 9.0)),
Some(9.0),
);
assert_eq!(end.local_position, Offset::new(7.0, 8.0));
assert_eq!(end.primary_velocity, Some(9.0));
}
}