mirror of
https://github.com/hubaldv/bioz-host-rs.git
synced 2026-03-10 01:10:30 +00:00
Implemented custom marker support during logging. Updated buttons.
This commit is contained in:
128
src/app.rs
128
src/app.rs
@@ -12,7 +12,7 @@ use chrono::Local;
|
||||
use atomic_float::AtomicF32;
|
||||
use tokio::{sync::mpsc::{Sender}};
|
||||
|
||||
use eframe::egui::{self, Button, CollapsingHeader, Color32, ComboBox, DragValue, Id, Key, Label, Layout, Modifiers, RichText, TextEdit, Widget};
|
||||
use eframe::egui::{self, Button, CollapsingHeader, Color32, ComboBox, DragValue, Id, Key, Label, Layout, Modal, Modifiers, RichText, TextEdit, Widget};
|
||||
use egui_plot::{Corner, GridInput, GridMark, Legend, Line, Plot, PlotPoint, Points};
|
||||
use egui_dock::{DockArea, DockState, Style};
|
||||
use egui_extras::{TableBuilder, Column};
|
||||
@@ -70,6 +70,8 @@ pub struct App {
|
||||
pub periods_per_dft_sweep: Arc<Mutex<(Vec<u32>, Option<Vec<f32>>)>>,
|
||||
pub gui_logging_state: Arc<Mutex<LoggingStates>>,
|
||||
log_filename: String,
|
||||
log_marker_modal: bool,
|
||||
log_marker: String,
|
||||
}
|
||||
|
||||
struct TabViewer {
|
||||
@@ -404,6 +406,7 @@ impl TabViewer {
|
||||
ui.label("R: Reset view/plots");
|
||||
ui.label("S: Toggle settings");
|
||||
ui.label("L: Toggle logging");
|
||||
ui.label("A: Add marker (when logging)");
|
||||
ui.label("CMD-W: Close window");
|
||||
}
|
||||
}
|
||||
@@ -542,7 +545,9 @@ impl App {
|
||||
periods_per_dft,
|
||||
periods_per_dft_sweep,
|
||||
gui_logging_state: Arc::new(Mutex::new(LoggingStates::Idle)),
|
||||
log_filename: format!("log_{}.csv", Local::now().format("%Y%m%d"))
|
||||
log_filename: format!("log_{}_single.csv", Local::now().format("%Y%m%d")),
|
||||
log_marker_modal: false,
|
||||
log_marker: String::new(),
|
||||
};
|
||||
|
||||
// For testing purposes, populate the Bode plot with a sample low-pass filter response
|
||||
@@ -608,10 +613,27 @@ impl eframe::App for App {
|
||||
|
||||
ui.separator();
|
||||
|
||||
if ui.add_enabled(connected, toggle_start_stop(&mut *self.on.lock().unwrap())).changed() {
|
||||
self.update_start_stop();
|
||||
let on = *self.on.lock().unwrap();
|
||||
|
||||
let (color, text) = match on {
|
||||
true => (Color32::DARK_RED, "Stop"),
|
||||
false => (Color32::DARK_GREEN, "Start"),
|
||||
};
|
||||
|
||||
let start_stop_button = Button::new(
|
||||
RichText::new(text)
|
||||
.strong()
|
||||
.color(Color32::WHITE)
|
||||
).fill(color)
|
||||
.corner_radius(5.0)
|
||||
.min_size(egui::vec2(45.0, 0.0))
|
||||
.frame(true);
|
||||
|
||||
if ui.add_enabled(connected, start_stop_button).clicked() {
|
||||
*self.on.lock().unwrap() = !on;
|
||||
self.update_start_stop();
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
|
||||
if ui.add_enabled(connected, Button::new("Reset view")).clicked() {
|
||||
@@ -620,33 +642,83 @@ impl eframe::App for App {
|
||||
|
||||
ui.separator();
|
||||
|
||||
ui.add_enabled(connected, Label::new("Logging:"));
|
||||
|
||||
let gui_logging_state = *self.gui_logging_state.lock().unwrap();
|
||||
|
||||
let (color, signal) = match gui_logging_state {
|
||||
LoggingStates::Idle => (Color32::DARK_RED, LoggingSignal::StartFileLogging(self.log_filename.clone())),
|
||||
LoggingStates::Starting => (Color32::from_rgb(204, 153, 0), LoggingSignal::StopFileLogging),
|
||||
LoggingStates::Logging => (Color32::DARK_GREEN, LoggingSignal::StopFileLogging),
|
||||
};
|
||||
let mut logging_enabled = !matches!(gui_logging_state, LoggingStates::Idle);
|
||||
|
||||
let button = Button::new(
|
||||
RichText::new("Logging")
|
||||
.strong()
|
||||
.color(Color32::WHITE)
|
||||
).fill(color)
|
||||
.corner_radius(5.0)
|
||||
.frame(true);
|
||||
if ui.add_enabled(connected, toggle_start_stop(&mut logging_enabled)).changed() {
|
||||
let signal = match gui_logging_state {
|
||||
LoggingStates::Idle => LoggingSignal::StartFileLogging(self.log_filename.clone()),
|
||||
LoggingStates::Starting | LoggingStates::Logging => LoggingSignal::StopFileLogging,
|
||||
};
|
||||
|
||||
if ui.add(button).clicked() {
|
||||
self.log_tx.try_send(signal).unwrap_or_else(|e| {
|
||||
error!("Failed to send logging toggle signal: {:?}", e);
|
||||
});
|
||||
};
|
||||
|
||||
ui.separator();
|
||||
|
||||
ui.add_enabled_ui(on && logging_enabled, |ui| {
|
||||
if Button::new("Add marker").corner_radius(5.0).min_size(egui::vec2(20.0, 0.0)).ui(ui).on_hover_text("Add a marker to the current time series plots").clicked() {
|
||||
self.log_marker_modal = true;
|
||||
}
|
||||
});
|
||||
|
||||
if self.log_marker_modal {
|
||||
if Modal::new(Id::new("modal_marker"))
|
||||
.show(ctx, |ui| {
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.heading("Add marker");
|
||||
|
||||
ui.add_space(16.0);
|
||||
|
||||
// Input field for marker
|
||||
let text_edit_response = TextEdit::singleline(&mut self.log_marker)
|
||||
.desired_width(100.0)
|
||||
.id(Id::new("marker_field"))
|
||||
.hint_text("Marker name")
|
||||
.ui(ui);
|
||||
|
||||
ui.add_space(16.0);
|
||||
|
||||
// Centered Add button
|
||||
let add_clicked = Button::new("Add")
|
||||
.corner_radius(5.0)
|
||||
.min_size(egui::vec2(80.0, 30.0))
|
||||
.ui(ui)
|
||||
.clicked();
|
||||
|
||||
// Check for Enter key in the TextEdit
|
||||
let enter_pressed = text_edit_response.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter));
|
||||
|
||||
if add_clicked || enter_pressed {
|
||||
info!("Adding marker: {}", self.log_marker);
|
||||
self.log_tx.try_send(LoggingSignal::AddMarker(self.log_marker.clone())).unwrap_or_else(|e| {
|
||||
error!("Failed to send logging marker signal: {:?}", e);
|
||||
});
|
||||
self.log_marker = String::new();
|
||||
ui.close();
|
||||
}
|
||||
|
||||
// Request focus on the text edit when the modal opens
|
||||
text_edit_response.request_focus();
|
||||
});
|
||||
})
|
||||
.should_close()
|
||||
{
|
||||
self.log_marker_modal = false;
|
||||
self.log_marker = String::new();
|
||||
}
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
|
||||
ui.add_enabled_ui(gui_logging_state == LoggingStates::Idle, |ui| {
|
||||
ui.label("Log filename:");
|
||||
TextEdit::singleline(&mut self.log_filename).desired_width(125.0).id(Id::new("file_name_field")).ui(ui);
|
||||
TextEdit::singleline(&mut self.log_filename).desired_width(150.0).id(Id::new("file_name_field")).ui(ui);
|
||||
});
|
||||
|
||||
// Spacer to push the LED to the right
|
||||
@@ -691,6 +763,12 @@ impl eframe::App for App {
|
||||
self.tab_active = TabActive::Single;
|
||||
*self.on.lock().unwrap() = false;
|
||||
self.update_start_stop();
|
||||
if *self.gui_logging_state.lock().unwrap() == LoggingStates::Logging {
|
||||
self.log_tx.try_send(LoggingSignal::StopFileLogging).unwrap_or_else(|e| {
|
||||
error!("Failed to send logging logging signal: {:?}", e);
|
||||
});
|
||||
}
|
||||
self.log_filename = format!("log_{}_single.csv", Local::now().format("%Y%m%d"));
|
||||
info!("Switched to Single tab");
|
||||
}
|
||||
}
|
||||
@@ -699,6 +777,12 @@ impl eframe::App for App {
|
||||
self.tab_active = TabActive::Sweep;
|
||||
*self.on.lock().unwrap() = false;
|
||||
self.update_start_stop();
|
||||
if *self.gui_logging_state.lock().unwrap() == LoggingStates::Logging {
|
||||
self.log_tx.try_send(LoggingSignal::StopFileLogging).unwrap_or_else(|e| {
|
||||
error!("Failed to send logging logging signal: {:?}", e);
|
||||
});
|
||||
}
|
||||
self.log_filename = format!("log_{}_sweep.csv", Local::now().format("%Y%m%d"));
|
||||
info!("Switched to Sweep tab");
|
||||
}
|
||||
}
|
||||
@@ -725,7 +809,8 @@ impl eframe::App for App {
|
||||
// Check if the file name field is focused
|
||||
// If it is, we don't want to trigger shortcuts
|
||||
let file_name_field_is_focused = ctx.memory(|memory| memory.has_focus(Id::new("file_name_field")));
|
||||
if !file_name_field_is_focused {
|
||||
let marker_field_is_focused = ctx.memory(|memory| memory.has_focus(Id::new("marker_field")));
|
||||
if !file_name_field_is_focused && !marker_field_is_focused {
|
||||
|
||||
// Space to start/stop measurement
|
||||
if ctx.input(|i| i.key_pressed(Key::Space))
|
||||
@@ -746,6 +831,11 @@ impl eframe::App for App {
|
||||
self.reset_view();
|
||||
}
|
||||
|
||||
// Toggle marker modal
|
||||
if ctx.input(|i| i.key_pressed(egui::Key::A)) && *self.gui_logging_state.lock().unwrap() == LoggingStates::Logging {
|
||||
self.log_marker_modal = !self.log_marker_modal;
|
||||
}
|
||||
|
||||
// Enable/disable GUI logging
|
||||
if ctx.input(|i| i.key_pressed(egui::Key::L)) {
|
||||
let gui_logging_enabled = *self.gui_logging_state.lock().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user