use crate::Cursive;
use crate::Vec2;
use std::any::Any;
use std::ops::Deref;
use std::rc::Rc;
#[derive(Clone)]
pub struct Callback(Rc<dyn Fn(&mut Cursive)>);
pub type AnyCb<'a> = &'a mut dyn FnMut(&mut dyn crate::view::View);
pub struct EventTrigger {
trigger: Box<dyn Fn(&Event) -> bool>,
tag: Box<dyn AnyTag>,
}
trait AnyTag: Any + std::fmt::Debug {
fn as_any(&self) -> &dyn Any;
}
impl<T> AnyTag for T
where
T: Any + std::fmt::Debug,
{
fn as_any(&self) -> &dyn Any {
self
}
}
impl EventTrigger {
pub fn from_fn<F>(f: F) -> Self
where
F: 'static + Fn(&Event) -> bool,
{
EventTrigger::from_fn_and_tag(f, "free function")
}
pub fn from_fn_and_tag<F, T>(f: F, tag: T) -> Self
where
F: 'static + Fn(&Event) -> bool,
T: Any + std::fmt::Debug,
{
let tag = Box::new(tag);
let trigger = Box::new(f);
EventTrigger { trigger, tag }
}
pub fn has_tag<T: PartialEq + 'static>(&self, tag: &T) -> bool {
(*self.tag)
.as_any()
.downcast_ref::<T>()
.map_or(false, |t| tag == t)
}
pub fn apply(&self, event: &Event) -> bool {
(self.trigger)(event)
}
pub fn arrows() -> Self {
Self::from_fn_and_tag(
|e| {
matches!(
e,
Event::Key(Key::Left)
| Event::Key(Key::Down)
| Event::Key(Key::Up)
| Event::Key(Key::Right)
)
},
"arrows",
)
}
pub fn mouse() -> Self {
Self::from_fn_and_tag(|e| matches!(e, Event::Mouse { .. }), "mouse")
}
pub fn any() -> Self {
Self::from_fn_and_tag(|_| true, "any")
}
pub fn none() -> Self {
Self::from_fn_and_tag(|_| false, "none")
}
#[must_use]
pub fn or<O>(self, other: O) -> Self
where
O: Into<EventTrigger>,
{
let other = other.into();
let self_trigger = self.trigger;
let other_trigger = other.trigger;
let tag = (self.tag, "or", other.tag);
Self::from_fn_and_tag(
move |e| self_trigger(e) || other_trigger(e),
tag,
)
}
}
impl From<Event> for EventTrigger {
fn from(event: Event) -> Self {
let tag = event.clone();
Self::from_fn_and_tag(move |e| *e == event, tag)
}
}
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(move |siv| {
f(siv);
}))
}
pub fn from_fn_mut<F>(f: F) -> Self
where
F: 'static + FnMut(&mut Cursive),
{
Self::from_fn(crate::immut1!(f))
}
pub fn from_fn_once<F>(f: F) -> Self
where
F: 'static + FnOnce(&mut Cursive),
{
Self::from_fn_mut(crate::once1!(f))
}
pub fn dummy() -> Self {
Callback::from_fn(|_| ())
}
}
impl Deref for Callback {
type Target = dyn Fn(&mut Cursive) + 'static;
fn deref(&self) -> &Self::Target {
&*self.0
}
}
impl From<Rc<dyn Fn(&mut Cursive)>> for Callback {
fn from(f: Rc<dyn Fn(&mut Cursive)>) -> Self {
Callback(f)
}
}
impl From<Box<dyn Fn(&mut Cursive)>> for Callback {
fn from(f: Box<dyn Fn(&mut Cursive)>) -> Self {
Callback(Rc::from(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 with_cb_once<F>(f: F) -> Self
where
F: 'static + FnOnce(&mut Cursive),
{
EventResult::Consumed(Some(Callback::from_fn_once(f)))
}
pub fn consumed() -> Self {
EventResult::Consumed(None)
}
pub fn is_consumed(&self) -> bool {
matches!(*self, EventResult::Consumed(_))
}
pub fn has_callback(&self) -> bool {
matches!(*self, EventResult::Consumed(Some(_)))
}
pub fn process(self, s: &mut Cursive) {
if let EventResult::Consumed(Some(cb)) = self {
cb(s);
}
}
#[must_use]
pub fn or_else<F>(self, f: F) -> Self
where
F: FnOnce() -> EventResult,
{
match self {
EventResult::Ignored => f(),
other => other,
}
}
#[must_use]
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 {
matches!(
self,
MouseEvent::Press(_) | MouseEvent::WheelUp | MouseEvent::WheelDown
)
}
}
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
pub enum Event {
WindowResize,
FocusLost,
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;
}
}
#[must_use]
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)
}
}