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 { 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 { vec![] } fn update(&mut self, message: Message) -> Vec { if let Some(event) = message.as_ref::() { 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::() { match action { Action::Increment => { self.count += 1; } Action::Decrement => { self.count -= 1; } } } vec![] } fn view(&self) -> Box { 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); }