use crate::config::SharedConfig;
use crate::spawn_transaction_no_commit_send_result;
use eframe::egui::{Align, Context, Layout, ScrollArea, Ui};
use egui_extras::{Column, TableBuilder};
use open_timeline_crud::{CrudError, DatabaseRowCount};
use open_timeline_gui_core::{Draw, Reload, body_text_height, widget_x_spacing};
use std::sync::Arc;
use tokio::sync::mpsc::Receiver;
use tokio::sync::mpsc::error::TryRecvError;
#[derive(Debug)]
pub struct StatsGui {
table_row_counts: Option<DatabaseRowCount>,
rx_reload: Option<Receiver<Result<DatabaseRowCount, CrudError>>>,
requested_reload: bool,
shared_config: SharedConfig,
}
impl StatsGui {
pub fn new(shared_config: SharedConfig) -> Self {
let mut stats_gui = Self {
table_row_counts: None,
rx_reload: None,
requested_reload: false,
shared_config,
};
stats_gui.request_reload();
stats_gui
}
}
impl Reload for StatsGui {
fn request_reload(&mut self) {
self.requested_reload = true;
let (tx, rx) = tokio::sync::mpsc::channel(1);
self.rx_reload = Some(rx);
let shared_config = Arc::clone(&self.shared_config);
spawn_transaction_no_commit_send_result!(
shared_config,
bounded,
tx,
|transaction| async move {
DatabaseRowCount::all(transaction).await
}
);
}
fn check_reload_response(&mut self) {
if let Some(rx) = self.rx_reload.as_mut() {
match rx.try_recv() {
Ok(msg) => match msg {
Ok(row_counts) => {
self.table_row_counts = Some(row_counts);
self.rx_reload = None;
self.requested_reload = false;
}
Err(_) => todo!(),
},
Err(TryRecvError::Empty) => (),
Err(TryRecvError::Disconnected) => (),
}
}
}
}
impl Draw for StatsGui {
fn draw(&mut self, _ctx: &Context, ui: &mut Ui) {
self.check_reload_response();
if let Some(row_counts) = self.table_row_counts.as_ref() {
let row_height = body_text_height(ui);
let spacing = widget_x_spacing(ui);
let available_width = ui.available_width();
let count_width = 100.0;
let table_name_width = available_width - count_width - spacing;
let table_name_width = table_name_width.max(0.0);
let counts = vec![
(row_counts.entities, "Entities"),
(row_counts.entity_tags, "Entity Tags"),
(row_counts.timelines, "Timelines"),
(row_counts.subtimelines, "Subtimelines"),
(row_counts.timeline_entities, "Timeline Entities"),
(row_counts.timeline_tags, "Timeline Tags"),
];
TableBuilder::new(ui)
.id_salt("stats_table_header")
.striped(true)
.column(Column::exact(count_width))
.column(Column::exact(table_name_width))
.header(row_height, |mut row| {
row.col(|ui| {
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
open_timeline_gui_core::Label::sub_heading(ui, "Count");
});
});
row.col(|ui| {
ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
open_timeline_gui_core::Label::sub_heading(ui, "Type");
});
});
});
ScrollArea::vertical().show(ui, |ui| {
TableBuilder::new(ui)
.id_salt("stats_table_body")
.striped(true)
.column(Column::exact(count_width))
.column(Column::exact(table_name_width))
.body(|mut body| {
for count in counts {
body.row(row_height, |mut row| {
row.col(|ui| {
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
ui.label(format!("{}", count.0))
});
});
row.col(|ui| {
ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
ui.label(count.1)
});
});
});
}
});
});
}
}
}