ui.rs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. use crate::view::View;
  2. //use log::debug;
  3. use tui::{
  4. backend::Backend,
  5. layout::{Alignment, Constraint, Direction, Layout, Rect},
  6. style::Style,
  7. text::{Span, Spans},
  8. widgets::{Block, Borders, List, ListItem, Paragraph},
  9. Frame,
  10. };
  11. pub fn ui<B: Backend>(f: &mut Frame<'_, B>, mut view: View) {
  12. let slice = Layout::default()
  13. .direction(Direction::Horizontal)
  14. .margin(2)
  15. .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
  16. .split(f.size());
  17. let nodes: Vec<ListItem> = view
  18. .id_list
  19. .node_id
  20. .iter()
  21. .map(|id| {
  22. let lines = vec![Spans::from(id.to_string())];
  23. ListItem::new(lines).style(Style::default())
  24. })
  25. .collect();
  26. let nodes =
  27. List::new(nodes).block(Block::default().borders(Borders::ALL)).highlight_symbol(">> ");
  28. f.render_stateful_widget(nodes, slice[0], &mut view.id_list.state);
  29. let index = view.info_list.index;
  30. render_info_left(view.clone(), f);
  31. render_info_right(view.clone(), f, index, slice);
  32. }
  33. fn render_info_left<B: Backend>(view: View, f: &mut Frame<'_, B>) {
  34. let length = render_outbound(view.clone(), f);
  35. let length = render_inbound(view.clone(), f, length);
  36. render_manual(view.clone(), f, length);
  37. }
  38. fn render_manual<B: Backend>(view: View, f: &mut Frame<'_, B>, length: usize) {
  39. let new_num: u16 = length.try_into().unwrap();
  40. let title_slice = Layout::default()
  41. .direction(Direction::Horizontal)
  42. .horizontal_margin(8)
  43. .vertical_margin(new_num)
  44. .constraints([Constraint::Percentage(100)].as_ref())
  45. .split(f.size());
  46. let info_slice = Layout::default()
  47. .direction(Direction::Horizontal)
  48. .horizontal_margin(10)
  49. .vertical_margin(new_num)
  50. .constraints([Constraint::Percentage(45), Constraint::Percentage(55)].as_ref())
  51. .split(f.size());
  52. let info = &view.info_list.infos;
  53. let mut title = Vec::new();
  54. for id in &view.id_list.node_id {
  55. match info.get(id) {
  56. Some(_) => {
  57. title.push(Spans::from(Span::styled("Manual:", Style::default())));
  58. }
  59. None => {
  60. // TODO
  61. }
  62. }
  63. }
  64. let mut man_info = Vec::new();
  65. for id in &view.id_list.node_id {
  66. match info.get(id) {
  67. Some(connects) => {
  68. man_info.push(Spans::from(""));
  69. man_info.push(Spans::from(format!("Key: {}", connects.manual[0].key)));
  70. man_info.push(Spans::from(""));
  71. }
  72. None => {
  73. // TODO
  74. }
  75. }
  76. }
  77. let info_graph = Paragraph::new(man_info).style(Style::default()).alignment(Alignment::Left);
  78. let title_graph = Paragraph::new(title).style(Style::default()).alignment(Alignment::Left);
  79. f.render_widget(info_graph, info_slice[0]);
  80. f.render_widget(title_graph, title_slice[0]);
  81. }
  82. fn render_inbound<B: Backend>(view: View, f: &mut Frame<'_, B>, length: usize) -> usize {
  83. let mut inbound_info = Vec::new();
  84. // TODO: find better way of doing this
  85. let new_num: u16 = length.try_into().unwrap();
  86. let num = new_num + 3;
  87. let title_slice = Layout::default()
  88. .direction(Direction::Horizontal)
  89. .horizontal_margin(8)
  90. .vertical_margin(num)
  91. .constraints([Constraint::Percentage(100)].as_ref())
  92. .split(f.size());
  93. let info_slice = Layout::default()
  94. .direction(Direction::Horizontal)
  95. .horizontal_margin(10)
  96. .vertical_margin(num)
  97. .constraints([Constraint::Percentage(45), Constraint::Percentage(55)].as_ref())
  98. .split(f.size());
  99. let info = &view.info_list.infos;
  100. let mut title = Vec::new();
  101. for id in &view.id_list.node_id {
  102. match info.get(id) {
  103. Some(_) => {
  104. title.push(Spans::from(Span::styled("Inbound:", Style::default())));
  105. }
  106. None => {
  107. // TODO
  108. }
  109. }
  110. }
  111. for id in &view.id_list.node_id {
  112. match info.get(id) {
  113. Some(connects) => {
  114. if connects.inbound.is_empty() {
  115. inbound_info.push(Spans::from(""));
  116. inbound_info.push(Spans::from(format!("Connected: Null")));
  117. inbound_info.push(Spans::from(format!("Last msg: Null")));
  118. inbound_info.push(Spans::from(format!("Last status: Null")));
  119. } else {
  120. for connect in &connects.inbound {
  121. inbound_info.push(Spans::from(""));
  122. inbound_info.push(Spans::from(format!("Connected: {}", connect.connected)));
  123. inbound_info
  124. .push(Spans::from(format!("Last msg: {}", connect.channel.last_msg)));
  125. inbound_info.push(Spans::from(format!(
  126. "Last status: {}",
  127. connect.channel.last_status
  128. )));
  129. }
  130. }
  131. }
  132. None => {
  133. // TODO
  134. }
  135. }
  136. }
  137. for _n in 1..info.len() {
  138. inbound_info.push(Spans::from(""))
  139. }
  140. let info_graph =
  141. Paragraph::new(inbound_info.clone()).style(Style::default()).alignment(Alignment::Left);
  142. let title_graph =
  143. Paragraph::new(title.clone()).style(Style::default()).alignment(Alignment::Left);
  144. f.render_widget(info_graph, info_slice[0]);
  145. f.render_widget(title_graph, title_slice[0]);
  146. return inbound_info.len() + title.len() + length + 2
  147. }
  148. fn render_outbound<B: Backend>(view: View, f: &mut Frame<'_, B>) -> usize {
  149. let title_slice = Layout::default()
  150. .direction(Direction::Horizontal)
  151. .horizontal_margin(8)
  152. .vertical_margin(4)
  153. .constraints([Constraint::Percentage(100)].as_ref())
  154. .split(f.size());
  155. let info_slice = Layout::default()
  156. .direction(Direction::Horizontal)
  157. .horizontal_margin(10)
  158. .vertical_margin(4)
  159. .constraints([Constraint::Percentage(45), Constraint::Percentage(55)].as_ref())
  160. .split(f.size());
  161. let info = &view.info_list.infos;
  162. let mut title = Vec::new();
  163. for id in &view.id_list.node_id {
  164. match info.get(id) {
  165. Some(_) => {
  166. title.push(Spans::from(Span::styled("Outbound:", Style::default())));
  167. }
  168. None => {
  169. // TODO
  170. }
  171. }
  172. }
  173. let mut slots = Vec::new();
  174. for id in &view.id_list.node_id {
  175. match info.get(id) {
  176. Some(connects) => {
  177. for slot in &connects.outbound[0].slots {
  178. slots.push(Spans::from(""));
  179. slots.push(Spans::from(format!("Addr: {}", slot.addr)));
  180. slots.push(Spans::from(format!("Last msg: {}", slot.channel.last_msg)));
  181. slots.push(Spans::from(format!("Last status: {}", slot.channel.last_status)));
  182. }
  183. }
  184. None => {
  185. // TODO
  186. }
  187. }
  188. }
  189. for _n in 1..info.len() {
  190. slots.push(Spans::from(""))
  191. }
  192. let info_graph =
  193. Paragraph::new(slots.clone()).style(Style::default()).alignment(Alignment::Left);
  194. let title_graph =
  195. Paragraph::new(title.clone()).style(Style::default()).alignment(Alignment::Left);
  196. f.render_widget(info_graph, info_slice[0]);
  197. f.render_widget(title_graph, title_slice[0]);
  198. let out_len = slots.len() + title.len();
  199. return out_len
  200. }
  201. fn render_info_right<B: Backend>(
  202. _view: View,
  203. f: &mut Frame<'_, B>,
  204. _index: usize,
  205. slice: Vec<Rect>,
  206. ) {
  207. let span = vec![];
  208. let graph =
  209. Paragraph::new(span).block(Block::default().borders(Borders::ALL)).style(Style::default());
  210. f.render_widget(graph, slice[1]);
  211. }