Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub struct AppConfigFields {
pub network_legend_position: Option<LegendPosition>,
pub network_scale_type: AxisScaling,
pub network_use_binary_prefix: bool,
pub network_show_packets: bool,
pub retention_ms: u64,
pub dedicated_average_row: bool,
pub default_tree_collapse: bool,
Expand Down
10 changes: 8 additions & 2 deletions src/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,14 @@ impl Painter {
mem_rows += data.gpu_harvest.len() as u16; // add row(s) for gpu
}

if mem_rows == 1 {
mem_rows += 1; // need at least 2 rows for RX and TX
let network_rows = if app_state.app_config_fields.network_show_packets {
4 // 4 rows for RX/TX and Packet Rates (Avg sizes moved to right side)
} else {
2 // 2 rows for RX and TX
};

if mem_rows < network_rows {
mem_rows += network_rows - mem_rows; // min rows
}

let vertical_chunks = Layout::default()
Expand Down
273 changes: 244 additions & 29 deletions src/canvas/widgets/network_basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,13 @@ impl Painter {
pub fn draw_basic_network(
&self, f: &mut Frame<'_>, app_state: &mut App, draw_loc: Rect, widget_id: u64,
) {
let divided_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
.split(draw_loc);

let net_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.horizontal_margin(1)
.split(divided_loc[0]);

let total_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.horizontal_margin(1)
.split(divided_loc[1]);
let show_packets = app_state.app_config_fields.network_show_packets;

// Determine if we need grid layout based on available width
// Assume we need at least ~15 chars per column for horizontal layout
// With 4 columns, that's ~60 chars minimum
// If width is less than 60, use grid layout (4 rows x 2 columns)
let use_grid_layout = show_packets && draw_loc.width < 60;

if app_state.current_widget.widget_id == widget_id {
f.render_widget(
Expand All @@ -52,22 +43,246 @@ impl Painter {
let total_rx_label = format!("Total RX: {:.1}{}", total_rx.0, total_rx.1);
let total_tx_label = format!("Total TX: {:.1}{}", total_tx.0, total_tx.1);

let net_text = vec![
Line::from(Span::styled(rx_label, self.styles.rx_style)),
Line::from(Span::styled(tx_label, self.styles.tx_style)),
];
if use_grid_layout {
// 4 rows x 2 columns layout
// Column 1: RX, TX, Total RX, Total TX (top to bottom)
// Column 2: RX Packets, TX Packets, AVG RX, AVG TX (top to bottom)
let grid_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
.split(draw_loc);

// Calculate packet data
let rx_packet_rate = network_data.rx_packets;
let tx_packet_rate = network_data.tx_packets;
let avg_rx_packet_size = if network_data.rx_packets > 0 {
(network_data.rx as f64 / 8.0) / network_data.rx_packets as f64
} else {
0.0
};
let avg_tx_packet_size = if network_data.tx_packets > 0 {
(network_data.tx as f64 / 8.0) / network_data.tx_packets as f64
} else {
0.0
};

// Column 1: RX, TX, Total RX, Total TX
let col1_loc = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(25),
])
.split(grid_loc[0]);
f.render_widget(
Paragraph::new(Line::from(Span::styled(rx_label, self.styles.rx_style)))
.block(Block::default()),
col1_loc[0],
);
f.render_widget(
Paragraph::new(Line::from(Span::styled(tx_label, self.styles.tx_style)))
.block(Block::default()),
col1_loc[1],
);
f.render_widget(
Paragraph::new(Line::from(Span::styled(
total_rx_label,
self.styles.total_rx_style,
)))
.block(Block::default()),
col1_loc[2],
);
f.render_widget(
Paragraph::new(Line::from(Span::styled(
total_tx_label,
self.styles.total_tx_style,
)))
.block(Block::default()),
col1_loc[3],
);

let total_net_text = vec![
Line::from(Span::styled(total_rx_label, self.styles.total_rx_style)),
Line::from(Span::styled(total_tx_label, self.styles.total_tx_style)),
];
// Column 2: RX Packets, TX Packets, AVG RX, AVG TX
let col2_loc = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(25),
])
.split(grid_loc[1]);
f.render_widget(
Paragraph::new(Line::from(Span::styled(
format!("RX Pkt: {} pkt/s", rx_packet_rate),
self.styles.rx_style,
)))
.block(Block::default()),
col2_loc[0],
);
f.render_widget(
Paragraph::new(Line::from(Span::styled(
format!("TX Pkt: {} pkt/s", tx_packet_rate),
self.styles.tx_style,
)))
.block(Block::default()),
col2_loc[1],
);
f.render_widget(
Paragraph::new(Line::from(Span::styled(
format!("Avg RX: {:.1} B", avg_rx_packet_size),
self.styles.total_rx_style,
)))
.block(Block::default()),
col2_loc[2],
);
f.render_widget(
Paragraph::new(Line::from(Span::styled(
format!("Avg TX: {:.1} B", avg_tx_packet_size),
self.styles.total_tx_style,
)))
.block(Block::default()),
col2_loc[3],
);
} else if show_packets {
// Horizontal 4-column layout
let constraints = [
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(25),
Constraint::Percentage(25),
];

f.render_widget(Paragraph::new(net_text).block(Block::default()), net_loc[0]);
let divided_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints(constraints)
.split(draw_loc);

f.render_widget(
Paragraph::new(total_net_text).block(Block::default()),
total_loc[0],
);
// Column 1: RX/TX
let col1_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.horizontal_margin(1)
.split(divided_loc[0]);
let col1_text = vec![
Line::from(Span::styled(rx_label, self.styles.rx_style)),
Line::from(Span::styled(tx_label, self.styles.tx_style)),
];
f.render_widget(
Paragraph::new(col1_text).block(Block::default()),
col1_loc[0],
);

// Column 2: Total RX/TX
let col2_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.horizontal_margin(1)
.split(divided_loc[1]);
let col2_text = vec![
Line::from(Span::styled(total_rx_label, self.styles.total_rx_style)),
Line::from(Span::styled(total_tx_label, self.styles.total_tx_style)),
];
f.render_widget(
Paragraph::new(col2_text).block(Block::default()),
col2_loc[0],
);

// Calculate packet data
let rx_packet_rate = network_data.rx_packets;
let tx_packet_rate = network_data.tx_packets;
let avg_rx_packet_size = if network_data.rx_packets > 0 {
(network_data.rx as f64 / 8.0) / network_data.rx_packets as f64
} else {
0.0
};
let avg_tx_packet_size = if network_data.tx_packets > 0 {
(network_data.tx as f64 / 8.0) / network_data.tx_packets as f64
} else {
0.0
};

// Column 3: RX/TX packets
let col3_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.horizontal_margin(1)
.split(divided_loc[2]);
let col3_text = vec![
Line::from(Span::styled(
format!("RX Pkt: {} pkt/s", rx_packet_rate),
self.styles.rx_style,
)),
Line::from(Span::styled(
format!("TX Pkt: {} pkt/s", tx_packet_rate),
self.styles.tx_style,
)),
];
f.render_widget(
Paragraph::new(col3_text).block(Block::default()),
col3_loc[0],
);

// Column 4: AVG RX/TX packets
let col4_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.horizontal_margin(1)
.split(divided_loc[3]);
let col4_text = vec![
Line::from(Span::styled(
format!("Avg RX: {:.1} B", avg_rx_packet_size),
self.styles.total_rx_style,
)),
Line::from(Span::styled(
format!("Avg TX: {:.1} B", avg_tx_packet_size),
self.styles.total_tx_style,
)),
];
f.render_widget(
Paragraph::new(col4_text).block(Block::default()),
col4_loc[0],
);
} else {
// No packets, 2-column layout
let constraints = [Constraint::Percentage(50), Constraint::Percentage(50)];

let divided_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints(constraints)
.split(draw_loc);

// Column 1: RX/TX
let col1_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.horizontal_margin(1)
.split(divided_loc[0]);
let col1_text = vec![
Line::from(Span::styled(rx_label, self.styles.rx_style)),
Line::from(Span::styled(tx_label, self.styles.tx_style)),
];
f.render_widget(
Paragraph::new(col1_text).block(Block::default()),
col1_loc[0],
);

// Column 2: Total RX/TX
let col2_loc = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(100)])
.horizontal_margin(1)
.split(divided_loc[1]);
let col2_text = vec![
Line::from(Span::styled(total_rx_label, self.styles.total_rx_style)),
Line::from(Span::styled(total_tx_label, self.styles.total_tx_style)),
];
f.render_widget(
Paragraph::new(col2_text).block(Block::default()),
col2_loc[0],
);
}

// Update draw loc in widget map
if app_state.should_get_widget_bounds() {
Expand Down
Loading