use crate::Cursive;
use crate::Vec2;
use std::any::Any;
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
#[derive(Clone)]
pub struct Callback(Rc<Box<dyn Fn(&mut Cursive)>>);
pub type AnyCb<'a> = &'a mut dyn FnMut(&mut dyn Any);
pub struct EventTrigger(Box<dyn Fn(&Event) -> bool>);
impl EventTrigger {
pub fn from_fn<F>(f: F) -> Self
where
F: 'static + Fn(&Event) -> bool,
{
EventTrigger(Box::new(f))
}
pub fn apply(&self, event: &Event) -> bool {
(self.0)(event)
}
pub fn arrows() -> Self {
Self::from_fn(|e| match e {
Event::Key(Key::Left)
| Event::Key(Key::Down)
| Event::Key(Key::Up)
| Event::Key(Key::Right) => true,
_ => false,
})
}
pub fn mouse() -> Self {
Self::from_fn(|e| match e {
Event::Mouse { .. } => true,
_ => false,
})
}
pub fn any() -> Self {
Self::from_fn(|_| true)
}
pub fn none() -> Self {
Self::from_fn(|_| false)
}
pub fn or<O>(self, other: O) -> Self
where
O: Into<EventTrigger>,
{
let other = other.into();
Self::from_fn(move |e| self.apply(e) || other.apply(e))
}
}
impl From<Event> for EventTrigger {
fn from(event: Event) -> Self {
Self::from_fn(move |e| *e == event)
}
}
impl From<char> for EventTrigger {
fn from(c: char) -> Self {
Self::from(Event::from(c))
}
}
impl From<Key> for EventTrigger {
fn from(k: Key) -> Self {
Self::from(Event::from(k))
}
}
impl<F> From<F> for EventTrigger
where
F: 'static + Fn(&Event) -> bool,
{
fn from(f: F) -> Self {
Self::from_fn(f)
}
}
impl Callback {
pub fn from_fn<F>(f: F) -> Self
where
F: 'static + Fn(&mut Cursive),
{
Callback(Rc::new(Box::new(move |siv| {
f(siv);
})))
}
pub fn from_fn_mut<F>(f: F) -> Self
where
F: 'static + FnMut(&mut Cursive),
{
let cb = RefCell::new(f);
Self::from_fn(move |s| {
if let Ok(mut cb) = cb.try_borrow_mut() {
(&mut *cb)(s);
}
})
}
pub fn dummy() -> Self {
Callback::from_fn(|_| ())
}
}
impl Deref for Callback {
type Target = Box<dyn Fn(&mut Cursive)>;
fn deref<'a>(&'a self) -> &'a Box<dyn Fn(&mut Cursive)> {
&self.0
}
}
impl From<Rc<Box<dyn Fn(&mut Cursive)>>> for Callback {
fn from(f: Rc<Box<dyn Fn(&mut Cursive)>>) -> Self {
Callback(f)
}
}
impl From<Box<dyn Fn(&mut Cursive) + Send>> for Callback {
fn from(f: Box<dyn Fn(&mut Cursive) + Send>) -> Self {
Callback(Rc::new(f))
}
}
impl From<Box<dyn Fn(&mut Cursive)>> for Callback {
fn from(f: Box<dyn Fn(&mut Cursive)>) -> Self {
Callback(Rc::new(f))
}
}
pub enum EventResult {
Ignored,
Consumed(Option<Callback>), }
impl EventResult {
pub fn with_cb<F>(f: F) -> Self
where
F: 'static + Fn(&mut Cursive),
{
EventResult::Consumed(Some(Callback::from_fn(f)))
}
pub fn is_consumed(&self) -> bool {
match *self {
EventResult::Consumed(_) => true,
_ => false,
}
}
pub fn has_callback(&self) -> bool {
match *self {
EventResult::Consumed(Some(_)) => true,
_ => false,
}
}
pub fn process(self, s: &mut Cursive) {
if let EventResult::Consumed(Some(cb)) = self {
cb(s);
}
}
pub fn or_else<F>(self, f: F) -> Self
where
F: FnOnce() -> EventResult,
{
match self {
EventResult::Ignored => f(),
other => other,
}
}
pub fn and(self, other: Self) -> Self {
match (self, other) {
(EventResult::Ignored, result)
| (result, EventResult::Ignored) => result,
(EventResult::Consumed(None), EventResult::Consumed(cb))
| (EventResult::Consumed(cb), EventResult::Consumed(None)) => {
EventResult::Consumed(cb)
}
(
EventResult::Consumed(Some(cb1)),
EventResult::Consumed(Some(cb2)),
) => EventResult::with_cb(move |siv| {
(cb1)(siv);
(cb2)(siv);
}),
}
}
}
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum Key {
Enter,
Tab,
Backspace,
Esc,
Left,
Right,
Up,
Down,
Ins,
Del,
Home,
End,
PageUp,
PageDown,
PauseBreak,
NumpadCenter,
F0,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
}
impl Key {
pub fn from_f(n: u8) -> Key {
match n {
0 => Key::F0,
1 => Key::F1,
2 => Key::F2,
3 => Key::F3,
4 => Key::F4,
5 => Key::F5,
6 => Key::F6,
7 => Key::F7,
8 => Key::F8,
9 => Key::F9,
10 => Key::F10,
11 => Key::F11,
12 => Key::F12,
_ => panic!("unknown function key: F{}", n),
}
}
}
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseButton {
Left,
Middle,
Right,
Button4,
Button5,
#[doc(hidden)]
Other,
}
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
pub enum MouseEvent {
Press(MouseButton),
Release(MouseButton),
Hold(MouseButton),
WheelUp,
WheelDown,
}
impl MouseEvent {
pub fn button(self) -> Option<MouseButton> {
match self {
MouseEvent::Press(btn)
| MouseEvent::Release(btn)
| MouseEvent::Hold(btn) => Some(btn),
_ => None,
}
}
pub fn grabs_focus(self) -> bool {
match self {
MouseEvent::Press(_)
| MouseEvent::WheelUp
| MouseEvent::WheelDown => true,
_ => false,
}
}
}
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
pub enum Event {
WindowResize,
Refresh,
Char(char),
CtrlChar(char),
AltChar(char),
Key(Key),
Shift(Key),
Alt(Key),
AltShift(Key),
Ctrl(Key),
CtrlShift(Key),
CtrlAlt(Key),
Mouse {
offset: Vec2,
position: Vec2,
event: MouseEvent,
},
Unknown(Vec<u8>),
#[doc(hidden)]
Exit,
}
impl Event {
pub fn mouse_position(&self) -> Option<Vec2> {
if let Event::Mouse { position, .. } = *self {
Some(position)
} else {
None
}
}
pub fn mouse_position_mut(&mut self) -> Option<&mut Vec2> {
if let Event::Mouse {
ref mut position, ..
} = *self
{
Some(position)
} else {
None
}
}
pub fn relativize<V>(&mut self, top_left: V)
where
V: Into<Vec2>,
{
if let Event::Mouse { ref mut offset, .. } = *self {
*offset = *offset + top_left;
}
}
pub fn relativized<V>(&self, top_left: V) -> Self
where
V: Into<Vec2>,
{
let mut result = self.clone();
result.relativize(top_left);
result
}
}
impl From<char> for Event {
fn from(c: char) -> Event {
Event::Char(c)
}
}
impl From<Key> for Event {
fn from(k: Key) -> Event {
Event::Key(k)
}
}