Skip to content

Commit 1f5836d

Browse files
committed
Revise line selection and column removal.
1 parent e28c7e9 commit 1f5836d

7 files changed

+166
-169
lines changed

.idea/json-log-reader.iml

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,6 @@ impl TemplateApp {
106106
}
107107

108108
impl eframe::App for TemplateApp {
109-
/// Called by the frame work to save state before shutdown.
110-
fn save(&mut self, storage: &mut dyn eframe::Storage) {
111-
eframe::set_value(storage, eframe::APP_KEY, self);
112-
}
113-
114109
/// Called each time the UI needs repainting, which may be many times per second.
115110
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
116111
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
@@ -178,4 +173,9 @@ impl eframe::App for TemplateApp {
178173
});
179174
}
180175
}
176+
177+
/// Called by the frame work to save state before shutdown.
178+
fn save(&mut self, storage: &mut dyn eframe::Storage) {
179+
eframe::set_value(storage, eframe::APP_KEY, self);
180+
}
181181
}

src/app/filtered_log_entries_tab.rs

+12-17
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use log::error;
1212
use super::{
1313
log_entries_table::LogEntriesTable,
1414
log_file_reader::{LineNumber, LogFileReader},
15-
log_view::{LogViewerState, LogViewTabResponse, LogViewTabTrait},
15+
log_view::{LogViewTabTrait, LogViewerState},
1616
};
1717

1818
#[derive(Debug)]
@@ -53,22 +53,22 @@ impl Default for SearchOptions {
5353

5454
pub struct FilteredLogEntriesTab {
5555
log_file_path: PathBuf,
56-
selected_line_num: Option<LineNumber>,
5756
editable_search_term: String,
5857
search_term: String,
5958
search_results: Vec<LineNumber>,
6059
search_options: SearchOptions,
60+
selected_line: Option<LineNumber>
6161
}
6262

6363
impl FilteredLogEntriesTab {
6464
pub fn new(log_file_path: PathBuf) -> Box<Self> {
6565
Box::new(Self {
6666
log_file_path,
67-
selected_line_num: None,
6867
search_term: Default::default(),
6968
search_results: vec![],
7069
search_options: Default::default(),
7170
editable_search_term: Default::default(),
71+
selected_line: None
7272
})
7373
}
7474

@@ -170,35 +170,30 @@ impl FilteredLogEntriesTab {
170170

171171
impl LogViewTabTrait for FilteredLogEntriesTab {
172172
fn title(&self) -> egui::WidgetText {
173-
format!("Search: {}", self.search_term).into()
173+
if self.search_term.is_empty() {
174+
"Search".into()
175+
} else {
176+
format!("Search: {}", self.search_term).into()
177+
}
174178
}
175179

176180
fn ui(
177181
&mut self,
178182
ui: &mut Ui,
179183
log_reader: &mut LogFileReader,
180184
viewer_state: &mut LogViewerState,
181-
) -> LogViewTabResponse {
185+
) {
182186
self.ui_search(ui);
183187

184188
let mut log_entries_table = LogEntriesTable::new()
185189
.filtered_lines(&self.search_results)
186190
.select_line(viewer_state.selected_line_num);
187191

188-
if viewer_state.selected_line_num != self.selected_line_num {
192+
if self.selected_line != viewer_state.selected_line_num {
193+
self.selected_line = viewer_state.selected_line_num;
189194
log_entries_table = log_entries_table.scroll_to_selected();
190-
self.selected_line_num = viewer_state.selected_line_num;
191-
}
192-
193-
let response = log_entries_table.ui(ui, log_reader, viewer_state);
194-
195-
// Save a selection that came from this tab immediately to prevent scrolling
196-
if let Some(selected_line_num) = response.selected_line_num {
197-
self.selected_line_num = Some(selected_line_num);
198195
}
199196

200-
LogViewTabResponse {
201-
selected_line_num: response.selected_line_num,
202-
}
197+
log_entries_table.ui(ui, log_reader, viewer_state);
203198
}
204199
}

src/app/log_entries_tab.rs

+11-20
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1+
use crate::app::log_file_reader::LineNumber;
12
use super::{
23
log_entries_table::LogEntriesTable,
3-
log_file_reader::{LineNumber, LogFileReader},
4-
log_view::{LogViewerState, LogViewTabResponse, LogViewTabTrait},
4+
log_file_reader::{LogFileReader},
5+
log_view::{LogViewerState, LogViewTabTrait},
56
};
67

78
pub struct LogEntriesTab {
8-
selected_line_num: Option<LineNumber>,
9+
selected_line: Option<LineNumber>
910
}
1011

1112
impl LogEntriesTab {
1213
pub fn new() -> Box<Self> {
13-
Box::new(Self {
14-
selected_line_num: None,
15-
})
14+
Box::new(Self { selected_line: None })
1615
}
1716
}
1817

@@ -25,25 +24,17 @@ impl LogViewTabTrait for LogEntriesTab {
2524
&mut self,
2625
ui: &mut egui::Ui,
2726
log_reader: &mut LogFileReader,
28-
viewer_state: &mut LogViewerState,
29-
) -> LogViewTabResponse {
27+
viewer_state: &mut LogViewerState,
28+
) {
29+
3030
let mut log_entries_table =
3131
LogEntriesTable::new().select_line(viewer_state.selected_line_num);
3232

33-
if viewer_state.selected_line_num != self.selected_line_num {
33+
if self.selected_line != viewer_state.selected_line_num {
34+
self.selected_line = viewer_state.selected_line_num;
3435
log_entries_table = log_entries_table.scroll_to_selected();
35-
self.selected_line_num = viewer_state.selected_line_num;
3636
}
3737

38-
let response = log_entries_table.ui(ui, log_reader, viewer_state);
39-
40-
// Save a selection that came from this tab immediately to prevent scrolling
41-
if let Some(selected_line_num) = response.selected_line_num {
42-
self.selected_line_num = Some(selected_line_num);
43-
}
44-
45-
LogViewTabResponse {
46-
selected_line_num: response.selected_line_num,
47-
}
38+
log_entries_table.ui(ui, log_reader, viewer_state);
4839
}
4940
}

src/app/log_entries_table.rs

+49-28
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,34 @@
1-
use egui::{Align, Color32, RichText, Ui};
1+
use eframe::emath::Vec2;
2+
use egui::{
3+
include_image, Align, Button, Color32, CursorIcon, ImageSource, Response, RichText, Ui,
4+
};
25
use egui_extras::{Column, TableBuilder, TableRow};
6+
use egui_toast::ToastKind;
37

48
use crate::app::log_view::{ColumnTextColor, LogViewerState};
59

610
use super::log_file_reader::{LineNumber, LogFileReader};
711

8-
#[derive(Default)]
9-
pub struct LogEntriesResponse {
10-
pub selected_line_num: Option<LineNumber>,
11-
}
12-
1312
pub struct LogEntriesTable<'a> {
1413
filtered_lines: Option<&'a [LineNumber]>,
1514
selected_line: Option<usize>,
1615
scroll_to_selected: bool,
1716
}
1817

1918
impl<'a> LogEntriesTable<'a> {
19+
fn add_tool_button(
20+
ui: &mut egui::Ui,
21+
image_source: ImageSource<'_>,
22+
hover_text: &str,
23+
) -> Response {
24+
ui.add_sized(
25+
Vec2::new(14.0, 14.0),
26+
Button::image(image_source).frame(false),
27+
)
28+
.on_hover_cursor(CursorIcon::PointingHand)
29+
.on_hover_text(hover_text)
30+
}
31+
2032
pub fn new() -> Self {
2133
Self {
2234
filtered_lines: None,
@@ -45,9 +57,7 @@ impl<'a> LogEntriesTable<'a> {
4557
ui: &mut Ui,
4658
log_file_reader: &mut LogFileReader,
4759
viewer_state: &mut LogViewerState,
48-
) -> LogEntriesResponse {
49-
let mut response: LogEntriesResponse = Default::default();
50-
60+
) {
5161
let total_rows = match self.filtered_lines {
5262
Some(lines) => lines.len(),
5363
None => log_file_reader.line_count() as usize,
@@ -56,6 +66,7 @@ impl<'a> LogEntriesTable<'a> {
5666
let mut table_builder = TableBuilder::new(ui)
5767
.max_scroll_height(f32::INFINITY)
5868
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
69+
.striped(true)
5970
.sense(egui::Sense::click());
6071

6172
let mut col_iter = viewer_state.displayed_columns.iter().peekable();
@@ -81,15 +92,32 @@ impl<'a> LogEntriesTable<'a> {
8192
table_builder = table_builder.scroll_to_row(selected_row, Some(Align::Center));
8293
}
8394
}
95+
self.scroll_to_selected = false;
8496
}
8597

8698
table_builder
8799
.header(18.0, |mut row| {
100+
let columns_displayed_count = viewer_state.displayed_columns.len();
101+
let mut columns_to_remove: Vec<String> = vec![];
88102
for displayed_column in &viewer_state.displayed_columns {
89103
row.col(|ui| {
90104
ui.label(RichText::new(displayed_column).strong());
105+
if columns_displayed_count > 1 {
106+
let rm_icon = include_image!("../../assets/icons8-minus-48-white.png");
107+
if Self::add_tool_button(ui, rm_icon, "Remove Column").clicked() {
108+
columns_to_remove.push(displayed_column.clone());
109+
}
110+
}
91111
});
92112
}
113+
114+
if !columns_to_remove.is_empty() {
115+
viewer_state
116+
.displayed_columns
117+
.retain(|c| !columns_to_remove.contains(c));
118+
119+
viewer_state.add_toast(ToastKind::Info, "Removed column.".into(), 2.0);
120+
}
93121
})
94122
.body(|body| {
95123
body.rows(16.0, total_rows, |mut row| {
@@ -101,18 +129,14 @@ impl<'a> LogEntriesTable<'a> {
101129

102130
row.set_selected(self.selected_line == Some(line_number));
103131

104-
if let Some(logline_response) =
105-
Self::ui_logline(log_file_reader, viewer_state, &mut row, line_number)
106-
{
107-
if let Some(selected_line_num) = logline_response.selected_line_num {
108-
viewer_state.selected_line_num = Some(selected_line_num);
109-
response.selected_line_num = Some(selected_line_num);
110-
}
132+
Self::ui_logline(log_file_reader, viewer_state, &mut row, line_number);
133+
134+
if row.response().clicked() {
135+
self.selected_line = Some(line_number);
136+
viewer_state.selected_line_num = self.selected_line;
111137
}
112138
});
113139
});
114-
115-
response
116140
}
117141

118142
/// Maps a line number to a table row.
@@ -130,16 +154,19 @@ impl<'a> LogEntriesTable<'a> {
130154
viewer_state: &mut LogViewerState,
131155
row: &mut TableRow<'_, '_>,
132156
line_num: LineNumber,
133-
) -> Option<LogEntriesResponse> {
134-
let mut response: LogEntriesResponse = Default::default();
157+
) -> Option<()> {
135158
let log_line = log_file_reader.read_line(line_num)?;
136159

137160
match LogFileReader::parse_logline(&log_line) {
138161
Some(log_entry) => {
139162
for column_str in &viewer_state.displayed_columns {
140163
row.col(|ui| {
141164
let column_value = &log_entry.object[column_str];
142-
let full_col_text = if column_value.is_empty() { String::new() } else { column_value.to_string() };
165+
let full_col_text = if column_value.is_empty() {
166+
String::new()
167+
} else {
168+
column_value.to_string()
169+
};
143170
let mut column_text = if let Some(split) = full_col_text.split_once('\n') {
144171
split.0
145172
} else {
@@ -179,13 +206,7 @@ impl<'a> LogEntriesTable<'a> {
179206
}
180207
}
181208

182-
if row.response().clicked() {
183-
response = LogEntriesResponse {
184-
selected_line_num: Some(line_num),
185-
};
186-
}
187-
188-
Some(response)
209+
Some(())
189210
}
190211
}
191212

0 commit comments

Comments
 (0)