use ratatui::{ Frame, layout::{Constraint, Direction, Layout, Rect}, style::Stylize, text::Line, widgets::{Block, Borders, List, ListItem}, }; use crate::App; // helper function to create a centered rect using up certain percentage of the // available rect `r` fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect { // Cut the given rectangle into three vertical pieces let popup_layout = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Percentage((100 - percent_y) / 2), Constraint::Percentage(percent_y), Constraint::Percentage((100 - percent_y) / 2), ]) .split(r); // Then cut the middle vertical piece into three width-wise pieces Layout::default() .direction(Direction::Horizontal) .constraints([ Constraint::Percentage((100 - percent_x) / 2), Constraint::Percentage(percent_x), Constraint::Percentage((100 - percent_x) / 2), ]) .split(popup_layout[1])[1] // Return the middle chunk } impl App { pub fn draw(&self, frame: &mut Frame) { let [top, middle, bottom] = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Min(3), Constraint::Min(3), Constraint::Min(3)]) .split(frame.area()) .as_array() .cloned() .unwrap(); let [footer_left, footer_right] = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) .split(bottom) .as_array() .cloned() .unwrap(); frame.render_widget(self, frame.area()); network_info(frame, footer_left); peers(&self.peers, frame, footer_right); } } fn peers(peers: &crate::Peers, frame: &mut Frame, area: Rect) { let mut items = Vec::with_capacity(peers.len()); for (k, v) in peers.iter() { let item = format!("{:?}: {} ({})", k, v.0, v.1); let s = Line::from(item.yellow()); let item = ListItem::new(s); items.push(item); } let block = Block::default().title("Peers").borders(Borders::all()); let list = List::new(items).block(block); frame.render_widget(list, area); } fn network_info(frame: &mut Frame, area: Rect) { let udp: Line = format!("UDP socket: {:?}", joecalsend::LISTENING_SOCKET_ADDR) .yellow() .into(); let multicast: Line = format!( "Multicast address: {:?}:{}", joecalsend::MULTICAST_IP, joecalsend::DEFAULT_PORT ) .yellow() .into(); let http: Line = format!("HTTP address: {:?}", joecalsend::LISTENING_SOCKET_ADDR) .yellow() .into(); let items = [ ListItem::new(udp), ListItem::new(multicast), ListItem::new(http), ]; let block = Block::default().title("Listeners").borders(Borders::all()); let list = List::new(items).block(block); frame.render_widget(list, area); }