fatui 0.1.0

a silly little framework for terminal user interfaces
Documentation
use crossterm::event::{KeyCode, MouseButton};
use std::rc::Rc;

use crate::pos::{Pos, X, Y};

use super::FrameInput;

/// a raw input event
///
/// this represents the barest form of user input.
/// it tracks no state and provides no history,
/// which can make it underpowered for a lot of use cases.
/// you may prefer to track a whole [`Input`][crate::Input] instead.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Event {
	/// no actual specific input --
	/// the renderer just needs to redraw the ui,
	/// e.g. due to a window size change or the window regaining focus
	Redraw,
	/// the window has been closed and you should end the software now
	Close,
	/// there was a mouse input, outside of the current region
	MouseOutside,
	/// the mouse moved to the given new position
	MouseMove(Pos),
	/// a mouse button was pressed
	MouseDown(MouseButton, Pos),
	/// a mouse button was released
	MouseUp(MouseButton, Pos),
	/// a key was pressed
	KeyPress(KeyCode),
	/// a key was released
	KeyRelease(KeyCode),
	/// some text was pasted
	Paste(Rc<str>),
}
crate::seal!(Event);

impl Default for Event {
	fn default() -> Self {
		Self::Redraw
	}
}

macro_rules! split {
	($fn:ident, $field:ident, $pos:ty) => {
		fn $fn(self, mid: $pos) -> (Self, Self) {
			match self {
				Self::MouseMove(pos) => {
					if pos.$field < mid {
						(self, Self::MouseOutside)
					} else {
						(Self::MouseOutside, Self::MouseMove(pos - mid))
					}
				}
				Self::MouseDown(b, pos) => {
					if pos.$field < mid {
						(self, Self::MouseOutside)
					} else {
						(Self::MouseOutside, Self::MouseDown(b, pos - mid))
					}
				}
				Self::MouseUp(b, pos) => {
					if pos.$field < mid {
						(self, Self::MouseOutside)
					} else {
						(Self::MouseOutside, Self::MouseUp(b, pos - mid))
					}
				}
				other => (other.clone(), other.clone()),
			}
		}
	};
}

impl FrameInput for Event {
	split!(split_h, x, X);
	split!(split_v, y, Y);
}