feat: refactored centered box to diplay in any of 9 areas

This commit is contained in:
Jack Wills
2022-04-28 21:25:27 +00:00
parent d6694e9317
commit 1017850a6c
7 changed files with 202 additions and 57 deletions
+49 -19
View File
@@ -19,6 +19,7 @@ use crate::{
app_error::AppError,
};
use super::gui_state::BoxLocation;
use super::{GuiState, SelectablePanel};
const NAME_TEXT: &str = r#"
@@ -497,7 +498,7 @@ pub fn draw_help_box<B: Backend>(f: &mut Frame<'_, B>) {
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(Color::Black));
let area = centered_info(lines as u16, max_line_width as u16, f.size());
let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::MiddleCentre);
let split_popup = Layout::default()
.direction(Direction::Vertical)
@@ -560,38 +561,67 @@ pub fn draw_error<B: Backend>(f: &mut Frame<'_, B>, error: AppError, seconds: Op
.block(block)
.alignment(Alignment::Center);
let area = centered_info(lines as u16, max_line_width as u16, f.size());
let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::MiddleCentre);
f.render_widget(Clear, area);
f.render_widget(paragraph, area);
}
/// Show info box in bottom right corner
pub fn draw_info<B: Backend>(f: &mut Frame<'_, B>, text: String) {
let block = Block::default()
.title("")
.title_alignment(Alignment::Center)
.borders(Borders::NONE);
// Add a blank line, so that the text is verticall centered
let text = format!("\n{}", text);
let mut max_line_width = 0;
text.lines().into_iter().for_each(|line| {
let width = line.chars().count();
if width > max_line_width {
max_line_width = width;
}
});
let mut lines = text.lines().count();
// Add some horizontal & vertical margins
max_line_width += 8;
lines += 3;
let paragraph = Paragraph::new(text)
.style(Style::default().bg(Color::Blue).fg(Color::White))
.block(block)
.alignment(Alignment::Center);
let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::BottomRight);
f.render_widget(Clear, area);
f.render_widget(paragraph, area);
}
/// draw a box in the center of the screen, based on max line width + number of lines
fn centered_info(number_lines: u16, max_line_width: u16, r: Rect) -> Rect {
fn draw_popup(text_lines: u16, text_width: u16, r: Rect, box_location:BoxLocation) -> Rect {
// This can panic if number_lines or max_line_width is larger than r.height or r.width
let blank_vertical = (r.height - number_lines) / 2;
let blank_horizontal = (r.width - max_line_width) / 2;
let blank_vertical = (r.height - text_lines) / 2;
let blank_horizontal = (r.width - text_width) / 2;
let vertical_constraints = box_location.get_vertical_constraints(blank_vertical, text_lines);
let horizontal_constraints = box_location.get_horizontal_constraints(blank_horizontal, text_width);
let indexes = box_location.get_indexes();
let popup_layout = Layout::default()
.direction(Direction::Vertical)
.constraints(
[
Constraint::Max(blank_vertical),
Constraint::Max(number_lines),
Constraint::Max(blank_vertical),
]
.as_ref(),
vertical_constraints
)
.split(r);
Layout::default()
.direction(Direction::Horizontal)
.constraints(
[
Constraint::Max(blank_horizontal),
Constraint::Max(max_line_width),
Constraint::Max(blank_horizontal),
]
.as_ref(),
horizontal_constraints
)
.split(popup_layout[1])[1]
}
.split(popup_layout[indexes.0])[indexes.1]
}
+92 -14
View File
@@ -1,5 +1,5 @@
use std::{collections::HashMap, fmt};
use tui::layout::Rect;
use tui::layout::{Constraint, Rect};
#[derive(Debug, PartialEq, std::hash::Hash, std::cmp::Eq, Clone, Copy)]
pub enum SelectablePanel {
@@ -7,7 +7,78 @@ pub enum SelectablePanel {
Commands,
Logs,
}
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
pub enum BoxLocation {
TopLeft,
TopCentre,
TopRight,
MiddleLeft,
MiddleCentre,
MiddleRight,
BottomLeft,
BottomCentre,
BottomRight,
}
impl BoxLocation {
pub fn get_indexes(&self) -> (usize, usize) {
match self {
Self::TopLeft => (0, 0),
Self::TopCentre => (0, 1),
Self::TopRight => (0, 2),
Self::MiddleLeft => (1, 0),
Self::MiddleCentre => (1, 1),
Self::MiddleRight => (1, 2),
Self::BottomLeft => (2, 0),
Self::BottomCentre => (2, 1),
Self::BottomRight => (2, 2),
}
}
// Should combine and just return a tupple?
pub fn get_horizontal_constraints(&self, blank_vertical: u16, text_width: u16) -> [Constraint; 3] {
match self {
Self::TopLeft | Self::MiddleLeft | Self::BottomLeft => [
Constraint::Max(text_width),
Constraint::Max(blank_vertical),
Constraint::Max(blank_vertical),
],
Self::TopCentre | Self::MiddleCentre | Self::BottomCentre => [
Constraint::Max(blank_vertical),
Constraint::Max(text_width),
Constraint::Max(blank_vertical),
],
Self::TopRight | Self::MiddleRight | Self::BottomRight => [
Constraint::Max(blank_vertical),
Constraint::Max(blank_vertical),
Constraint::Max(text_width),
],
}
}
pub fn get_vertical_constraints(&self, blank_vertical: u16, number_lines: u16) -> [Constraint; 3] {
match self {
Self::TopLeft | Self::TopCentre | Self::TopRight => [
Constraint::Max(number_lines),
Constraint::Max(blank_vertical),
Constraint::Max(blank_vertical),
],
Self::MiddleLeft | Self::MiddleCentre | Self::MiddleRight => [
Constraint::Max(blank_vertical),
Constraint::Max(number_lines),
Constraint::Max(blank_vertical),
],
Self::BottomLeft | Self::BottomCentre | Self::BottomRight => [
Constraint::Max(blank_vertical),
Constraint::Max(blank_vertical),
Constraint::Max(number_lines),
],
}
}
}
#[derive(Debug, Clone)]
pub enum Loading {
One,
Two,
@@ -34,20 +105,9 @@ impl Loading {
Self::Eight => Self::Nine,
Self::Nine => Self::Ten,
Self::Ten => Self::One,
// Self::Five => Self::One
}
}
}
// "⠋",
// "⠙",
// "⠹",
// "⠸",
// "⠼",
// "⠴",
// "⠦",
// "⠧",
// "⠇",
// "⠏"
impl fmt::Display for Loading {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -92,7 +152,7 @@ impl SelectablePanel {
}
/// Global gui_state, stored in an Arc<Mutex>
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct GuiState {
// Think this should be a BMapTree, so can define order when iterating over potential intersects
// Is an issue if two panels are in the same space, sush as a smaller panel embedded, yet infront of, a larger panel
@@ -101,6 +161,8 @@ pub struct GuiState {
loading: Loading,
pub selected_panel: SelectablePanel,
pub show_help: bool,
// show_info_panel: bool,
pub info_box_text: Option<String>,
}
impl GuiState {
@@ -111,6 +173,8 @@ impl GuiState {
loading: Loading::One,
selected_panel: SelectablePanel::Containers,
show_help: false,
// show_info_panel: false,
info_box_text: None,
}
}
@@ -158,4 +222,18 @@ impl GuiState {
pub fn reset_loading(&mut self) {
self.loading = Loading::One;
}
pub fn set_info_box(&mut self, text: String) {
self.info_box_text = Some(text);
// self.show_info_panel = true;
// Should spawn and after 10 seconds close?
// Need to copy whatever we're doing with parsing logs icon
}
pub fn reset_info_box(&mut self) {
// self.loading = Loading::One;
self.info_box_text = None;
// self.show_info_panel = false;
}
}
+9 -1
View File
@@ -11,6 +11,7 @@ use std::{
sync::{atomic::Ordering, Arc},
};
use tokio::sync::broadcast::Sender;
use tracing::error;
use tui::{
backend::{Backend, CrosstermBackend},
layout::{Constraint, Direction, Layout},
@@ -50,7 +51,7 @@ pub async fn create_ui(
terminal.show_cursor().unwrap();
if let Err(err) = res {
err.disp()
error!(%err);
}
Ok(())
}
@@ -126,6 +127,7 @@ fn ui<B: Backend>(
let log_index = app_data.lock().get_selected_log_index();
let selected_panel = gui_state.lock().selected_panel;
let show_help = gui_state.lock().show_help;
let info_text = gui_state.lock().info_box_text.clone();
let whole_layout = Layout::default()
.direction(Direction::Vertical)
@@ -198,11 +200,17 @@ fn ui<B: Backend>(
show_help,
);
// only draw charts if there are containers
if has_containers {
draw_chart(f, lower_main[1], app_data, log_index);
}
if let Some(info) = info_text {
draw_info(f, info);
}
// Check if error, and show popup if so
if show_help {
draw_help_box(f);