use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use tairitsu_vdom::{EventData, MouseEvent, Platform};
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum TriggerMode {
Continuous,
OncePerState,
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum AnimationEventType {
MouseEnter,
MouseLeave,
MouseMove { throttle_ms: u32 },
GlobalMouseMove { throttle_ms: u32 },
Click,
Focus,
Blur,
}
pub struct AnimationTrigger {
pub event: AnimationEventType,
pub mode: TriggerMode,
pub debounce_ms: u32,
}
impl Default for AnimationTrigger {
fn default() -> Self {
Self {
event: AnimationEventType::MouseEnter,
mode: TriggerMode::OncePerState,
debounce_ms: 100,
}
}
}
impl AnimationTrigger {
pub fn new(event: AnimationEventType) -> Self {
Self {
event,
..Default::default()
}
}
pub fn with_mode(mut self, mode: TriggerMode) -> Self {
self.mode = mode;
self
}
pub fn with_debounce(mut self, debounce_ms: u32) -> Self {
self.debounce_ms = debounce_ms;
self
}
}
pub struct EventDrivenAnimation<'a, P: Platform> {
platform: Rc<RefCell<P>>,
elements: &'a HashMap<String, P::Element>,
element: P::Element,
window_element: Option<P::Element>,
}
impl<'a, P: Platform> EventDrivenAnimation<'a, P> {
pub fn new(
platform: Rc<RefCell<P>>,
elements: &'a HashMap<String, P::Element>,
element: P::Element,
) -> Self {
Self {
platform,
elements,
element,
window_element: None,
}
}
pub fn with_window_element(&mut self, window_element: P::Element) -> &mut Self {
self.window_element = Some(window_element);
self
}
pub fn on_mouse_enter<F>(&mut self, f: F) -> &mut Self
where
F: Fn(i32, i32) -> String + 'static,
{
self.bind_event("mouseenter", move |event: Box<dyn EventData>| {
event
.as_any()
.downcast_ref::<MouseEvent>()
.map(|mouse_event| (f)(mouse_event.client_x, mouse_event.client_y))
})
}
pub fn on_mouse_leave<F>(&mut self, f: F) -> &mut Self
where
F: Fn(i32, i32) -> String + 'static,
{
self.bind_event("mouseleave", move |event: Box<dyn EventData>| {
event
.as_any()
.downcast_ref::<MouseEvent>()
.map(|mouse_event| (f)(mouse_event.client_x, mouse_event.client_y))
})
}
pub fn on_mouse_move<F>(&mut self, _throttle_ms: u32, f: F) -> &mut Self
where
F: Fn(i32, i32) -> String + 'static,
{
self.bind_event("mousemove", move |event: Box<dyn EventData>| {
event
.as_any()
.downcast_ref::<MouseEvent>()
.map(|mouse_event| (f)(mouse_event.client_x, mouse_event.client_y))
})
}
pub fn on_global_mouse_move<F>(&mut self, _throttle_ms: u32, f: F) -> &mut Self
where
F: Fn(i32, i32) -> String + 'static,
{
let has_window = self.window_element.is_some();
if has_window {
if let Some(window_elem) = self.window_element.take() {
let platform = self.platform.clone();
let elements = self.elements.clone();
let wrapped_handler = move |event: Box<dyn EventData>| {
if let Some(mouse_event) = event.as_any().downcast_ref::<MouseEvent>() {
let value_str = (f)(mouse_event.client_x, mouse_event.client_y);
for element_handle in elements.values() {
platform.borrow_mut().set_style(
element_handle,
"transform",
&value_str,
);
}
}
};
self.platform.borrow_mut().add_event_listener(
&window_elem,
"mousemove",
Box::new(wrapped_handler),
);
self.window_element = Some(window_elem);
}
} else {
let platform = self.platform.clone();
let elements = self.elements.clone();
let element = self.element.clone();
let wrapped_handler = move |event: Box<dyn EventData>| {
if let Some(mouse_event) = event.as_any().downcast_ref::<MouseEvent>() {
let value_str = (f)(mouse_event.client_x, mouse_event.client_y);
for element_handle in elements.values() {
platform
.borrow_mut()
.set_style(element_handle, "transform", &value_str);
}
}
};
self.platform.borrow_mut().add_event_listener(
&element,
"mousemove",
Box::new(wrapped_handler),
);
}
self
}
pub fn on_click<F>(&mut self, f: F) -> &mut Self
where
F: Fn(i32, i32) -> String + 'static,
{
self.bind_event("click", move |event: Box<dyn EventData>| {
event
.as_any()
.downcast_ref::<MouseEvent>()
.map(|mouse_event| (f)(mouse_event.client_x, mouse_event.client_y))
})
}
pub fn on_focus<F>(&mut self, f: F) -> &mut Self
where
F: Fn() -> String + 'static,
{
self.bind_event("focus", move |_event: Box<dyn EventData>| Some((f)()))
}
pub fn on_blur<F>(&mut self, f: F) -> &mut Self
where
F: Fn() -> String + 'static,
{
self.bind_event("blur", move |_event: Box<dyn EventData>| Some((f)()))
}
fn bind_event<F>(&mut self, event_type: &str, handler: F) -> &mut Self
where
F: Fn(Box<dyn EventData>) -> Option<String> + 'static,
{
let platform = self.platform.clone();
let elements = self.elements.clone();
let element = self.element.clone();
let wrapped_handler = move |event: Box<dyn EventData>| {
if let Some(value_str) = handler(event) {
for element_handle in elements.values() {
platform
.borrow_mut()
.set_style(element_handle, "transform", &value_str);
}
}
};
self.platform.borrow_mut().add_event_listener(
&element,
event_type,
Box::new(wrapped_handler),
);
self
}
pub fn build(&mut self) {
}
}