use crate::kurbo::{Rect, Shape, Size, Vec2};
use druid_shell::{Clipboard, KeyEvent, KeyModifiers, TimerToken};
use crate::mouse::MouseEvent;
use crate::{Command, Target, WidgetId};
#[derive(Debug, Clone)]
pub enum Event {
WindowConnected,
Size(Size),
MouseDown(MouseEvent),
MouseUp(MouseEvent),
MouseMoved(MouseEvent),
KeyDown(KeyEvent),
KeyUp(KeyEvent),
Paste(Clipboard),
Wheel(WheelEvent),
Zoom(f64),
Timer(TimerToken),
Command(Command),
TargetedCommand(Target, Command),
}
#[derive(Debug, Clone)]
pub enum LifeCycle {
WidgetAdded,
RouteWidgetAdded,
AnimFrame(u64),
HotChanged(bool),
RouteFocusChanged {
old: Option<WidgetId>,
new: Option<WidgetId>,
},
FocusChanged(bool),
#[cfg(test)]
DebugRequestState {
widget: WidgetId,
state_cell: StateCell,
},
#[cfg(test)]
DebugInspectState(StateCheckFn),
}
#[derive(Debug, Clone)]
pub struct WheelEvent {
pub delta: Vec2,
pub mods: KeyModifiers,
}
impl Event {
pub fn transform_scroll(&self, offset: Vec2, viewport: Rect, force: bool) -> Option<Event> {
match self {
Event::MouseDown(mouse_event) => {
if force || viewport.winding(mouse_event.pos) != 0 {
let mut mouse_event = mouse_event.clone();
mouse_event.pos += offset;
Some(Event::MouseDown(mouse_event))
} else {
None
}
}
Event::MouseUp(mouse_event) => {
if force || viewport.winding(mouse_event.pos) != 0 {
let mut mouse_event = mouse_event.clone();
mouse_event.pos += offset;
Some(Event::MouseUp(mouse_event))
} else {
None
}
}
Event::MouseMoved(mouse_event) => {
if force || viewport.winding(mouse_event.pos) != 0 {
let mut mouse_event = mouse_event.clone();
mouse_event.pos += offset;
Some(Event::MouseMoved(mouse_event))
} else {
None
}
}
_ => Some(self.clone()),
}
}
}
#[cfg(test)]
pub(crate) use state_cell::{StateCell, StateCheckFn};
#[cfg(test)]
mod state_cell {
use crate::core::BaseState;
use crate::WidgetId;
use std::{cell::RefCell, rc::Rc};
#[derive(Clone, Default)]
pub struct StateCell(Rc<RefCell<Option<BaseState>>>);
#[derive(Clone)]
pub struct StateCheckFn(Rc<dyn Fn(&BaseState)>);
struct WidgetDrop(bool, WidgetId);
impl Drop for WidgetDrop {
fn drop(&mut self) {
if self.0 {
eprintln!("panic in {:?}", self.1);
}
}
}
impl StateCell {
pub(crate) fn set(&self, state: BaseState) {
assert!(
self.0.borrow_mut().replace(state).is_none(),
"StateCell already set"
)
}
#[allow(dead_code)]
pub(crate) fn take(&self) -> Option<BaseState> {
self.0.borrow_mut().take()
}
}
impl StateCheckFn {
pub(crate) fn new(f: impl Fn(&BaseState) + 'static) -> Self {
StateCheckFn(Rc::new(f))
}
pub(crate) fn call(&self, state: &BaseState) {
let mut panic_reporter = WidgetDrop(true, state.id);
(self.0)(&state);
panic_reporter.0 = false;
}
}
impl std::fmt::Debug for StateCell {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let inner = if self.0.borrow().is_some() {
"Some"
} else {
"None"
};
write!(f, "StateCell({})", inner)
}
}
impl std::fmt::Debug for StateCheckFn {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "StateCheckFn")
}
}
}