mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
clean up mod command
This commit is contained in:
parent
6663f4efcb
commit
6776e2ec55
4 changed files with 99 additions and 113 deletions
113
src/command.rs
113
src/command.rs
|
|
@ -10,6 +10,13 @@ use crate::*;
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Command<S>: Send + Sync + Sized {
|
||||
fn execute (self, state: &mut S) -> Perhaps<Self>;
|
||||
fn delegate <T> (self, state: &mut S, wrap: impl Fn(Self)->T) -> Perhaps<T> {
|
||||
Ok(self.execute(state)?.map(wrap))
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! input_to_command {
|
||||
($Command:ty: <$Engine:ty>|$state:ident:$State:ty,$input:ident|$handler:expr) => {
|
||||
impl InputToCommand<$Engine, $State> for $Command {
|
||||
|
|
@ -20,27 +27,6 @@ use crate::*;
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum NextPrev {
|
||||
Next,
|
||||
Prev,
|
||||
}
|
||||
|
||||
pub trait Execute<T> {
|
||||
fn command (&mut self, command: T) -> Perhaps<T>;
|
||||
}
|
||||
|
||||
pub trait Command<S>: Send + Sync + Sized {
|
||||
fn execute (self, state: &mut S) -> Perhaps<Self>;
|
||||
}
|
||||
pub fn delegate <B, C: Command<S>, S> (
|
||||
cmd: C,
|
||||
wrap: impl Fn(C)->B,
|
||||
state: &mut S,
|
||||
) -> Perhaps<B> {
|
||||
Ok(cmd.execute(state)?.map(wrap))
|
||||
}
|
||||
|
||||
pub trait InputToCommand<E: Engine, S>: Command<S> + Sized {
|
||||
fn input_to_command (state: &S, input: &E::Input) -> Option<Self>;
|
||||
fn execute_with_state (state: &mut S, input: &E::Input) -> Perhaps<bool> {
|
||||
|
|
@ -52,65 +38,38 @@ pub trait InputToCommand<E: Engine, S>: Command<S> + Sized {
|
|||
})
|
||||
}
|
||||
}
|
||||
pub struct MenuBar<E: Engine, S, C: Command<S>> {
|
||||
pub menus: Vec<Menu<E, S, C>>,
|
||||
pub index: usize,
|
||||
}
|
||||
impl<E: Engine, S, C: Command<S>> MenuBar<E, S, C> {
|
||||
pub fn new () -> Self { Self { menus: vec![], index: 0 } }
|
||||
pub fn add (mut self, menu: Menu<E, S, C>) -> Self {
|
||||
self.menus.push(menu);
|
||||
self
|
||||
}
|
||||
}
|
||||
pub struct Menu<E: Engine, S, C: Command<S>> {
|
||||
pub title: String,
|
||||
pub items: Vec<MenuItem<E, S, C>>,
|
||||
pub index: Option<usize>,
|
||||
}
|
||||
impl<E: Engine, S, C: Command<S>> Menu<E, S, C> {
|
||||
pub fn new (title: impl AsRef<str>) -> Self {
|
||||
Self {
|
||||
title: title.as_ref().to_string(),
|
||||
items: vec![],
|
||||
index: None,
|
||||
|
||||
pub type KeyMapping<const N: usize, E, T, U> = [(E, &'static dyn Fn(&T)->U);N];
|
||||
|
||||
pub struct EventMap<'a, const N: usize, E, T, U>(
|
||||
pub [(E, &'a dyn Fn(T) -> U); N],
|
||||
pub Option<&'a dyn Fn(T) -> U>,
|
||||
);
|
||||
|
||||
impl<'a, const N: usize, E: PartialEq, T, U> EventMap<'a, N, E, T, U> {
|
||||
pub fn handle (&self, context: T, event: &E) -> Option<U> {
|
||||
for (binding, handler) in self.0.iter() {
|
||||
if event == binding {
|
||||
return Some(handler(context))
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn add (mut self, item: MenuItem<E, S, C>) -> Self {
|
||||
self.items.push(item);
|
||||
self
|
||||
}
|
||||
pub fn sep (mut self) -> Self {
|
||||
self.items.push(MenuItem::sep());
|
||||
self
|
||||
}
|
||||
pub fn cmd (mut self, hotkey: &'static str, text: &'static str, command: C) -> Self {
|
||||
self.items.push(MenuItem::cmd(hotkey, text, command));
|
||||
self
|
||||
}
|
||||
pub fn off (mut self, hotkey: &'static str, text: &'static str) -> Self {
|
||||
self.items.push(MenuItem::off(hotkey, text));
|
||||
self
|
||||
return None
|
||||
}
|
||||
}
|
||||
pub enum MenuItem<E: Engine, S, C: Command<S>> {
|
||||
/// Unused.
|
||||
__(PhantomData<E>, PhantomData<S>),
|
||||
/// A separator. Skip it.
|
||||
Separator,
|
||||
/// A menu item with command, description and hotkey.
|
||||
Command(&'static str, &'static str, C),
|
||||
/// A menu item that can't be activated but has description and hotkey
|
||||
Disabled(&'static str, &'static str)
|
||||
|
||||
#[macro_export] macro_rules! event_map {
|
||||
($events:expr) => {
|
||||
EventMap($events, None)
|
||||
};
|
||||
($events:expr, $default: expr) => {
|
||||
EventMap($events, $default)
|
||||
};
|
||||
}
|
||||
impl<E: Engine, S, C: Command<S>> MenuItem<E, S, C> {
|
||||
pub fn sep () -> Self {
|
||||
Self::Separator
|
||||
}
|
||||
pub fn cmd (hotkey: &'static str, text: &'static str, command: C) -> Self {
|
||||
Self::Command(hotkey, text, command)
|
||||
}
|
||||
pub fn off (hotkey: &'static str, text: &'static str) -> Self {
|
||||
Self::Disabled(hotkey, text)
|
||||
|
||||
#[macro_export] macro_rules! event_map_input_to_command {
|
||||
($Engine:ty: $Model:ty: $Command:ty: $EventMap:expr) => {
|
||||
input_to_command!($Command: <$Engine>|state: $Model, input|{
|
||||
event_map!($EventMap).handle(state, input.event())?
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
35
src/event.rs
35
src/event.rs
|
|
@ -1,36 +1 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct EventMap<'a, const N: usize, E, T, U>(
|
||||
pub [(E, &'a dyn Fn(T) -> U); N],
|
||||
pub Option<&'a dyn Fn(T) -> U>,
|
||||
);
|
||||
|
||||
pub type KeyMapping<const N: usize, E, T, U> = [(E, &'static dyn Fn(&T)->U);N];
|
||||
|
||||
impl<'a, const N: usize, E: PartialEq, T, U> EventMap<'a, N, E, T, U> {
|
||||
pub fn handle (&self, context: T, event: &E) -> Option<U> {
|
||||
for (binding, handler) in self.0.iter() {
|
||||
if event == binding {
|
||||
return Some(handler(context))
|
||||
}
|
||||
}
|
||||
return None
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! event_map {
|
||||
($events:expr) => {
|
||||
EventMap($events, None)
|
||||
};
|
||||
($events:expr, $default: expr) => {
|
||||
EventMap($events, $default)
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! event_map_input_to_command {
|
||||
($Engine:ty: $Model:ty: $Command:ty: $EventMap:expr) => {
|
||||
input_to_command!($Command: <$Engine>|state: $Model, input|{
|
||||
event_map!($EventMap).handle(state, input.event())?
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ pub mod border; pub use self::border::*;
|
|||
pub mod clock; pub use self::clock::*;
|
||||
pub mod color; pub use self::color::*;
|
||||
pub mod command; pub use self::command::*;
|
||||
pub mod event; pub use self::event::*;
|
||||
pub mod file; pub use self::file::*;
|
||||
pub mod focus; pub use self::focus::*;
|
||||
pub mod groovebox; pub use self::groovebox::*;
|
||||
|
|
|
|||
63
src/menu.rs
Normal file
63
src/menu.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use crate::*;
|
||||
pub struct MenuBar<E: Engine, S, C: Command<S>> {
|
||||
pub menus: Vec<Menu<E, S, C>>,
|
||||
pub index: usize,
|
||||
}
|
||||
impl<E: Engine, S, C: Command<S>> MenuBar<E, S, C> {
|
||||
pub fn new () -> Self { Self { menus: vec![], index: 0 } }
|
||||
pub fn add (mut self, menu: Menu<E, S, C>) -> Self {
|
||||
self.menus.push(menu);
|
||||
self
|
||||
}
|
||||
}
|
||||
pub struct Menu<E: Engine, S, C: Command<S>> {
|
||||
pub title: String,
|
||||
pub items: Vec<MenuItem<E, S, C>>,
|
||||
pub index: Option<usize>,
|
||||
}
|
||||
impl<E: Engine, S, C: Command<S>> Menu<E, S, C> {
|
||||
pub fn new (title: impl AsRef<str>) -> Self {
|
||||
Self {
|
||||
title: title.as_ref().to_string(),
|
||||
items: vec![],
|
||||
index: None,
|
||||
}
|
||||
}
|
||||
pub fn add (mut self, item: MenuItem<E, S, C>) -> Self {
|
||||
self.items.push(item);
|
||||
self
|
||||
}
|
||||
pub fn sep (mut self) -> Self {
|
||||
self.items.push(MenuItem::sep());
|
||||
self
|
||||
}
|
||||
pub fn cmd (mut self, hotkey: &'static str, text: &'static str, command: C) -> Self {
|
||||
self.items.push(MenuItem::cmd(hotkey, text, command));
|
||||
self
|
||||
}
|
||||
pub fn off (mut self, hotkey: &'static str, text: &'static str) -> Self {
|
||||
self.items.push(MenuItem::off(hotkey, text));
|
||||
self
|
||||
}
|
||||
}
|
||||
pub enum MenuItem<E: Engine, S, C: Command<S>> {
|
||||
/// Unused.
|
||||
__(PhantomData<E>, PhantomData<S>),
|
||||
/// A separator. Skip it.
|
||||
Separator,
|
||||
/// A menu item with command, description and hotkey.
|
||||
Command(&'static str, &'static str, C),
|
||||
/// A menu item that can't be activated but has description and hotkey
|
||||
Disabled(&'static str, &'static str)
|
||||
}
|
||||
impl<E: Engine, S, C: Command<S>> MenuItem<E, S, C> {
|
||||
pub fn sep () -> Self {
|
||||
Self::Separator
|
||||
}
|
||||
pub fn cmd (hotkey: &'static str, text: &'static str, command: C) -> Self {
|
||||
Self::Command(hotkey, text, command)
|
||||
}
|
||||
pub fn off (hotkey: &'static str, text: &'static str) -> Self {
|
||||
Self::Disabled(hotkey, text)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue