Automatically hide columns if they do not fit
All checks were successful
Build and deploy / Build container and manifests (push) Successful in 6m4s
All checks were successful
Build and deploy / Build container and manifests (push) Successful in 6m4s
This commit is contained in:
parent
413d9f2157
commit
61d57d6de1
|
@ -1,4 +1,5 @@
|
|||
#![feature(let_chains)]
|
||||
#![feature(iter_intersperse)]
|
||||
mod helper;
|
||||
mod io;
|
||||
pub mod ldap;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::cmp::{self, max};
|
||||
use std::io::Write as _;
|
||||
use std::iter::once;
|
||||
use std::time::Duration;
|
||||
|
||||
use futures::StreamExt;
|
||||
|
@ -37,6 +38,42 @@ struct RendererInner {
|
|||
rx: UnboundedReceiver<Message>,
|
||||
}
|
||||
|
||||
fn compute_widths(rows: &Vec<Vec<Span<'static>>>) -> Vec<u16> {
|
||||
let table_header = Tunnel::header();
|
||||
std::iter::once(&table_header)
|
||||
.chain(rows)
|
||||
.map(|row| row.iter().map(|cell| cell.width() as u16))
|
||||
.fold(vec![0; table_header.len()], |acc, row| {
|
||||
acc.into_iter()
|
||||
.zip(row)
|
||||
.map(|v| cmp::max(v.0, v.1))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
fn compute_column_skip(
|
||||
widths: &[u16],
|
||||
column_spacing: u16,
|
||||
highlight_symbol: usize,
|
||||
max_width: u16,
|
||||
) -> (usize, usize) {
|
||||
for pattern in [(7, 0), (4, 0), (4, 1), (4, 2)] {
|
||||
let width: u16 = widths
|
||||
.iter()
|
||||
.take(pattern.0)
|
||||
.skip(pattern.1)
|
||||
.intersperse(&column_spacing)
|
||||
.chain(once(&(highlight_symbol as u16)))
|
||||
.sum();
|
||||
|
||||
if width <= max_width {
|
||||
return pattern;
|
||||
}
|
||||
}
|
||||
|
||||
(4, 3)
|
||||
}
|
||||
|
||||
impl RendererInner {
|
||||
fn new(rx: UnboundedReceiver<Message>) -> Self {
|
||||
Self {
|
||||
|
@ -109,22 +146,6 @@ impl RendererInner {
|
|||
(height as u16, Paragraph::new(text).centered().block(block))
|
||||
}
|
||||
|
||||
fn compute_widths(&mut self, rows: &Vec<Vec<Span<'static>>>) -> Vec<Constraint> {
|
||||
let table_header = Tunnel::header();
|
||||
std::iter::once(&table_header)
|
||||
.chain(rows)
|
||||
.map(|row| row.iter().map(|cell| cell.width() as u16))
|
||||
.fold(vec![0; table_header.len()], |acc, row| {
|
||||
acc.into_iter()
|
||||
.zip(row)
|
||||
.map(|v| cmp::max(v.0, v.1))
|
||||
.collect()
|
||||
})
|
||||
.into_iter()
|
||||
.map(|c| Constraint::Length(c + 1))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn render(&mut self, frame: &mut Frame) {
|
||||
self.render_title(frame, frame.area());
|
||||
|
||||
|
@ -153,15 +174,41 @@ impl RendererInner {
|
|||
let highlight_style = Style::default().bold();
|
||||
let header_style = Style::default().bold().reversed();
|
||||
let row_style = Style::default();
|
||||
let highlight_symbol = Line::from("> ");
|
||||
let column_spacing = 3;
|
||||
|
||||
let r = self
|
||||
let rows = self
|
||||
.rows
|
||||
.iter()
|
||||
.map(From::from)
|
||||
.collect::<Vec<Vec<Span<'static>>>>();
|
||||
|
||||
let rows = r.iter().map(|row| {
|
||||
let widths = compute_widths(&rows);
|
||||
let (take, skip) = compute_column_skip(
|
||||
&widths,
|
||||
column_spacing,
|
||||
highlight_symbol.width(),
|
||||
rect.width,
|
||||
);
|
||||
|
||||
let constraints: Vec<_> = widths
|
||||
.into_iter()
|
||||
.take(take)
|
||||
.enumerate()
|
||||
.map(|(index, width)| {
|
||||
if index == 3 {
|
||||
Constraint::Min(width)
|
||||
} else {
|
||||
Constraint::Length(width)
|
||||
}
|
||||
})
|
||||
.skip(skip)
|
||||
.collect();
|
||||
|
||||
let rows = rows.iter().map(|row| {
|
||||
row.iter()
|
||||
.take(take)
|
||||
.skip(skip)
|
||||
.cloned()
|
||||
.map(Cell::from)
|
||||
.collect::<Row>()
|
||||
|
@ -171,6 +218,8 @@ impl RendererInner {
|
|||
|
||||
let header = Tunnel::header()
|
||||
.iter()
|
||||
.take(take)
|
||||
.skip(skip)
|
||||
.cloned()
|
||||
.map(Cell::from)
|
||||
.collect::<Row>()
|
||||
|
@ -181,10 +230,10 @@ impl RendererInner {
|
|||
.header(header)
|
||||
.rows(rows)
|
||||
.flex(Flex::Start)
|
||||
.column_spacing(3)
|
||||
.widths(self.compute_widths(&r))
|
||||
.column_spacing(column_spacing)
|
||||
.widths(&constraints)
|
||||
.row_highlight_style(highlight_style)
|
||||
.highlight_symbol(Line::from("> "))
|
||||
.highlight_symbol(highlight_symbol)
|
||||
.highlight_spacing(HighlightSpacing::Always);
|
||||
|
||||
frame.render_stateful_widget(t, rect, &mut self.state);
|
||||
|
|
|
@ -9,8 +9,8 @@ use crate::io::Stats;
|
|||
|
||||
pub struct TunnelRow {
|
||||
name: Span<'static>,
|
||||
access: Span<'static>,
|
||||
port: Span<'static>,
|
||||
access: Span<'static>,
|
||||
address: Span<'static>,
|
||||
stats: Arc<Stats>,
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ impl From<&TunnelRow> for Vec<Span<'static>> {
|
|||
fn from(row: &TunnelRow) -> Self {
|
||||
vec![
|
||||
row.name.clone(),
|
||||
row.access.clone(),
|
||||
row.port.clone(),
|
||||
row.access.clone(),
|
||||
row.address.clone(),
|
||||
row.stats.connections().to_string().into(),
|
||||
row.stats.rx().to_string().into(),
|
||||
|
@ -33,8 +33,8 @@ impl Tunnel {
|
|||
pub fn header() -> Vec<Span<'static>> {
|
||||
vec![
|
||||
"Name".into(),
|
||||
"Access".into(),
|
||||
"Port".into(),
|
||||
"Access".into(),
|
||||
"Address".into(),
|
||||
"Conn".into(),
|
||||
"Rx".into(),
|
||||
|
@ -56,8 +56,8 @@ impl Tunnel {
|
|||
|
||||
TunnelRow {
|
||||
name: tunnel.registry_entry.get_name().to_string().into(),
|
||||
access,
|
||||
port: tunnel.inner.port.to_string().into(),
|
||||
access,
|
||||
address,
|
||||
stats: tunnel.inner.stats.clone(),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user