use egui;
use egui_mobius::{Dispatcher, Signal, SignalDispatcher, Slot};
use crate::components::event_logger::log_colors::LogColors;
use crate::components::event_logger::log_type::LogType;
use crate::components::event_logger::logger_state::LoggerState;
use crate::components::event_logger::messages::{
LogEntry, LogSender, LoggerEvent, LoggerResponse, Message,
};
#[allow(dead_code)]
#[derive(Clone)]
pub struct EguiMobiusEventLogger {
dispatcher: Dispatcher<LoggerEvent>,
response_slot: Option<Slot<LoggerResponse>>,
ctx: egui::Context,
}
impl Default for EguiMobiusEventLogger {
fn default() -> Self {
let dispatcher = Dispatcher::<LoggerEvent>::new();
let ctx = egui::Context::default();
crate::components::event_logger::processor::init_logger_backend(LogColors::default());
Self::new(ctx, LogColors::default(), dispatcher, None)
}
}
impl EguiMobiusEventLogger {
pub fn new(
ctx: egui::Context,
colors: LogColors,
dispatcher: Dispatcher<LoggerEvent>,
response_slot: Option<Slot<LoggerResponse>>,
) -> Self {
crate::components::event_logger::processor::init_logger_backend(colors.clone());
if let Some(mut slot) = response_slot.clone() {
let ctx_clone = ctx.clone();
slot.start(move |_response| {
ctx_clone.request_repaint();
});
}
dispatcher.register_slot("logger_events", move |_event| {
});
Self {
dispatcher,
response_slot,
ctx,
}
}
pub fn add_log(&self, msg: Message, sender: LogSender, style_type: LogType) {
self.dispatcher.send(
"logger_events",
LoggerEvent::AddEntry(msg, sender, style_type),
);
}
pub fn info(&self, msg: String, sender: LogSender, style_type: LogType) {
self.add_log(Message::Info(msg), sender, style_type);
}
pub fn warn(&self, msg: String, sender: LogSender, style_type: LogType) {
self.add_log(Message::Warn(msg), sender, style_type);
}
pub fn debug(&self, msg: String, sender: LogSender, style_type: LogType) {
self.add_log(Message::Debug(msg), sender, style_type);
}
pub fn error(&self, msg: String, sender: LogSender, style_type: LogType) {
self.add_log(Message::Error(msg), sender, style_type);
}
pub fn clear(&self) {
self.dispatcher.send("logger_events", LoggerEvent::ClearLog);
}
pub fn update_colors(&self, new_colors: LogColors) {
self.dispatcher
.send("logger_events", LoggerEvent::UpdateColors(new_colors));
}
pub fn toggle_timestamps(&self, show: bool) {
self.dispatcher
.send("logger_events", LoggerEvent::ToggleTimestamps(show));
}
pub fn toggle_messages(&self, show: bool) {
self.dispatcher
.send("logger_events", LoggerEvent::ToggleMessages(show));
}
pub fn export_recent(&self, count: usize) -> Vec<LogEntry> {
self.dispatcher
.send("logger_events", LoggerEvent::ExportRecent(count));
let state = crate::components::event_logger::processor::LOGGER_STATE
.lock()
.unwrap();
state.export_recent(count)
}
pub fn show(&self, ui: &mut egui::Ui) {
ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.label("Display columns:");
let (show_timestamps, show_messages) = {
let state = crate::components::event_logger::processor::LOGGER_STATE
.lock()
.unwrap();
(state.show_timestamps, state.show_messages)
};
let mut ts_value = show_timestamps;
if ui.checkbox(&mut ts_value, "Timestamps").changed() {
self.toggle_timestamps(ts_value);
}
let mut msg_value = show_messages;
if ui.checkbox(&mut msg_value, "Messages").changed() {
self.toggle_messages(msg_value);
}
});
let state = crate::components::event_logger::processor::LOGGER_STATE
.lock()
.unwrap();
self.show_event_log_content(ui, &state);
});
}
fn show_event_log_content(&self, ui: &mut egui::Ui, state: &LoggerState) {
let show_timestamps = state.show_timestamps;
let show_messages = state.show_messages;
if show_timestamps && show_messages {
egui::ScrollArea::vertical()
.auto_shrink([false, false])
.stick_to_bottom(true)
.show(ui, |ui| {
egui::Grid::new("logger_grid")
.num_columns(2)
.spacing([10.0, 6.0])
.striped(true)
.show(ui, |ui| {
ui.strong("Time");
ui.strong("Message");
ui.end_row();
for entry in state.logs.iter().rev() {
let (timestamp, message) = state.format_log_entry(entry);
ui.label(timestamp);
ui.label(message);
ui.end_row();
}
});
});
} else if show_timestamps {
egui::ScrollArea::vertical()
.auto_shrink([false, false])
.stick_to_bottom(true)
.show(ui, |ui| {
for entry in state.logs.iter().rev() {
let (timestamp, _) = state.format_log_entry(entry);
ui.label(timestamp);
}
});
} else if show_messages {
egui::ScrollArea::vertical()
.auto_shrink([false, false])
.stick_to_bottom(true)
.show(ui, |ui| {
for entry in state.logs.iter().rev() {
let (_, message) = state.format_log_entry(entry);
ui.label(message);
}
});
} else {
ui.label("No columns selected");
}
}
}
pub fn create_event_logger(
ctx: egui::Context,
colors: LogColors,
) -> (
EguiMobiusEventLogger,
Slot<LoggerEvent>,
Signal<LoggerResponse>,
) {
let (_event_signal, event_slot) = egui_mobius::factory::create_signal_slot::<LoggerEvent>();
let (response_signal, response_slot) =
egui_mobius::factory::create_signal_slot::<LoggerResponse>();
crate::components::event_logger::processor::init_logger_backend(colors.clone());
let dispatcher = Dispatcher::<LoggerEvent>::new();
let response_signal_clone = response_signal.clone();
dispatcher.register_slot("logger_events", move |event| {
let response = crate::components::event_logger::processor::process_event(event);
if let Err(e) = response_signal_clone.send(response) {
eprintln!("Failed to send logger response: {e:?}");
}
});
let logger = EguiMobiusEventLogger::new(ctx, colors, dispatcher, Some(response_slot));
(logger, event_slot, response_signal)
}