refactor: pass &FrameDate into draw_frame()
This commit is contained in:
+10
-10
@@ -478,10 +478,11 @@ impl AppData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get Option of the current selected container's ports, sorted by private port
|
/// Get Option of the current selected container's ports, sorted by private port
|
||||||
pub fn get_selected_ports(&mut self) -> Option<(&[ContainerPorts], State)> {
|
pub fn get_selected_ports(&self) -> Option<(Vec<ContainerPorts>, State)> {
|
||||||
if let Some(item) = self.get_mut_selected_container() {
|
if let Some(item) = self.get_selected_container() {
|
||||||
item.ports.sort_by(|a, b| a.private.cmp(&b.private));
|
let mut ports = item.ports.clone();
|
||||||
return Some((&item.ports, item.state));
|
ports.sort_by(|a, b| a.private.cmp(&b.private));
|
||||||
|
return Some((ports, item.state));
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -646,12 +647,12 @@ impl AppData {
|
|||||||
|
|
||||||
/// Chart data related methods
|
/// Chart data related methods
|
||||||
/// Get mutable Option of the currently selected container chart data
|
/// Get mutable Option of the currently selected container chart data
|
||||||
pub fn get_chart_data(&mut self) -> Option<(CpuTuple, MemTuple)> {
|
pub fn get_chart_data(&self) -> Option<(CpuTuple, MemTuple)> {
|
||||||
self.containers
|
self.containers
|
||||||
.state
|
.state
|
||||||
.selected()
|
.selected()
|
||||||
.and_then(|i| self.containers.items.get_mut(i))
|
.and_then(|i| self.containers.items.get(i))
|
||||||
.map(|i| i.get_chart_data())
|
.map(container_state::ContainerItem::get_chart_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error related methods
|
/// Error related methods
|
||||||
@@ -2180,8 +2181,7 @@ mod tests {
|
|||||||
private: 8001,
|
private: 8001,
|
||||||
public: None
|
public: None
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
.as_slice(),
|
|
||||||
State::Running(RunningState::Healthy),
|
State::Running(RunningState::Healthy),
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
@@ -2193,7 +2193,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
Some((vec![].as_slice(), State::Running(RunningState::Healthy)))
|
Some((vec![], State::Running(RunningState::Healthy)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-28
@@ -64,19 +64,17 @@ impl InputHandler {
|
|||||||
match message {
|
match message {
|
||||||
InputMessages::ButtonPress(key) => self.button_press(key.0, key.1).await,
|
InputMessages::ButtonPress(key) => self.button_press(key.0, key.1).await,
|
||||||
InputMessages::MouseEvent(mouse_event) => {
|
InputMessages::MouseEvent(mouse_event) => {
|
||||||
if !self.gui_state.lock().status_contains(&[
|
let status = self.gui_state.lock().get_status();
|
||||||
Status::Error,
|
let contains = |s: Status| status.contains(&s);
|
||||||
Status::Help,
|
|
||||||
Status::DeleteConfirm,
|
if !contains(Status::Error)
|
||||||
Status::Filter,
|
| !contains(Status::Help)
|
||||||
]) {
|
| !contains(Status::DeleteConfirm)
|
||||||
|
| !contains(Status::Filter)
|
||||||
|
{
|
||||||
self.mouse_press(mouse_event);
|
self.mouse_press(mouse_event);
|
||||||
}
|
}
|
||||||
let delete_confirm = self
|
if contains(Status::DeleteConfirm) {
|
||||||
.gui_state
|
|
||||||
.lock()
|
|
||||||
.status_contains(&[Status::DeleteConfirm]);
|
|
||||||
if delete_confirm {
|
|
||||||
self.button_intersect(mouse_event).await;
|
self.button_intersect(mouse_event).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,11 +90,9 @@ impl InputHandler {
|
|||||||
/// Send a quit message to docker, to abort all spawns, if an error is returned, set is_running to false here instead
|
/// Send a quit message to docker, to abort all spawns, if an error is returned, set is_running to false here instead
|
||||||
/// If gui_status is Error or Init, then just set the is_running to false immediately, for a quicker exit
|
/// If gui_status is Error or Init, then just set the is_running to false immediately, for a quicker exit
|
||||||
fn quit(&self) {
|
fn quit(&self) {
|
||||||
let error_init = self
|
let status = self.gui_state.lock().get_status();
|
||||||
.gui_state
|
let contains = |s: Status| status.contains(&s);
|
||||||
.lock()
|
if !contains(Status::Error) | !contains(Status::Init) {
|
||||||
.status_contains(&[Status::Error, Status::Init]);
|
|
||||||
if !error_init {
|
|
||||||
self.is_running
|
self.is_running
|
||||||
.store(false, std::sync::atomic::Ordering::SeqCst);
|
.store(false, std::sync::atomic::Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
@@ -235,10 +231,11 @@ impl InputHandler {
|
|||||||
|
|
||||||
/// Attempt to save the currently selected container logs to a file
|
/// Attempt to save the currently selected container logs to a file
|
||||||
async fn s_key(&self) {
|
async fn s_key(&self) {
|
||||||
let log_status = Status::Logs;
|
let status = self.gui_state.lock().get_status();
|
||||||
let status = self.gui_state.lock().status_contains(&[log_status]);
|
let contains = |s: Status| status.contains(&s);
|
||||||
if !status {
|
|
||||||
self.gui_state.lock().status_push(log_status);
|
if !contains(Status::Logs) {
|
||||||
|
self.gui_state.lock().status_push(Status::Logs);
|
||||||
let uuid = Uuid::new_v4();
|
let uuid = Uuid::new_v4();
|
||||||
GuiState::start_loading_animation(&self.gui_state, uuid);
|
GuiState::start_loading_animation(&self.gui_state, uuid);
|
||||||
if self.save_logs().await.is_err() {
|
if self.save_logs().await.is_err() {
|
||||||
@@ -248,7 +245,7 @@ impl InputHandler {
|
|||||||
Status::Error,
|
Status::Error,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.gui_state.lock().status_del(log_status);
|
self.gui_state.lock().status_del(Status::Logs);
|
||||||
self.gui_state.lock().stop_loading_animation(uuid);
|
self.gui_state.lock().stop_loading_animation(uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,17 +423,14 @@ impl InputHandler {
|
|||||||
}
|
}
|
||||||
/// Handle keyboard button events
|
/// Handle keyboard button events
|
||||||
async fn button_press(&mut self, key_code: KeyCode, key_modifier: KeyModifiers) {
|
async fn button_press(&mut self, key_code: KeyCode, key_modifier: KeyModifiers) {
|
||||||
let contains_delete = self
|
let status = self.gui_state.lock().get_status();
|
||||||
.gui_state
|
let contains = |s: Status| status.contains(&s);
|
||||||
.lock()
|
|
||||||
.status_contains(&[Status::DeleteConfirm]);
|
|
||||||
|
|
||||||
let contains = |s: Status| self.gui_state.lock().status_contains(&[s]);
|
|
||||||
|
|
||||||
let contains_error = contains(Status::Error);
|
let contains_error = contains(Status::Error);
|
||||||
let contains_help = contains(Status::Help);
|
let contains_help = contains(Status::Help);
|
||||||
let contains_exec = contains(Status::Exec);
|
let contains_exec = contains(Status::Exec);
|
||||||
let contains_filter: bool = contains(Status::Filter);
|
let contains_filter = contains(Status::Filter);
|
||||||
|
let contains_delete = contains(Status::DeleteConfirm);
|
||||||
|
|
||||||
if !contains_exec {
|
if !contains_exec {
|
||||||
let is_c = || key_code == KeyCode::Char('c') || key_code == KeyCode::Char('C');
|
let is_c = || key_code == KeyCode::Char('c') || key_code == KeyCode::Char('C');
|
||||||
|
|||||||
+103
-61
@@ -96,7 +96,7 @@ fn generate_block<'a>(
|
|||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.border_type(BorderType::Rounded)
|
.border_type(BorderType::Rounded)
|
||||||
.title(title);
|
.title(title);
|
||||||
if fd.selected_panel == panel && !gui_state.lock().status_contains(&[Status::Filter]) {
|
if fd.selected_panel == panel && !fd.status.contains(&Status::Filter) {
|
||||||
block = block.border_style(Style::default().fg(Color::LightCyan));
|
block = block.border_style(Style::default().fg(Color::LightCyan));
|
||||||
}
|
}
|
||||||
block
|
block
|
||||||
@@ -260,7 +260,7 @@ pub fn logs(
|
|||||||
gui_state: &Arc<Mutex<GuiState>>,
|
gui_state: &Arc<Mutex<GuiState>>,
|
||||||
) {
|
) {
|
||||||
let block = generate_block(area, fd, gui_state, SelectablePanel::Logs);
|
let block = generate_block(area, fd, gui_state, SelectablePanel::Logs);
|
||||||
if fd.init {
|
if fd.status.contains(&Status::Init) {
|
||||||
let paragraph = Paragraph::new(format!("parsing logs {}", fd.loading_icon))
|
let paragraph = Paragraph::new(format!("parsing logs {}", fd.loading_icon))
|
||||||
.style(Style::default())
|
.style(Style::default())
|
||||||
.block(block)
|
.block(block)
|
||||||
@@ -274,7 +274,7 @@ pub fn logs(
|
|||||||
.alignment(Alignment::Center);
|
.alignment(Alignment::Center);
|
||||||
f.render_widget(paragraph, area);
|
f.render_widget(paragraph, area);
|
||||||
} else {
|
} else {
|
||||||
let items = List::new(app_data.lock().get_logs())
|
let items = List::new(logs)
|
||||||
.block(block)
|
.block(block)
|
||||||
.highlight_symbol(RIGHT_ARROW)
|
.highlight_symbol(RIGHT_ARROW)
|
||||||
.highlight_style(Style::default().add_modifier(Modifier::BOLD));
|
.highlight_style(Style::default().add_modifier(Modifier::BOLD));
|
||||||
@@ -287,15 +287,8 @@ pub fn logs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Display the ports in a formatted list
|
// Display the ports in a formatted list
|
||||||
pub fn ports(
|
pub fn ports(f: &mut Frame, area: Rect, fd: &FrameData) {
|
||||||
f: &mut Frame,
|
if let Some(ports) = fd.ports.as_ref() {
|
||||||
area: Rect,
|
|
||||||
app_data: &Arc<Mutex<AppData>>,
|
|
||||||
max_lens: (usize, usize, usize),
|
|
||||||
) {
|
|
||||||
let mut data = app_data.lock();
|
|
||||||
let ports = data.get_selected_ports();
|
|
||||||
if let Some(ports) = ports {
|
|
||||||
let block = Block::default()
|
let block = Block::default()
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.border_type(BorderType::Rounded)
|
.border_type(BorderType::Rounded)
|
||||||
@@ -307,7 +300,7 @@ pub fn ports(
|
|||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
));
|
));
|
||||||
|
|
||||||
let (ip, private, public) = max_lens;
|
let (ip, private, public) = fd.port_max_lens;
|
||||||
|
|
||||||
if ports.0.is_empty() {
|
if ports.0.is_empty() {
|
||||||
let text = match ports.1 {
|
let text = match ports.1 {
|
||||||
@@ -318,7 +311,6 @@ pub fn ports(
|
|||||||
.alignment(Alignment::Center)
|
.alignment(Alignment::Center)
|
||||||
.block(block);
|
.block(block);
|
||||||
f.render_widget(paragraph, area);
|
f.render_widget(paragraph, area);
|
||||||
drop(data);
|
|
||||||
} else {
|
} else {
|
||||||
let mut output = vec![Line::from(
|
let mut output = vec![Line::from(
|
||||||
Span::from(format!(
|
Span::from(format!(
|
||||||
@@ -327,7 +319,7 @@ pub fn ports(
|
|||||||
))
|
))
|
||||||
.fg(Color::Yellow),
|
.fg(Color::Yellow),
|
||||||
)];
|
)];
|
||||||
for item in ports.0 {
|
for item in &ports.0 {
|
||||||
let fg = Color::White;
|
let fg = Color::White;
|
||||||
let strings = item.get_all();
|
let strings = item.get_all();
|
||||||
|
|
||||||
@@ -345,9 +337,8 @@ pub fn ports(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the cpu + mem charts
|
/// Draw the cpu + mem charts
|
||||||
pub fn chart(f: &mut Frame, area: Rect, app_data: &Arc<Mutex<AppData>>) {
|
pub fn chart(f: &mut Frame, area: Rect, fd: &FrameData) {
|
||||||
let cpu_mem = app_data.lock().get_chart_data();
|
if let Some((cpu, mem)) = fd.chart_data.as_ref() {
|
||||||
if let Some((cpu, mem)) = cpu_mem {
|
|
||||||
let area = Layout::default()
|
let area = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints(CONSTRAINT_50_50)
|
.constraints(CONSTRAINT_50_50)
|
||||||
@@ -489,10 +480,11 @@ pub fn filter_bar(area: Rect, frame: &mut Frame, fd: &FrameData) {
|
|||||||
|
|
||||||
/// Draw heading bar at top of program, always visible
|
/// Draw heading bar at top of program, always visible
|
||||||
/// TODO Should separate into loading icon/headers/help functions
|
/// TODO Should separate into loading icon/headers/help functions
|
||||||
|
#[allow(clippy::too_many_lines)]
|
||||||
pub fn heading_bar(
|
pub fn heading_bar(
|
||||||
area: Rect,
|
area: Rect,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
data: &FrameData,
|
fd: &FrameData,
|
||||||
gui_state: &Arc<Mutex<GuiState>>,
|
gui_state: &Arc<Mutex<GuiState>>,
|
||||||
) {
|
) {
|
||||||
let block = |fg: Color| Block::default().style(Style::default().bg(Color::Magenta).fg(fg));
|
let block = |fg: Color| Block::default().style(Style::default().bg(Color::Magenta).fg(fg));
|
||||||
@@ -503,7 +495,7 @@ pub fn heading_bar(
|
|||||||
let header_block = |x: &Header| {
|
let header_block = |x: &Header| {
|
||||||
let mut color = Color::Black;
|
let mut color = Color::Black;
|
||||||
let mut suffix = "";
|
let mut suffix = "";
|
||||||
if let Some((a, b)) = &data.sorted_by {
|
if let Some((a, b)) = &fd.sorted_by {
|
||||||
if x == a {
|
if x == a {
|
||||||
match b {
|
match b {
|
||||||
SortedOrder::Asc => suffix = " ▲",
|
SortedOrder::Asc => suffix = " ▲",
|
||||||
@@ -536,26 +528,30 @@ pub fn heading_bar(
|
|||||||
|
|
||||||
// Meta data to iterate over to create blocks with correct widths
|
// Meta data to iterate over to create blocks with correct widths
|
||||||
let header_meta = [
|
let header_meta = [
|
||||||
(Header::Name, data.columns.name.1),
|
(Header::Name, fd.columns.name.1),
|
||||||
(Header::State, data.columns.state.1),
|
(Header::State, fd.columns.state.1),
|
||||||
(Header::Status, data.columns.status.1),
|
(Header::Status, fd.columns.status.1),
|
||||||
(Header::Cpu, data.columns.cpu.1),
|
(Header::Cpu, fd.columns.cpu.1),
|
||||||
(Header::Memory, data.columns.mem.1 + data.columns.mem.2 + 3),
|
(Header::Memory, fd.columns.mem.1 + fd.columns.mem.2 + 3),
|
||||||
(Header::Id, data.columns.id.1),
|
(Header::Id, fd.columns.id.1),
|
||||||
(Header::Image, data.columns.image.1),
|
(Header::Image, fd.columns.image.1),
|
||||||
(Header::Rx, data.columns.net_rx.1),
|
(Header::Rx, fd.columns.net_rx.1),
|
||||||
(Header::Tx, data.columns.net_tx.1),
|
(Header::Tx, fd.columns.net_tx.1),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Need to add widths to this
|
// Need to add widths to this
|
||||||
|
|
||||||
let suffix = if data.help_visible { "exit" } else { "show" };
|
let suffix = if fd.status.contains(&Status::Help) {
|
||||||
|
"exit"
|
||||||
|
} else {
|
||||||
|
"show"
|
||||||
|
};
|
||||||
let info_text = format!("( h ) {suffix} help{MARGIN}",);
|
let info_text = format!("( h ) {suffix} help{MARGIN}",);
|
||||||
let info_width = info_text.chars().count();
|
let info_width = info_text.chars().count();
|
||||||
|
|
||||||
let column_width = usize::from(area.width).saturating_sub(info_width);
|
let column_width = usize::from(area.width).saturating_sub(info_width);
|
||||||
let column_width = if column_width > 0 { column_width } else { 1 };
|
let column_width = if column_width > 0 { column_width } else { 1 };
|
||||||
let splits = if data.has_containers {
|
let splits = if fd.has_containers {
|
||||||
vec![
|
vec![
|
||||||
Constraint::Max(4),
|
Constraint::Max(4),
|
||||||
Constraint::Max(column_width.try_into().unwrap_or_default()),
|
Constraint::Max(column_width.try_into().unwrap_or_default()),
|
||||||
@@ -571,11 +567,11 @@ pub fn heading_bar(
|
|||||||
.split(area);
|
.split(area);
|
||||||
|
|
||||||
// Draw loading icon, or not, and a prefix with a single space
|
// Draw loading icon, or not, and a prefix with a single space
|
||||||
let loading_paragraph = Paragraph::new(format!("{:>2}", data.loading_icon))
|
let loading_paragraph = Paragraph::new(format!("{:>2}", fd.loading_icon))
|
||||||
.block(block(Color::White))
|
.block(block(Color::White))
|
||||||
.alignment(Alignment::Left);
|
.alignment(Alignment::Left);
|
||||||
frame.render_widget(loading_paragraph, split_bar[0]);
|
frame.render_widget(loading_paragraph, split_bar[0]);
|
||||||
if data.has_containers {
|
if fd.has_containers {
|
||||||
let header_section_width = split_bar[1].width;
|
let header_section_width = split_bar[1].width;
|
||||||
|
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
@@ -610,7 +606,7 @@ pub fn heading_bar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// show/hide help
|
// show/hide help
|
||||||
let color = if data.help_visible {
|
let color = if fd.status.contains(&Status::Help) {
|
||||||
Color::Black
|
Color::Black
|
||||||
} else {
|
} else {
|
||||||
Color::White
|
Color::White
|
||||||
@@ -620,7 +616,7 @@ pub fn heading_bar(
|
|||||||
.alignment(Alignment::Right);
|
.alignment(Alignment::Right);
|
||||||
|
|
||||||
// If no containers, don't display the headers, could maybe do this first?
|
// If no containers, don't display the headers, could maybe do this first?
|
||||||
let help_index = if data.has_containers { 2 } else { 0 };
|
let help_index = if fd.has_containers { 2 } else { 0 };
|
||||||
frame.render_widget(help_paragraph, split_bar[help_index]);
|
frame.render_widget(help_paragraph, split_bar[help_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1004,7 +1000,7 @@ pub fn error(f: &mut Frame, error: AppError, seconds: Option<u8>) {
|
|||||||
|
|
||||||
/// Draw info box in one of the 9 BoxLocations
|
/// Draw info box in one of the 9 BoxLocations
|
||||||
// TODO is this broken - I don't think so
|
// TODO is this broken - I don't think so
|
||||||
pub fn info(f: &mut Frame, text: String, instant: Instant, gui_state: &Arc<Mutex<GuiState>>) {
|
pub fn info(f: &mut Frame, text: String, instant: &Instant, gui_state: &Arc<Mutex<GuiState>>) {
|
||||||
let block = Block::default()
|
let block = Block::default()
|
||||||
.title("")
|
.title("")
|
||||||
.title_alignment(Alignment::Center)
|
.title_alignment(Alignment::Center)
|
||||||
@@ -1084,7 +1080,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
app_error::AppError,
|
app_error::AppError,
|
||||||
tests::{gen_appdata, gen_container_summary, gen_containers},
|
tests::{gen_appdata, gen_container_summary, gen_containers},
|
||||||
ui::{draw_frame, GuiState},
|
ui::{draw_frame, GuiState, Status},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{FrameData, ORANGE, VERSION};
|
use super::{FrameData, ORANGE, VERSION};
|
||||||
@@ -1100,6 +1096,42 @@ mod tests {
|
|||||||
|
|
||||||
const BORDER_CHARS: [&str; 6] = ["╭", "╮", "─", "│", "╰", "╯"];
|
const BORDER_CHARS: [&str; 6] = ["╭", "╮", "─", "│", "╰", "╯"];
|
||||||
|
|
||||||
|
impl From<(&Arc<Mutex<AppData>>, &Arc<Mutex<GuiState>>)> for FrameData {
|
||||||
|
fn from(data: (&Arc<Mutex<AppData>>, &Arc<Mutex<GuiState>>)) -> Self {
|
||||||
|
let (app_data, gui_data) = (data.0.lock(), data.1.lock());
|
||||||
|
|
||||||
|
// set max height for container section, needs +5 to deal with docker commands list and borders
|
||||||
|
let height = app_data.get_container_len();
|
||||||
|
let height = if height < 12 {
|
||||||
|
u16::try_from(height + 5).unwrap_or_default()
|
||||||
|
} else {
|
||||||
|
12
|
||||||
|
};
|
||||||
|
|
||||||
|
let (filter_by, filter_term) = app_data.get_filter();
|
||||||
|
Self {
|
||||||
|
chart_data: app_data.get_chart_data(),
|
||||||
|
columns: app_data.get_width(),
|
||||||
|
container_title: app_data.get_container_title(),
|
||||||
|
delete_confirm: gui_data.get_delete_container(),
|
||||||
|
filter_by,
|
||||||
|
filter_term: filter_term.cloned(),
|
||||||
|
has_containers: app_data.get_container_len() > 0,
|
||||||
|
has_error: app_data.get_error(),
|
||||||
|
height,
|
||||||
|
ports: app_data.get_selected_ports(),
|
||||||
|
port_max_lens: app_data.get_longest_port(),
|
||||||
|
info_text: gui_data.info_box_text.clone(),
|
||||||
|
is_loading: gui_data.is_loading(),
|
||||||
|
loading_icon: gui_data.get_loading().to_string(),
|
||||||
|
log_title: app_data.get_log_title(),
|
||||||
|
selected_panel: gui_data.get_selected_panel(),
|
||||||
|
sorted_by: app_data.get_sorted(),
|
||||||
|
status: gui_data.get_status(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate state to be used in *most* gui tests
|
/// Generate state to be used in *most* gui tests
|
||||||
fn test_setup(w: u16, h: u16, control_start: bool, container_start: bool) -> TuiTestSetup {
|
fn test_setup(w: u16, h: u16, control_start: bool, container_start: bool) -> TuiTestSetup {
|
||||||
let backend = TestBackend::new(w, h);
|
let backend = TestBackend::new(w, h);
|
||||||
@@ -1118,7 +1150,6 @@ mod tests {
|
|||||||
|
|
||||||
let app_data = Arc::new(Mutex::new(app_data));
|
let app_data = Arc::new(Mutex::new(app_data));
|
||||||
let gui_state = Arc::new(Mutex::new(gui_state));
|
let gui_state = Arc::new(Mutex::new(gui_state));
|
||||||
|
|
||||||
let fd = FrameData::from((&app_data, &gui_state));
|
let fd = FrameData::from((&app_data, &gui_state));
|
||||||
let area = Rect::new(0, 0, w, h);
|
let area = Rect::new(0, 0, w, h);
|
||||||
TuiTestSetup {
|
TuiTestSetup {
|
||||||
@@ -1944,7 +1975,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
fd.init = true;
|
fd.status.insert(Status::Init);
|
||||||
|
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
@@ -1974,7 +2005,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
let mut fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
fd.init = true;
|
fd.status.insert(Status::Init);
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
@@ -2188,10 +2219,11 @@ mod tests {
|
|||||||
let (w, h) = (80, 10);
|
let (w, h) = (80, 10);
|
||||||
let mut setup = test_setup(w, h, true, true);
|
let mut setup = test_setup(w, h, true, true);
|
||||||
|
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::chart(f, setup.area, &setup.app_data);
|
super::chart(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -2238,11 +2270,12 @@ mod tests {
|
|||||||
let mut setup = test_setup(w, h, true, true);
|
let mut setup = test_setup(w, h, true, true);
|
||||||
|
|
||||||
insert_chart_data(&setup);
|
insert_chart_data(&setup);
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
|
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::chart(f, setup.area, &setup.app_data);
|
super::chart(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -2285,11 +2318,12 @@ mod tests {
|
|||||||
|
|
||||||
insert_chart_data(&setup);
|
insert_chart_data(&setup);
|
||||||
setup.app_data.lock().containers.items[0].state = State::Paused;
|
setup.app_data.lock().containers.items[0].state = State::Paused;
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
|
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::chart(f, setup.area, &setup.app_data);
|
super::chart(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -2327,11 +2361,12 @@ mod tests {
|
|||||||
let mut setup = test_setup(w, h, true, true);
|
let mut setup = test_setup(w, h, true, true);
|
||||||
insert_chart_data(&setup);
|
insert_chart_data(&setup);
|
||||||
setup.app_data.lock().containers.items[0].state = State::Dead;
|
setup.app_data.lock().containers.items[0].state = State::Dead;
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
|
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::chart(f, setup.area, &setup.app_data);
|
super::chart(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -2393,7 +2428,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd.help_visible = true;
|
fd.status.insert(Status::Help);
|
||||||
let expected = [" ( h ) exit help "];
|
let expected = [" ( h ) exit help "];
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
@@ -2807,7 +2842,7 @@ mod tests {
|
|||||||
super::info(
|
super::info(
|
||||||
f,
|
f,
|
||||||
"test".to_owned(),
|
"test".to_owned(),
|
||||||
std::time::Instant::now(),
|
&std::time::Instant::now(),
|
||||||
&setup.gui_state,
|
&setup.gui_state,
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -3079,11 +3114,11 @@ mod tests {
|
|||||||
let mut setup = test_setup(w, h, true, true);
|
let mut setup = test_setup(w, h, true, true);
|
||||||
setup.app_data.lock().containers.items[0].ports = vec![];
|
setup.app_data.lock().containers.items[0].ports = vec![];
|
||||||
|
|
||||||
let max_lens = setup.app_data.lock().get_longest_port();
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::ports(f, setup.area, &setup.app_data, max_lens);
|
super::ports(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3124,11 +3159,12 @@ mod tests {
|
|||||||
|
|
||||||
// When state is "State::Running | State::Paused | State::Restarting, won't show "no ports"
|
// When state is "State::Running | State::Paused | State::Restarting, won't show "no ports"
|
||||||
setup.app_data.lock().containers.items[0].state = State::Dead;
|
setup.app_data.lock().containers.items[0].state = State::Dead;
|
||||||
let max_lens = setup.app_data.lock().get_longest_port();
|
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::ports(f, setup.area, &setup.app_data, max_lens);
|
super::ports(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3179,12 +3215,11 @@ mod tests {
|
|||||||
public: Some(8003),
|
public: Some(8003),
|
||||||
});
|
});
|
||||||
|
|
||||||
let max_lens = setup.app_data.lock().get_longest_port();
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
|
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::ports(f, setup.area, &setup.app_data, max_lens);
|
super::ports(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3233,12 +3268,12 @@ mod tests {
|
|||||||
fn test_draw_blocks_ports_container_state() {
|
fn test_draw_blocks_ports_container_state() {
|
||||||
let (w, h) = (32, 8);
|
let (w, h) = (32, 8);
|
||||||
let mut setup = test_setup(w, h, true, true);
|
let mut setup = test_setup(w, h, true, true);
|
||||||
let max_lens = setup.app_data.lock().get_longest_port();
|
|
||||||
|
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::ports(f, setup.area, &setup.app_data, max_lens);
|
super::ports(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3266,10 +3301,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setup.app_data.lock().containers.items[0].state = State::Paused;
|
setup.app_data.lock().containers.items[0].state = State::Paused;
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::ports(f, setup.area, &setup.app_data, max_lens);
|
super::ports(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3286,10 +3322,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setup.app_data.lock().containers.items[0].state = State::Exited;
|
setup.app_data.lock().containers.items[0].state = State::Exited;
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
super::ports(f, setup.area, &setup.app_data, max_lens);
|
super::ports(f, setup.area, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3357,10 +3394,12 @@ mod tests {
|
|||||||
"│ │ ││ │ ││ │",
|
"│ │ ││ │ ││ │",
|
||||||
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
|
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
draw_frame(f, &setup.app_data, &setup.gui_state);
|
draw_frame(f, &setup.app_data, &setup.gui_state, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3421,10 +3460,11 @@ mod tests {
|
|||||||
"│ │ ││ │ ││ │",
|
"│ │ ││ │ ││ │",
|
||||||
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
|
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
|
||||||
];
|
];
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
draw_frame(f, &setup.app_data, &setup.gui_state);
|
draw_frame(f, &setup.app_data, &setup.gui_state, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3475,10 +3515,11 @@ mod tests {
|
|||||||
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
|
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
|
||||||
" Esc clear ← by → Name Image Status All term: r_1 ",
|
" Esc clear ← by → Name Image Status All term: r_1 ",
|
||||||
];
|
];
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
draw_frame(f, &setup.app_data, &setup.gui_state);
|
draw_frame(f, &setup.app_data, &setup.gui_state, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -3543,10 +3584,11 @@ mod tests {
|
|||||||
"│ │ ││ │ ││ │",
|
"│ │ ││ │ ││ │",
|
||||||
"╰──────────────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
|
"╰──────────────────────────────────────────────────────────────────────────────╯╰──────────────────────────────────────────────────────────────────────────────╯╰────────────────────────────╯",
|
||||||
];
|
];
|
||||||
|
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||||
setup
|
setup
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|f| {
|
.draw(|f| {
|
||||||
draw_frame(f, &setup.app_data, &setup.gui_state);
|
draw_frame(f, &setup.app_data, &setup.gui_state, &fd);
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -266,10 +266,9 @@ impl GuiState {
|
|||||||
self.delete_container = id;
|
self.delete_container = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the current gui_status contains any of the given status'
|
/// Return a copy of the Status HashSet
|
||||||
/// Don't really like this methodology for gui state, needs a re-think
|
pub fn get_status(&self) -> HashSet<Status> {
|
||||||
pub fn status_contains(&self, status: &[Status]) -> bool {
|
self.status.clone()
|
||||||
status.iter().any(|i| self.status.contains(i))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a gui_status into the current gui_status HashSet
|
/// Remove a gui_status into the current gui_status HashSet
|
||||||
|
|||||||
+41
-33
@@ -11,6 +11,7 @@ use ratatui::{
|
|||||||
Frame, Terminal,
|
Frame, Terminal,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
io::{self, Stdout, Write},
|
io::{self, Stdout, Write},
|
||||||
sync::{atomic::Ordering, Arc},
|
sync::{atomic::Ordering, Arc},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
@@ -26,7 +27,10 @@ mod gui_state;
|
|||||||
pub use self::color_match::*;
|
pub use self::color_match::*;
|
||||||
pub use self::gui_state::{DeleteButton, GuiState, SelectablePanel, Status};
|
pub use self::gui_state::{DeleteButton, GuiState, SelectablePanel, Status};
|
||||||
use crate::{
|
use crate::{
|
||||||
app_data::{AppData, Columns, ContainerId, FilterBy, Header, SortedOrder},
|
app_data::{
|
||||||
|
AppData, Columns, ContainerId, ContainerPorts, CpuTuple, FilterBy, Header, MemTuple,
|
||||||
|
SortedOrder, State,
|
||||||
|
},
|
||||||
app_error::AppError,
|
app_error::AppError,
|
||||||
exec::TerminalSize,
|
exec::TerminalSize,
|
||||||
input_handler::InputMessages,
|
input_handler::InputMessages,
|
||||||
@@ -163,14 +167,15 @@ impl Ui {
|
|||||||
/// The loop for drawing the main UI to the terminal
|
/// The loop for drawing the main UI to the terminal
|
||||||
async fn gui_loop(&mut self) -> Result<(), AppError> {
|
async fn gui_loop(&mut self) -> Result<(), AppError> {
|
||||||
while self.is_running.load(Ordering::SeqCst) {
|
while self.is_running.load(Ordering::SeqCst) {
|
||||||
let exec = self.gui_state.lock().status_contains(&[Status::Exec]);
|
let fd = FrameData::from(&*self);
|
||||||
|
let exec = fd.status.contains(&Status::Exec);
|
||||||
if exec {
|
if exec {
|
||||||
self.exec().await;
|
self.exec().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|frame| draw_frame(frame, &self.app_data, &self.gui_state))
|
.draw(|frame| draw_frame(frame, &self.app_data, &self.gui_state, &fd))
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
return Err(AppError::Terminal);
|
return Err(AppError::Terminal);
|
||||||
@@ -206,11 +211,8 @@ impl Ui {
|
|||||||
|
|
||||||
/// Draw either the Error, or main oxker ui, to the terminal
|
/// Draw either the Error, or main oxker ui, to the terminal
|
||||||
async fn draw_ui(&mut self) -> Result<(), AppError> {
|
async fn draw_ui(&mut self) -> Result<(), AppError> {
|
||||||
let status_dockerconnect = self
|
let status = self.gui_state.lock().get_status();
|
||||||
.gui_state
|
if status.contains(&Status::DockerConnect) {
|
||||||
.lock()
|
|
||||||
.status_contains(&[Status::DockerConnect]);
|
|
||||||
if status_dockerconnect {
|
|
||||||
self.err_loop()?;
|
self.err_loop()?;
|
||||||
} else {
|
} else {
|
||||||
self.gui_loop().await?;
|
self.gui_loop().await?;
|
||||||
@@ -221,8 +223,8 @@ impl Ui {
|
|||||||
|
|
||||||
/// Frequent data required by multiple framde drawing functions, can reduce mutex reads by placing it all in here
|
/// Frequent data required by multiple framde drawing functions, can reduce mutex reads by placing it all in here
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
|
||||||
pub struct FrameData {
|
pub struct FrameData {
|
||||||
|
chart_data: Option<(CpuTuple, MemTuple)>,
|
||||||
columns: Columns,
|
columns: Columns,
|
||||||
container_title: String,
|
container_title: String,
|
||||||
delete_confirm: Option<ContainerId>,
|
delete_confirm: Option<ContainerId>,
|
||||||
@@ -231,19 +233,20 @@ pub struct FrameData {
|
|||||||
has_containers: bool,
|
has_containers: bool,
|
||||||
has_error: Option<AppError>,
|
has_error: Option<AppError>,
|
||||||
height: u16,
|
height: u16,
|
||||||
help_visible: bool,
|
|
||||||
info_text: Option<(String, Instant)>,
|
info_text: Option<(String, Instant)>,
|
||||||
init: bool,
|
|
||||||
is_loading: bool,
|
is_loading: bool,
|
||||||
loading_icon: String,
|
loading_icon: String,
|
||||||
log_title: String,
|
log_title: String,
|
||||||
|
port_max_lens: (usize, usize, usize),
|
||||||
|
ports: Option<(Vec<ContainerPorts>, State)>,
|
||||||
selected_panel: SelectablePanel,
|
selected_panel: SelectablePanel,
|
||||||
sorted_by: Option<(Header, SortedOrder)>,
|
sorted_by: Option<(Header, SortedOrder)>,
|
||||||
|
status: HashSet<Status>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(&Arc<Mutex<AppData>>, &Arc<Mutex<GuiState>>)> for FrameData {
|
impl From<&Ui> for FrameData {
|
||||||
fn from(data: (&Arc<Mutex<AppData>>, &Arc<Mutex<GuiState>>)) -> Self {
|
fn from(ui: &Ui) -> Self {
|
||||||
let (app_data, gui_data) = (data.0.lock(), data.1.lock());
|
let (app_data, gui_data) = (ui.app_data.lock(), ui.gui_state.lock());
|
||||||
|
|
||||||
// set max height for container section, needs +5 to deal with docker commands list and borders
|
// set max height for container section, needs +5 to deal with docker commands list and borders
|
||||||
let height = app_data.get_container_len();
|
let height = app_data.get_container_len();
|
||||||
@@ -255,6 +258,7 @@ impl From<(&Arc<Mutex<AppData>>, &Arc<Mutex<GuiState>>)> for FrameData {
|
|||||||
|
|
||||||
let (filter_by, filter_term) = app_data.get_filter();
|
let (filter_by, filter_term) = app_data.get_filter();
|
||||||
Self {
|
Self {
|
||||||
|
chart_data: app_data.get_chart_data(),
|
||||||
columns: app_data.get_width(),
|
columns: app_data.get_width(),
|
||||||
container_title: app_data.get_container_title(),
|
container_title: app_data.get_container_title(),
|
||||||
delete_confirm: gui_data.get_delete_container(),
|
delete_confirm: gui_data.get_delete_container(),
|
||||||
@@ -263,24 +267,27 @@ impl From<(&Arc<Mutex<AppData>>, &Arc<Mutex<GuiState>>)> for FrameData {
|
|||||||
has_containers: app_data.get_container_len() > 0,
|
has_containers: app_data.get_container_len() > 0,
|
||||||
has_error: app_data.get_error(),
|
has_error: app_data.get_error(),
|
||||||
height,
|
height,
|
||||||
help_visible: gui_data.status_contains(&[Status::Help]),
|
|
||||||
info_text: gui_data.info_box_text.clone(),
|
info_text: gui_data.info_box_text.clone(),
|
||||||
init: gui_data.status_contains(&[Status::Init]),
|
|
||||||
is_loading: gui_data.is_loading(),
|
is_loading: gui_data.is_loading(),
|
||||||
loading_icon: gui_data.get_loading().to_string(),
|
loading_icon: gui_data.get_loading().to_string(),
|
||||||
log_title: app_data.get_log_title(),
|
log_title: app_data.get_log_title(),
|
||||||
|
port_max_lens: app_data.get_longest_port(),
|
||||||
|
ports: app_data.get_selected_ports(),
|
||||||
selected_panel: gui_data.get_selected_panel(),
|
selected_panel: gui_data.get_selected_panel(),
|
||||||
sorted_by: app_data.get_sorted(),
|
sorted_by: app_data.get_sorted(),
|
||||||
|
status: gui_data.get_status(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the main ui to a frame of the terminal
|
/// Draw the main ui to a frame of the terminal
|
||||||
fn draw_frame(f: &mut Frame, app_data: &Arc<Mutex<AppData>>, gui_state: &Arc<Mutex<GuiState>>) {
|
fn draw_frame(
|
||||||
let fd = FrameData::from((app_data, gui_state));
|
f: &mut Frame,
|
||||||
let contains_filter = gui_state.lock().status_contains(&[Status::Filter]);
|
app_data: &Arc<Mutex<AppData>>,
|
||||||
|
gui_state: &Arc<Mutex<GuiState>>,
|
||||||
let whole_constraints = if contains_filter {
|
fd: &FrameData,
|
||||||
|
) {
|
||||||
|
let whole_constraints = if fd.status.contains(&Status::Filter) {
|
||||||
vec![Constraint::Max(1), Constraint::Min(1), Constraint::Max(1)]
|
vec![Constraint::Max(1), Constraint::Min(1), Constraint::Max(1)]
|
||||||
} else {
|
} else {
|
||||||
vec![Constraint::Max(1), Constraint::Min(1)]
|
vec![Constraint::Max(1), Constraint::Min(1)]
|
||||||
@@ -320,15 +327,15 @@ fn draw_frame(f: &mut Frame, app_data: &Arc<Mutex<AppData>>, gui_state: &Arc<Mut
|
|||||||
.constraints(lower_split)
|
.constraints(lower_split)
|
||||||
.split(upper_main[1]);
|
.split(upper_main[1]);
|
||||||
|
|
||||||
draw_blocks::containers(app_data, top_panel[0], f, &fd, gui_state);
|
draw_blocks::containers(app_data, top_panel[0], f, fd, gui_state);
|
||||||
|
|
||||||
draw_blocks::logs(app_data, lower_main[0], f, &fd, gui_state);
|
draw_blocks::logs(app_data, lower_main[0], f, fd, gui_state);
|
||||||
|
|
||||||
draw_blocks::heading_bar(whole_layout[0], f, &fd, gui_state);
|
draw_blocks::heading_bar(whole_layout[0], f, fd, gui_state);
|
||||||
|
|
||||||
// Draw filter bar
|
// Draw filter bar
|
||||||
if let Some(rect) = whole_layout.get(2) {
|
if let Some(rect) = whole_layout.get(2) {
|
||||||
draw_blocks::filter_bar(*rect, f, &fd);
|
draw_blocks::filter_bar(*rect, f, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(id) = fd.delete_confirm.as_ref() {
|
if let Some(id) = fd.delete_confirm.as_ref() {
|
||||||
@@ -346,27 +353,28 @@ fn draw_frame(f: &mut Frame, app_data: &Arc<Mutex<AppData>>, gui_state: &Arc<Mut
|
|||||||
|
|
||||||
// only draw commands + charts if there are containers
|
// only draw commands + charts if there are containers
|
||||||
if let Some(rect) = top_panel.get(1) {
|
if let Some(rect) = top_panel.get(1) {
|
||||||
draw_blocks::commands(app_data, *rect, f, &fd, gui_state);
|
draw_blocks::commands(app_data, *rect, f, fd, gui_state);
|
||||||
|
|
||||||
// Can calculate the max string length here, and then use that to keep the ports section as small as possible (+4 for some padding + border)
|
// Can calculate the max string length here, and then use that to keep the ports section as small as possible (+4 for some padding + border)
|
||||||
let max_lens = app_data.lock().get_longest_port();
|
let ports_len =
|
||||||
let ports_len = u16::try_from(max_lens.0 + max_lens.1 + max_lens.2 + 2).unwrap_or(26);
|
u16::try_from(fd.port_max_lens.0 + fd.port_max_lens.1 + fd.port_max_lens.2 + 2)
|
||||||
|
.unwrap_or(26);
|
||||||
|
|
||||||
let lower = Layout::default()
|
let lower = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Min(1), Constraint::Max(ports_len)])
|
.constraints([Constraint::Min(1), Constraint::Max(ports_len)])
|
||||||
.split(lower_main[1]);
|
.split(lower_main[1]);
|
||||||
|
|
||||||
draw_blocks::chart(f, lower[0], app_data);
|
draw_blocks::chart(f, lower[0], fd);
|
||||||
draw_blocks::ports(f, lower[1], app_data, max_lens);
|
draw_blocks::ports(f, lower[1], fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((text, instant)) = fd.info_text {
|
if let Some((text, instant)) = fd.info_text.as_ref() {
|
||||||
draw_blocks::info(f, text, instant, gui_state);
|
draw_blocks::info(f, text.to_owned(), instant, gui_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if error, and show popup if so
|
// Check if error, and show popup if so
|
||||||
if fd.help_visible {
|
if fd.status.contains(&Status::Help) {
|
||||||
draw_blocks::help_box(f);
|
draw_blocks::help_box(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user