|
|
@@ -1,5 +1,9 @@
|
|
|
+use std::cmp::max;
|
|
|
+use std::collections::hash_map::Iter;
|
|
|
+
|
|
|
+use ratatui::layout::{Constraint, Direction, Layout};
|
|
|
use ratatui::text::Span;
|
|
|
-use ratatui::widgets::{List, ListItem};
|
|
|
+use ratatui::widgets::{BarChart, List, ListItem};
|
|
|
use ratatui::{
|
|
|
backend::Backend,
|
|
|
layout::Alignment,
|
|
|
@@ -43,19 +47,8 @@ fn get_lump_style(lump: &LumpInfo) -> Style {
|
|
|
style
|
|
|
}
|
|
|
|
|
|
-/// Renders the user interface widgets.
|
|
|
-pub fn render<B: Backend>(app: &mut App, frame: &mut Frame<'_, B>) {
|
|
|
- // This is where you add new widgets.
|
|
|
- // See the following resources:
|
|
|
- // - https://docs.rs/ratatui/latest/ratatui/widgets/index.html
|
|
|
- // - https://github.com/tui-rs-revival/ratatui/tree/master/examples
|
|
|
-
|
|
|
- let mut list_size = frame.size();
|
|
|
- list_size.width = 18;
|
|
|
-
|
|
|
- let items: Vec<ListItem> = app
|
|
|
- .lumps
|
|
|
- .items
|
|
|
+fn compute_lump_list(lumps: &[LumpInfo]) -> (Vec<ListItem>, u16) {
|
|
|
+ let lump_items: Vec<ListItem> = lumps
|
|
|
.iter()
|
|
|
.map(|lump| {
|
|
|
ListItem::new(Line::from(Line::from(vec![
|
|
|
@@ -64,8 +57,53 @@ pub fn render<B: Backend>(app: &mut App, frame: &mut Frame<'_, B>) {
|
|
|
])))
|
|
|
})
|
|
|
.collect();
|
|
|
+ let item_width = 1 + lump_items
|
|
|
+ .iter()
|
|
|
+ .fold(0, |acc, item| max(acc, item.width() as u16));
|
|
|
+
|
|
|
+ (lump_items, item_width)
|
|
|
+}
|
|
|
+
|
|
|
+fn compute_size_list(sizes: Iter<'_, Option<LumpType>, usize>) -> (Vec<ListItem>, u16) {
|
|
|
+ let lump_items: Vec<ListItem> = sizes
|
|
|
+ .map(|(file_type, size)| {
|
|
|
+ let type_str = match file_type {
|
|
|
+ Some(file_type) => file_type.to_ui_string(),
|
|
|
+ None => "- Untyped -".into(),
|
|
|
+ };
|
|
|
+ ListItem::new(Line::from(Line::from(vec![
|
|
|
+ Span::styled(format!("{:16}", type_str), Style::default()),
|
|
|
+ Span::styled(format!("{:8}", size), Style::default()),
|
|
|
+ ])))
|
|
|
+ })
|
|
|
+ .collect();
|
|
|
+
|
|
|
+ let item_width = 1 + lump_items
|
|
|
+ .iter()
|
|
|
+ .fold(0, |acc, item| max(acc, item.width() as u16));
|
|
|
+
|
|
|
+ (lump_items, item_width)
|
|
|
+}
|
|
|
+
|
|
|
+/// Renders the user interface widgets.
|
|
|
+pub fn render<B: Backend>(app: &mut App, frame: &mut Frame<'_, B>) {
|
|
|
+ let (lump_items, item_width) = compute_lump_list(&app.lumps.items);
|
|
|
+
|
|
|
+ let (size_items, size_width) = compute_size_list(app.sizes.iter());
|
|
|
|
|
|
- let list = List::new(items)
|
|
|
+ let chunks = Layout::default()
|
|
|
+ .direction(Direction::Horizontal)
|
|
|
+ .constraints(
|
|
|
+ [
|
|
|
+ Constraint::Length(item_width),
|
|
|
+ Constraint::Length(size_width),
|
|
|
+ Constraint::Ratio(1, 1),
|
|
|
+ ]
|
|
|
+ .as_ref(),
|
|
|
+ )
|
|
|
+ .split(frame.size());
|
|
|
+
|
|
|
+ let lump_list = List::new(lump_items)
|
|
|
.block(
|
|
|
Block::default()
|
|
|
.title("Files")
|
|
|
@@ -74,7 +112,45 @@ pub fn render<B: Backend>(app: &mut App, frame: &mut Frame<'_, B>) {
|
|
|
.border_type(BorderType::Plain),
|
|
|
)
|
|
|
.highlight_style(Style::default().bg(Color::Cyan))
|
|
|
- .style(Style::default().fg(Color::Cyan).bg(Color::Black));
|
|
|
+ .style(Style::default());
|
|
|
+
|
|
|
+ let sizes_list = List::new(size_items)
|
|
|
+ .block(
|
|
|
+ Block::default()
|
|
|
+ .title("Sizes")
|
|
|
+ .title_alignment(Alignment::Center)
|
|
|
+ .borders(Borders::TOP | Borders::RIGHT)
|
|
|
+ .border_type(BorderType::Plain),
|
|
|
+ )
|
|
|
+ .highlight_style(Style::default().bg(Color::Cyan))
|
|
|
+ .style(Style::default());
|
|
|
+
|
|
|
+ let chart_data: Vec<(String, u64)> = app
|
|
|
+ .sizes
|
|
|
+ .iter()
|
|
|
+ .filter(|(_, size)| *size > &0)
|
|
|
+ .map(|(file_type, size)| {
|
|
|
+ let type_str = match file_type {
|
|
|
+ Some(file_type) => file_type.to_ui_string(),
|
|
|
+ None => "- Untyped -".into(),
|
|
|
+ };
|
|
|
+ (type_str, *size as u64)
|
|
|
+ })
|
|
|
+ .collect();
|
|
|
+ let char_slice: Vec<(&str, u64)> = chart_data
|
|
|
+ .iter()
|
|
|
+ .map(|(string, size)| (string.as_str(), *size))
|
|
|
+ .collect();
|
|
|
+
|
|
|
+ let size_chart = BarChart::default().data(&char_slice).bar_width(8).block(
|
|
|
+ Block::default()
|
|
|
+ .title("Sizes")
|
|
|
+ .title_alignment(Alignment::Center)
|
|
|
+ .borders(Borders::TOP | Borders::RIGHT)
|
|
|
+ .border_type(BorderType::Plain),
|
|
|
+ );
|
|
|
|
|
|
- frame.render_stateful_widget(list, list_size, &mut app.lumps.state)
|
|
|
+ frame.render_stateful_widget(lump_list, chunks[0], &mut app.lumps.state);
|
|
|
+ frame.render_widget(sizes_list, chunks[1]);
|
|
|
+ frame.render_widget(size_chart, chunks[2]);
|
|
|
}
|