app.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. use std::error;
  2. use rand::{distributions::Uniform, prelude::Distribution, rngs::ThreadRng};
  3. use ratatui::widgets::ListState;
  4. /// Application result type.
  5. pub type AppResult<T> = std::result::Result<T, Box<dyn error::Error>>;
  6. /// Application.
  7. #[derive(Debug)]
  8. pub struct App<'a> {
  9. /// APP的标题
  10. pub title: &'a str,
  11. /// Is the application running?
  12. pub running: bool,
  13. pub enhanced_graphics: bool,
  14. /// counter
  15. pub counter: u8,
  16. pub tabs: TabsState<'a>,
  17. pub memory_log_sparkline: Signal<RandomSignal>,
  18. logs: Vec<String>,
  19. pub stateful_logs: StatefulList<(&'a str, &'a str)>,
  20. backend_log_receiver: Option<std::sync::mpsc::Receiver<String>>,
  21. }
  22. impl<'a> App<'a> {
  23. /// Constructs a new instance of [`App`].
  24. pub fn new(title: &'a str) -> Self {
  25. let mut rand_signal = RandomSignal::new(0, 100);
  26. let sparkline_points = rand_signal.by_ref().take(300).collect();
  27. let sparkline = Signal {
  28. source: rand_signal,
  29. points: sparkline_points,
  30. tick_rate: 1,
  31. };
  32. Self {
  33. title,
  34. running: true,
  35. enhanced_graphics: true,
  36. counter: 0,
  37. tabs: TabsState::new(vec!["Tab0", "Tab1", "Tab2"]),
  38. memory_log_sparkline: sparkline,
  39. logs: Vec::new(),
  40. stateful_logs: StatefulList::with_items(vec![]),
  41. backend_log_receiver: None,
  42. }
  43. }
  44. pub fn set_backend_log_receiver(&mut self, receiver: std::sync::mpsc::Receiver<String>) {
  45. self.backend_log_receiver = Some(receiver);
  46. }
  47. /// Handles the tick event of the terminal.
  48. pub fn tick(&mut self) {
  49. self.memory_log_sparkline.on_tick();
  50. self.handle_logs_on_tick();
  51. }
  52. /// 当到达tick时,处理日志
  53. fn handle_logs_on_tick(&mut self) {
  54. let logs_to_push = self
  55. .backend_log_receiver
  56. .as_ref()
  57. .map(|rv| rv.try_iter().collect::<Vec<String>>());
  58. if let Some(logs) = logs_to_push {
  59. for log in logs {
  60. self.push_log(log);
  61. }
  62. }
  63. }
  64. /// Set running to false to quit the application.
  65. pub fn quit(&mut self) {
  66. self.running = false;
  67. }
  68. pub fn increment_counter(&mut self) {
  69. if let Some(res) = self.counter.checked_add(1) {
  70. self.counter = res;
  71. }
  72. }
  73. pub fn decrement_counter(&mut self) {
  74. if let Some(res) = self.counter.checked_sub(1) {
  75. self.counter = res;
  76. }
  77. }
  78. pub fn push_log(&mut self, log: String) {
  79. self.logs.push(log);
  80. }
  81. pub fn logs(&self) -> &Vec<String> {
  82. &self.logs
  83. }
  84. }
  85. #[derive(Debug)]
  86. pub struct TabsState<'a> {
  87. pub titles: Vec<&'a str>,
  88. pub index: usize,
  89. }
  90. impl<'a> TabsState<'a> {
  91. pub fn new(titles: Vec<&'a str>) -> TabsState {
  92. TabsState { titles, index: 0 }
  93. }
  94. pub fn next(&mut self) {
  95. self.index = (self.index + 1) % self.titles.len();
  96. }
  97. pub fn previous(&mut self) {
  98. if self.index > 0 {
  99. self.index -= 1;
  100. } else {
  101. self.index = self.titles.len() - 1;
  102. }
  103. }
  104. }
  105. #[derive(Clone, Debug)]
  106. pub struct Signal<S: Iterator> {
  107. source: S,
  108. pub points: Vec<S::Item>,
  109. tick_rate: usize,
  110. }
  111. impl<S> Signal<S>
  112. where
  113. S: Iterator,
  114. {
  115. fn on_tick(&mut self) {
  116. for _ in 0..self.tick_rate {
  117. self.points.remove(0);
  118. }
  119. self.points
  120. .extend(self.source.by_ref().take(self.tick_rate));
  121. }
  122. }
  123. #[derive(Clone, Debug)]
  124. pub struct RandomSignal {
  125. distribution: Uniform<u64>,
  126. rng: ThreadRng,
  127. }
  128. impl RandomSignal {
  129. pub fn new(lower: u64, upper: u64) -> RandomSignal {
  130. RandomSignal {
  131. distribution: Uniform::new(lower, upper),
  132. rng: rand::thread_rng(),
  133. }
  134. }
  135. }
  136. impl Iterator for RandomSignal {
  137. type Item = u64;
  138. fn next(&mut self) -> Option<u64> {
  139. Some(self.distribution.sample(&mut self.rng))
  140. }
  141. }
  142. #[derive(Debug)]
  143. pub struct StatefulList<T> {
  144. pub state: ListState,
  145. pub items: Vec<T>,
  146. }
  147. impl<T> StatefulList<T> {
  148. pub fn with_items(items: Vec<T>) -> StatefulList<T> {
  149. StatefulList {
  150. state: ListState::default(),
  151. items,
  152. }
  153. }
  154. pub fn next(&mut self) {
  155. let i = match self.state.selected() {
  156. Some(i) => {
  157. if i >= self.items.len() - 1 {
  158. 0
  159. } else {
  160. i + 1
  161. }
  162. }
  163. None => 0,
  164. };
  165. self.state.select(Some(i));
  166. }
  167. pub fn previous(&mut self) {
  168. let i = match self.state.selected() {
  169. Some(i) => {
  170. if i == 0 {
  171. self.items.len() - 1
  172. } else {
  173. i - 1
  174. }
  175. }
  176. None => 0,
  177. };
  178. self.state.select(Some(i));
  179. }
  180. }