ulmus 0.5.0

An Elm architecture TUI framework
Documentation
use crossterm::event::{Event, KeyCode, MouseEventKind};
use ulmus::{
	widget::{Border, Flexbox, Size, Text, Widget},
	Command, Message, Model, Program,
};

struct Counter {
	count: i64,
}

impl Counter {
	fn new(count: i64) -> Counter {
		Counter { count }
	}
}

#[derive(Clone, Copy)]
enum Action {
	Increment,
	Decrement,
}

fn button(title: &str, action: Action) -> Box<dyn Widget> {
	Border::new(
		Text::new(title).on_mouse(move |message| {
			if matches!(message.kind, MouseEventKind::Down(_)) {
				Message::new(action)
			} else {
				Message::empty()
			}
		}),
		"-".to_owned(),
		"-".to_owned(),
		"|".to_owned(),
		"|".to_owned(),
		"+".to_owned(),
		"+".to_owned(),
		"+".to_owned(),
		"+".to_owned(),
	)
	.forward(true)
}

impl Model for Counter {
	fn init(&self) -> Vec<Command> {
		vec![]
	}

	fn update(&mut self, message: Message) -> Vec<Command> {
		if let Some(event) = message.as_ref::<Event>() {
			match event {
				Event::Key(key_event) => match key_event.code {
					KeyCode::Char('+') => {
						self.count += 1;
					}
					KeyCode::Char('-') => {
						self.count -= 1;
					}
					KeyCode::Esc => {
						return vec![Command::Quit];
					}
					_ => {}
				},
				_ => {}
			}
		}
		if let Some(action) = message.as_ref::<Action>() {
			match action {
				Action::Increment => {
					self.count += 1;
				}
				Action::Decrement => {
					self.count -= 1;
				}
			}
		}

		vec![]
	}

	fn view(&self) -> Box<dyn Widget> {
		Flexbox::vertical(
			vec![
				Text::new(self.count.to_string()),
				Flexbox::horizontal(
					vec![
						button(
							"Decrement",
							Action::Decrement,
						),
						button(
							"Increment",
							Action::Increment,
						),
					],
					vec![
						Size::Length(20),
						Size::Length(20),
					],
				),
			],
			vec![Size::Length(2), Size::Length(3)],
		)
	}
}

fn main() {
	let mut model = Counter::new(0);

	let program = Program::default().enable_mouse();

	program.run(&mut model).unwrap();

	println!("The counter value on exit was {}", model.count);
}