/ tui / src / simulator / modifiers.rs
modifiers.rs
  1  use embedded_graphics_simulator::{
  2      OutputSettings, SimulatorDisplay, SimulatorEvent, Window, sdl2::Keycode,
  3  };
  4  use mousefood::{embedded_graphics::geometry, error::Error, prelude::*};
  5  use ratatui::{
  6      Frame, Terminal,
  7      backend::Backend,
  8      style::*,
  9      widgets::{Block, Paragraph, Wrap},
 10  };
 11  use std::{cell::RefCell, rc::Rc};
 12  
 13  fn main() -> Result<(), Error> {
 14      let mut simulator_window = Window::new(
 15          "mousefood simulator",
 16          &OutputSettings {
 17              scale: 4,
 18              ..Default::default()
 19          },
 20      );
 21      simulator_window.set_max_fps(30);
 22  
 23      let mut display = SimulatorDisplay::<Bgr565>::new(geometry::Size::new(128, 64));
 24  
 25      let events: Rc<RefCell<Vec<SimulatorEvent>>> = Rc::new(RefCell::new(Vec::new()));
 26      let events_cb = events.clone();
 27  
 28      let backend_config = EmbeddedBackendConfig {
 29          flush_callback: Box::new(move |display| {
 30              simulator_window.update(display);
 31              let mut ev = events_cb.borrow_mut();
 32              ev.clear();
 33              ev.extend(simulator_window.events());
 34          }),
 35          color_theme: ColorTheme::tokyo_night(),
 36          ..Default::default()
 37      };
 38      let backend: EmbeddedBackend<SimulatorDisplay<_>, _> =
 39          EmbeddedBackend::new(&mut display, backend_config);
 40  
 41      let mut terminal = Terminal::new(backend)?;
 42      let mut cursor_x: u16 = 1;
 43      let mut cursor_y: u16 = 1;
 44  
 45      loop {
 46          terminal.draw(|frame| draw(frame, cursor_x, cursor_y))?;
 47  
 48          for event in events.borrow().iter() {
 49              match event {
 50                  SimulatorEvent::KeyDown { keycode, .. } => match *keycode {
 51                      Keycode::Up | Keycode::W => {
 52                          cursor_y = cursor_y.saturating_sub(1);
 53                      }
 54                      Keycode::Down | Keycode::S => {
 55                          cursor_y = cursor_y.saturating_add(1);
 56                      }
 57                      Keycode::Left | Keycode::A => {
 58                          cursor_x = cursor_x.saturating_sub(1);
 59                      }
 60                      Keycode::Right | Keycode::D => {
 61                          cursor_x = cursor_x.saturating_add(1);
 62                      }
 63                      _ => {}
 64                  },
 65                  SimulatorEvent::Quit => return Ok(()),
 66                  _ => {}
 67              }
 68          }
 69  
 70          if let Ok(size) = terminal.backend_mut().size() {
 71              cursor_x = cursor_x.min(size.width.saturating_sub(1));
 72              cursor_y = cursor_y.min(size.height.saturating_sub(1));
 73          }
 74      }
 75  }
 76  
 77  fn draw(frame: &mut Frame, cursor_x: u16, cursor_y: u16) {
 78      use ratatui::{
 79          style::Modifier,
 80          text::{Line, Span},
 81      };
 82  
 83      let line = Line::from(vec![
 84          Span::styled(format!("F:{} ", frame.count()), Style::new().yellow()),
 85          Span::styled("RED ", Style::new().fg(Color::Red)),
 86          Span::styled(
 87              "DIM ",
 88              Style::new().fg(Color::Red).add_modifier(Modifier::DIM),
 89          ),
 90          Span::styled("UNDR ", Style::new().add_modifier(Modifier::UNDERLINED)),
 91          Span::styled("SLOW ", Style::new().add_modifier(Modifier::SLOW_BLINK)),
 92          Span::styled("FAST ", Style::new().add_modifier(Modifier::RAPID_BLINK)),
 93          Span::styled("REV ", Style::new().add_modifier(Modifier::REVERSED)),
 94          Span::styled("HIDE ", Style::new().add_modifier(Modifier::HIDDEN)),
 95          Span::styled("XOUT ", Style::new().add_modifier(Modifier::CROSSED_OUT)),
 96          Span::styled(
 97              "D+U ",
 98              Style::new().add_modifier(Modifier::DIM | Modifier::UNDERLINED),
 99          ),
100          // combos
101          Span::styled(
102              "GHOST ",
103              Style::new()
104                  .fg(Color::DarkGray)
105                  .add_modifier(Modifier::DIM | Modifier::ITALIC),
106          ),
107          Span::styled(
108              "ALARM ",
109              Style::new()
110                  .fg(Color::Red)
111                  .add_modifier(Modifier::RAPID_BLINK | Modifier::REVERSED),
112          ),
113          Span::styled(
114              "DEAD ",
115              Style::new()
116                  .fg(Color::Gray)
117                  .add_modifier(Modifier::CROSSED_OUT | Modifier::DIM),
118          ),
119          Span::styled(
120              "SHOUT ",
121              Style::new()
122                  .fg(Color::Yellow)
123                  .add_modifier(Modifier::BOLD | Modifier::UNDERLINED),
124          ),
125          Span::styled(
126              "HAUNT ",
127              Style::new()
128                  .fg(Color::Magenta)
129                  .add_modifier(Modifier::SLOW_BLINK | Modifier::DIM),
130          ),
131          Span::styled(
132              "CRIT",
133              Style::new()
134                  .fg(Color::White)
135                  .bg(Color::Red)
136                  .add_modifier(Modifier::BOLD | Modifier::RAPID_BLINK),
137          ),
138      ]);
139  
140      let paragraph = Paragraph::new(vec![line]).wrap(Wrap { trim: true });
141      let bordered_block = Block::bordered()
142          .border_style(Style::new().yellow())
143          .title("Mods");
144      frame.render_widget(paragraph.block(bordered_block), frame.area());
145      frame.set_cursor_position((cursor_x, cursor_y));
146  }