cranpose 0.1.141

Cranpose runtime and UI facade
Documentation
use cranpose_app_shell::{Modifiers, WheelScroll};
use cranpose_ui::Point;

const WEB_WHEEL_LINE_DELTA_PIXELS: f32 = 40.0;

pub(crate) const DOM_DELTA_PIXEL: u32 = 0;
pub(crate) const DOM_DELTA_LINE: u32 = 1;
pub(crate) const DOM_DELTA_PAGE: u32 = 2;

#[derive(Clone, Copy, Debug, PartialEq)]
pub(crate) struct WebWheelPage {
    pub width: f32,
    pub height: f32,
}

pub(crate) fn wheel_scroll_from_dom(
    delta_x: f32,
    delta_y: f32,
    delta_mode: u32,
    page: WebWheelPage,
    modifiers: Modifiers,
    uptime_millis: u64,
) -> WheelScroll {
    let (unit_x, unit_y) = match delta_mode {
        DOM_DELTA_PIXEL => (1.0, 1.0),
        DOM_DELTA_LINE => (WEB_WHEEL_LINE_DELTA_PIXELS, WEB_WHEEL_LINE_DELTA_PIXELS),
        DOM_DELTA_PAGE => (page.width.max(1.0), page.height.max(1.0)),
        _ => (1.0, 1.0),
    };

    WheelScroll::new(
        Point {
            x: -delta_x * unit_x,
            y: -delta_y * unit_y,
        },
        uptime_millis,
    )
    .with_modifiers(modifiers)
}

#[cfg(test)]
mod tests {
    use super::*;

    const PAGE: WebWheelPage = WebWheelPage {
        width: 800.0,
        height: 600.0,
    };

    fn dom(delta_x: f32, delta_y: f32, delta_mode: u32) -> WheelScroll {
        wheel_scroll_from_dom(delta_x, delta_y, delta_mode, PAGE, Modifiers::NONE, 0)
    }

    #[test]
    fn a_wheel_turned_down_in_the_browser_scrolls_the_same_way_it_does_on_the_desktop() {
        let down = dom(0.0, 100.0, DOM_DELTA_PIXEL);
        let up = dom(0.0, -100.0, DOM_DELTA_PIXEL);

        assert_eq!(down.delta.y, -100.0);
        assert_eq!(up.delta.y, 100.0);
    }

    #[test]
    fn the_horizontal_axis_is_negated_with_the_vertical_one() {
        let right = dom(75.0, 0.0, DOM_DELTA_PIXEL);

        assert_eq!(right.delta.x, -75.0);
        assert_eq!(right.delta.y, 0.0);
    }

    #[test]
    fn line_and_page_modes_are_converted_to_pixels() {
        assert_eq!(dom(0.0, 3.0, DOM_DELTA_LINE).delta.y, -120.0);
        assert_eq!(dom(2.0, 0.0, DOM_DELTA_LINE).delta.x, -80.0);
        assert_eq!(dom(0.0, 1.0, DOM_DELTA_PAGE).delta.y, -PAGE.height);
        assert_eq!(dom(1.0, 0.0, DOM_DELTA_PAGE).delta.x, -PAGE.width);
    }

    #[test]
    fn a_degenerate_page_size_still_scrolls() {
        let sample = wheel_scroll_from_dom(
            0.0,
            1.0,
            DOM_DELTA_PAGE,
            WebWheelPage {
                width: 0.0,
                height: 0.0,
            },
            Modifiers::NONE,
            0,
        );

        assert_eq!(sample.delta.y, -1.0);
    }

    #[test]
    fn an_unknown_delta_mode_is_read_as_pixels_rather_than_dropped() {
        assert_eq!(dom(0.0, 12.0, 99).delta.y, -12.0);
    }

    #[test]
    fn a_browser_pinch_arrives_as_the_zoom_gesture_and_zooms_in_when_spread() {
        let spread = wheel_scroll_from_dom(
            0.0,
            -40.0,
            DOM_DELTA_PIXEL,
            PAGE,
            Modifiers {
                ctrl: true,
                ..Modifiers::NONE
            },
            0,
        );

        assert!(spread.is_zoom());
        assert!(spread.zoom_factor() > 1.0);
    }
}