use dpi::PhysicalPosition;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ScrollDelta {
PageDelta(f32, f32),
LineDelta(f32, f32),
PixelDelta(PhysicalPosition<f64>),
}
impl ScrollDelta {
#[inline]
pub fn to_pixel_delta(
self,
line_px: PhysicalPosition<f64>,
page_px: PhysicalPosition<f64>,
) -> PhysicalPosition<f64> {
match self {
Self::PixelDelta(p) => p,
Self::LineDelta(x, y) => PhysicalPosition {
x: f64::from(x) * line_px.x,
y: f64::from(y) * line_px.y,
},
Self::PageDelta(x, y) => PhysicalPosition {
x: f64::from(x) * page_px.x,
y: f64::from(y) * page_px.y,
},
}
}
#[inline]
pub fn into_pixel_delta(
self,
line_px: PhysicalPosition<f64>,
page_px: PhysicalPosition<f64>,
) -> Self {
Self::PixelDelta(self.to_pixel_delta(line_px, page_px))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pixel_passthrough() {
let p = PhysicalPosition { x: 1.0, y: -2.0 };
assert_eq!(
ScrollDelta::PixelDelta(p).to_pixel_delta(
PhysicalPosition { x: 10.0, y: 10.0 },
PhysicalPosition { x: 100.0, y: 100.0 },
),
p
);
}
#[test]
fn line_delta_scales_per_axis() {
let line_px = PhysicalPosition { x: 2.0, y: 10.0 };
let page_px = PhysicalPosition { x: 100.0, y: 100.0 };
assert_eq!(
ScrollDelta::LineDelta(3.0, -1.0).to_pixel_delta(line_px, page_px),
PhysicalPosition { x: 6.0, y: -10.0 }
);
}
#[test]
fn page_delta_scales_per_axis() {
let line_px = PhysicalPosition { x: 10.0, y: 10.0 };
let page_px = PhysicalPosition { x: 4.0, y: 20.0 };
assert_eq!(
ScrollDelta::PageDelta(0.5, -2.0).to_pixel_delta(line_px, page_px),
PhysicalPosition { x: 2.0, y: -40.0 }
);
}
#[test]
fn into_pixel_delta_wraps() {
let out = ScrollDelta::LineDelta(1.0, 1.0).into_pixel_delta(
PhysicalPosition { x: 5.0, y: 6.0 },
PhysicalPosition { x: 100.0, y: 100.0 },
);
assert_eq!(
out,
ScrollDelta::PixelDelta(PhysicalPosition { x: 5.0, y: 6.0 })
);
}
}