ramp2 1.0.1

RAMP is the glue for Maverick OS, Air Servers, And Prisms UI abstraction
use ::air::Secret;
use maverick_os::inputs as native;
use maverick_os::{Data, Hardware, LogicalWindow};
use prism::events as event;

pub use maverick_os;
pub use prism;
pub use renderer::Renderer;

pub mod air;
pub mod hardware;
mod renderer;

pub struct Ramp<A: prism::Application>(prism::Prism<A>);
impl<A: prism::Application> maverick_os::Application for Ramp<A> {
    type Renderer = Renderer;

    fn name() -> String {A::name()}

    fn new(hardware: Hardware, window: LogicalWindow) -> Self {
        let key = "ramp.air.identity";
        let secret = match hardware.get_cache(key) {
            Some(Data::Text(saved)) => serde_json::from_str(&saved).expect("Invalid saved Air identity"),
            Some(_) => panic!("The saved Air identity must be text"),
            None => {
                let secret = Secret::new();
                let saved = serde_json::to_string(&secret).expect("Could not encode the Air identity");
                hardware.set_cache(key, &Data::Text(saved));
                secret
            }
        };
        let window = prism::Window {size: window.size, insets: window.insets};
        Self(prism::Prism::new(hardware::Hardware(hardware), air::Air::new(secret), window))
    }

    fn on_input(&mut self, input: native::Input) {
        match input {
            native::Input::Resized(window) => {
                self.0.resize(prism::Window {size: window.size, insets: window.insets});
            }
            native::Input::WindowFocused(focused) => {
                self.0.on_event(event::WindowEvent::Focused(focused));
                if !focused {
                    self.0.on_event(event::MouseEvent {position: None, state: event::MouseState::Moved});
                }
            }
            native::Input::WindowMoved(x, y) => self.0.on_event(event::WindowEvent::Moved(x, y)),
            native::Input::DroppedFile(path) => self.0.on_event(event::FileEvent::Dropped(path)),
            native::Input::HoveredFile(path) => self.0.on_event(event::FileEvent::Hovered(path)),
            native::Input::HoveredFileCancelled => self.0.on_event(event::FileEvent::Cancelled),
            native::Input::Device(device, input) => match input {
                native::DeviceInput::Keyboard(key, state, modifiers) => {
                    let key = match key {
                        native::Key::Escape => event::Key::Escape,
                        native::Key::Enter => event::Key::Enter,
                        native::Key::Tab => event::Key::Tab,
                        native::Key::Space => event::Key::Space,
                        native::Key::Up => event::Key::Up,
                        native::Key::Down => event::Key::Down,
                        native::Key::Left => event::Key::Left,
                        native::Key::Right => event::Key::Right,
                        native::Key::Delete => event::Key::Delete,
                        native::Key::Backspace => event::Key::Backspace,
                        native::Key::Home => event::Key::Home,
                        native::Key::End => event::Key::End,
                        native::Key::Shift => event::Key::Shift,
                        native::Key::Control => event::Key::Control,
                        native::Key::Alt => event::Key::Alt,
                        native::Key::SuperMeta => event::Key::SuperMeta,
                        native::Key::CapsLock => event::Key::CapsLock,
                        native::Key::NumLock => event::Key::NumLock,
                        native::Key::ScrollLock => event::Key::ScrollLock,
                        native::Key::Character(character) => event::Key::Character(character.to_string()),
                        key => {log::debug!("Unsupported keyboard key: {key:?}"); return}
                    };
                    let state = match state {
                        native::KeyboardState::Pressed => event::KeyboardState::Pressed,
                        native::KeyboardState::Repeated => event::KeyboardState::Repeated,
                        native::KeyboardState::Released => event::KeyboardState::Released,
                    };
                    let modifiers = event::Modifiers {
                        shift: modifiers.shift, control: modifiers.control,
                        alt: modifiers.alt, supermeta: modifiers.supermeta,
                    };
                    self.0.on_event(event::KeyboardEvent {key, state, modifiers});
                }
                native::DeviceInput::Mouse(position, state) => {
                    let button = |button| match button {
                        native::MouseButton::Left => event::MouseButton::Left,
                        native::MouseButton::Middle => event::MouseButton::Middle,
                        native::MouseButton::Right => event::MouseButton::Right,
                    };
                    let state = match state {
                        native::MouseState::Pressed(b) => event::MouseState::Pressed(button(b)),
                        native::MouseState::Released(b) => event::MouseState::Released(button(b)),
                        native::MouseState::Moved => event::MouseState::Moved,
                        native::MouseState::Scroll(x, y) => event::MouseState::Scroll(x, y),
                    };
                    self.0.on_event(event::MouseEvent {position: Some(position), state});
                }
                native::DeviceInput::CursorEntered => {
                    self.0.on_event(event::CursorEvent {device, entered: true});
                }
                native::DeviceInput::CursorLeft => {
                    self.0.on_event(event::CursorEvent {device, entered: false});
                    self.0.on_event(event::MouseEvent {position: None, state: event::MouseState::Moved});
                }
            },
        }
    }

    fn on_tick(&mut self) -> Vec<prism::drawable::Instruction> {self.0.draw()}
}

#[macro_export]
macro_rules! run {
    ($app:ty) => {$crate::maverick_os::start!($crate::Ramp<$app>);};
}