123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- use std::error;
- use rand::{distributions::Uniform, prelude::Distribution, rngs::ThreadRng};
- use ratatui::widgets::ListState;
- /// Application result type.
- pub type AppResult<T> = std::result::Result<T, Box<dyn error::Error>>;
- /// Application.
- #[derive(Debug)]
- pub struct App<'a> {
- /// APP的标题
- pub title: &'a str,
- /// Is the application running?
- pub running: bool,
- pub enhanced_graphics: bool,
- /// counter
- pub counter: u8,
- pub tabs: TabsState<'a>,
- pub memory_log_sparkline: Signal<RandomSignal>,
- logs: Vec<String>,
- pub stateful_logs: StatefulList<(&'a str, &'a str)>,
- backend_log_receiver: Option<std::sync::mpsc::Receiver<String>>,
- }
- impl<'a> App<'a> {
- /// Constructs a new instance of [`App`].
- pub fn new(title: &'a str) -> Self {
- let mut rand_signal = RandomSignal::new(0, 100);
- let sparkline_points = rand_signal.by_ref().take(300).collect();
- let sparkline = Signal {
- source: rand_signal,
- points: sparkline_points,
- tick_rate: 1,
- };
- Self {
- title,
- running: true,
- enhanced_graphics: true,
- counter: 0,
- tabs: TabsState::new(vec!["Tab0", "Tab1", "Tab2"]),
- memory_log_sparkline: sparkline,
- logs: Vec::new(),
- stateful_logs: StatefulList::with_items(vec![]),
- backend_log_receiver: None,
- }
- }
- pub fn set_backend_log_receiver(&mut self, receiver: std::sync::mpsc::Receiver<String>) {
- self.backend_log_receiver = Some(receiver);
- }
- /// Handles the tick event of the terminal.
- pub fn tick(&mut self) {
- self.memory_log_sparkline.on_tick();
- self.handle_logs_on_tick();
- }
- /// 当到达tick时,处理日志
- fn handle_logs_on_tick(&mut self) {
- let logs_to_push = self
- .backend_log_receiver
- .as_ref()
- .map(|rv| rv.try_iter().collect::<Vec<String>>());
- if let Some(logs) = logs_to_push {
- for log in logs {
- self.push_log(log);
- }
- }
- }
- /// Set running to false to quit the application.
- pub fn quit(&mut self) {
- self.running = false;
- }
- pub fn increment_counter(&mut self) {
- if let Some(res) = self.counter.checked_add(1) {
- self.counter = res;
- }
- }
- pub fn decrement_counter(&mut self) {
- if let Some(res) = self.counter.checked_sub(1) {
- self.counter = res;
- }
- }
- pub fn push_log(&mut self, log: String) {
- self.logs.push(log);
- }
- pub fn logs(&self) -> &Vec<String> {
- &self.logs
- }
- }
- #[derive(Debug)]
- pub struct TabsState<'a> {
- pub titles: Vec<&'a str>,
- pub index: usize,
- }
- impl<'a> TabsState<'a> {
- pub fn new(titles: Vec<&'a str>) -> TabsState {
- TabsState { titles, index: 0 }
- }
- pub fn next(&mut self) {
- self.index = (self.index + 1) % self.titles.len();
- }
- pub fn previous(&mut self) {
- if self.index > 0 {
- self.index -= 1;
- } else {
- self.index = self.titles.len() - 1;
- }
- }
- }
- #[derive(Clone, Debug)]
- pub struct Signal<S: Iterator> {
- source: S,
- pub points: Vec<S::Item>,
- tick_rate: usize,
- }
- impl<S> Signal<S>
- where
- S: Iterator,
- {
- fn on_tick(&mut self) {
- for _ in 0..self.tick_rate {
- self.points.remove(0);
- }
- self.points
- .extend(self.source.by_ref().take(self.tick_rate));
- }
- }
- #[derive(Clone, Debug)]
- pub struct RandomSignal {
- distribution: Uniform<u64>,
- rng: ThreadRng,
- }
- impl RandomSignal {
- pub fn new(lower: u64, upper: u64) -> RandomSignal {
- RandomSignal {
- distribution: Uniform::new(lower, upper),
- rng: rand::thread_rng(),
- }
- }
- }
- impl Iterator for RandomSignal {
- type Item = u64;
- fn next(&mut self) -> Option<u64> {
- Some(self.distribution.sample(&mut self.rng))
- }
- }
- #[derive(Debug)]
- pub struct StatefulList<T> {
- pub state: ListState,
- pub items: Vec<T>,
- }
- impl<T> StatefulList<T> {
- pub fn with_items(items: Vec<T>) -> StatefulList<T> {
- StatefulList {
- state: ListState::default(),
- items,
- }
- }
- pub fn next(&mut self) {
- let i = match self.state.selected() {
- Some(i) => {
- if i >= self.items.len() - 1 {
- 0
- } else {
- i + 1
- }
- }
- None => 0,
- };
- self.state.select(Some(i));
- }
- pub fn previous(&mut self) {
- let i = match self.state.selected() {
- Some(i) => {
- if i == 0 {
- self.items.len() - 1
- } else {
- i - 1
- }
- }
- None => 0,
- };
- self.state.select(Some(i));
- }
- }
|