diff --git a/src/app/filtered_log_entries_tab.rs b/src/app/filtered_log_entries_tab.rs index 7990f1a..fcc9b05 100644 --- a/src/app/filtered_log_entries_tab.rs +++ b/src/app/filtered_log_entries_tab.rs @@ -5,14 +5,14 @@ use std::{ }; use egui::Ui; -use grep::searcher::{sinks::Lossy, Searcher}; +use grep::searcher::{Searcher, sinks::Lossy}; use grep_regex::RegexMatcherBuilder; use log::error; use super::{ log_entries_table::LogEntriesTable, log_file_reader::{LineNumber, LogFileReader}, - log_view::{LogViewTabTrait, LogViewerState}, + log_view::{LogViewerState, LogViewTabTrait}, }; #[derive(Debug)] diff --git a/src/app/log_entries_table.rs b/src/app/log_entries_table.rs index ad6601b..19059b1 100644 --- a/src/app/log_entries_table.rs +++ b/src/app/log_entries_table.rs @@ -21,12 +21,9 @@ impl<'a> LogEntriesTable<'a> { image_source: ImageSource<'_>, hover_text: &str, ) -> Response { - ui.add_sized( - Vec2::new(14.0, 14.0), - Button::image(image_source).frame(false), - ) - .on_hover_cursor(CursorIcon::PointingHand) - .on_hover_text(hover_text) + ui.add_sized(Vec2::new(18.0, 18.0), Button::image(image_source)) + .on_hover_cursor(CursorIcon::PointingHand) + .on_hover_text(hover_text) } pub fn new() -> Self { @@ -67,8 +64,10 @@ impl<'a> LogEntriesTable<'a> { .max_scroll_height(f32::INFINITY) .cell_layout(egui::Layout::left_to_right(egui::Align::Center)) .striped(true) + .auto_shrink(false) + .min_scrolled_height(0.0) .sense(egui::Sense::click()); - + let mut col_iter = viewer_state.displayed_columns.iter().peekable(); while let Some(col_key) = col_iter.next() { let is_last_col = col_iter.peek().is_none(); @@ -96,7 +95,7 @@ impl<'a> LogEntriesTable<'a> { } table_builder - .header(18.0, |mut row| { + .header(24.0, |mut row| { let columns_displayed_count = viewer_state.displayed_columns.len(); let mut columns_to_remove: Vec = vec![]; for displayed_column in &viewer_state.displayed_columns { @@ -155,7 +154,19 @@ impl<'a> LogEntriesTable<'a> { row: &mut TableRow<'_, '_>, line_num: LineNumber, ) -> Option<()> { - let log_line = log_file_reader.read_line(line_num)?; + let log_line_opt = log_file_reader.read_line(line_num); + + if log_line_opt.is_none() { + row.col(|ui| { + ui.label( + RichText::new("⚠ Failed to read from log file.") + .color(ui.visuals().warn_fg_color), + ); + }); + return None; + } + + let log_line = log_line_opt.unwrap(); match LogFileReader::parse_logline(&log_line) { Some(log_entry) => { @@ -194,8 +205,6 @@ impl<'a> LogEntriesTable<'a> { } } None => { - row.col(|_| {}); - row.col(|_| {}); row.col(|ui| { ui.label( RichText::new(log_line.trim()) diff --git a/src/app/log_entry_context_tab.rs b/src/app/log_entry_context_tab.rs index ffb39c6..72bfa9c 100644 --- a/src/app/log_entry_context_tab.rs +++ b/src/app/log_entry_context_tab.rs @@ -1,12 +1,12 @@ use egui::{ - include_image, Button, Color32, CursorIcon, ImageSource, Response, RichText, Sense, Vec2, + Button, Color32, CursorIcon, ImageSource, include_image, Response, RichText, Sense, Vec2, }; use egui_extras::{Column, TableBuilder}; use egui_toast::ToastKind; use super::{ log_file_reader::LogFileReader, - log_view::{LogViewTabTrait, LogViewerState}, + log_view::{LogViewerState, LogViewTabTrait}, }; pub struct LogEntryContextTab {} @@ -21,12 +21,9 @@ impl LogEntryContextTab { image_source: ImageSource<'_>, hover_text: &str, ) -> Response { - ui.add_sized( - Vec2::new(14.0, 14.0), - Button::image(image_source).frame(false), - ) - .on_hover_cursor(CursorIcon::PointingHand) - .on_hover_text(hover_text) + ui.add_sized(Vec2::new(18.0, 18.0), Button::image(image_source)) + .on_hover_text(hover_text) + .on_hover_cursor(CursorIcon::PointingHand) } } @@ -52,10 +49,16 @@ impl LogViewTabTrait for LogEntryContextTab { return; } + let row_height_padding = 6.0; + let row_content_height = 14.0; + let log_entry = read_log_entry.unwrap(); TableBuilder::new(ui) .striped(true) + .min_scrolled_height(0.0) + .max_scroll_height(f32::INFINITY) + .auto_shrink(false) .sense(Sense::hover()) .cell_layout(egui::Layout::left_to_right(egui::Align::Center)) .column(Column::auto()) @@ -67,45 +70,49 @@ impl LogViewTabTrait for LogEntryContextTab { let key_str = entry.0; let value_str = entry.1.to_string(); let line_count = value_str.chars().filter(|c| *c == '\n').count() + 1; - body.row((line_count as f32) * 16.0, |mut row| { - row.col(|ui| { - let column_is_shown = - viewer_state.displayed_columns.iter().any(|s| s == key_str); - if !column_is_shown { - let add_icon = - include_image!("../../assets/icons8-add-48-white.png"); - if Self::add_tool_button(ui, add_icon, "Add Column").clicked() { - viewer_state.displayed_columns.push(key_str.to_string()); + body.row( + (line_count as f32) * row_content_height + row_height_padding, + |mut row| { + row.col(|ui| { + let column_is_shown = + viewer_state.displayed_columns.iter().any(|s| s == key_str); + if !column_is_shown { + let add_icon = + include_image!("../../assets/icons8-add-48-white.png"); + if Self::add_tool_button(ui, add_icon, "Add Column").clicked() { + viewer_state.displayed_columns.push(key_str.to_string()); + + viewer_state.add_toast( + ToastKind::Info, + format!("Added column '{}'", key_str).into(), + 2.0, + ); + } + } + }); + row.col(|ui| { + ui.label(RichText::new(key_str).color(Color32::WHITE).monospace()); + }); + row.col(|ui| { + let copy_icon = + include_image!("../../assets/icons8-copy-48-white.png"); + if Self::add_tool_button(ui, copy_icon, "Copy Value").clicked() { + ui.output_mut(|o| { + o.copied_text = value_str.clone(); + }); viewer_state.add_toast( ToastKind::Info, - format!("Added column '{}'", key_str).into(), + "Copied value to clipboard.".into(), 2.0, ); } - } - }); - row.col(|ui| { - ui.label(RichText::new(key_str).color(Color32::WHITE).monospace()); - }); - row.col(|ui| { - let copy_icon = include_image!("../../assets/icons8-copy-48-white.png"); - if Self::add_tool_button(ui, copy_icon, "Copy Value").clicked() { - ui.output_mut(|o| { - o.copied_text = value_str.clone(); - }); - - viewer_state.add_toast( - ToastKind::Info, - "Copied value to clipboard.".into(), - 2.0, - ); - } - }); - row.col(|ui| { - ui.label(RichText::new(value_str.trim()).monospace()); - }); - }); + }); + row.col(|ui| { + ui.label(RichText::new(value_str.trim()).monospace()); + }); + }, + ); } }); }