use std::fmt::{Debug, Formatter};
use tokio::sync::mpsc::Sender;
use super::TerminalWindowMainThreadSignal;
use crate::{ok, spinner_impl, telemetry::telemetry_sizing::TelemetryReportLineStorage,
ChUnit, CommonResult, InlineString, OffscreenBuffer, OffscreenBufferPool,
OutputDevice, Size, SpinnerStyle, TelemetryHudReport, DEBUG_TUI_COMPOSITOR,
DEBUG_TUI_MOD};
pub struct GlobalData<S, AS>
where
S: Debug + Default + Clone + Sync + Send,
AS: Debug + Default + Clone + Sync + Send,
{
pub window_size: Size,
pub maybe_saved_offscreen_buffer: Option<OffscreenBuffer>,
pub main_thread_channel_sender: Sender<TerminalWindowMainThreadSignal<AS>>,
pub state: S,
pub output_device: OutputDevice,
pub offscreen_buffer_pool: OffscreenBufferPool,
pub hud_report: TelemetryReportLineStorage,
pub spinner_helper: SpinnerHelper,
}
#[derive(Debug, Default)]
pub struct SpinnerHelper {
pub spinner_style: SpinnerStyle,
pub count: ChUnit,
pub empty_message: InlineString,
}
impl<S, AS> Debug for GlobalData<S, AS>
where
S: Debug + Default + Clone + Sync + Send,
AS: Debug + Default + Clone + Sync + Send,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "GlobalData")?;
write!(f, "\n - window_size: {:?}", self.window_size)?;
write!(f, "\n - ")?;
match &self.maybe_saved_offscreen_buffer {
None => write!(f, "no saved offscreen_buffer")?,
Some(offscreen_buffer) => {
if DEBUG_TUI_COMPOSITOR {
write!(f, "{offscreen_buffer:?}")?;
} else {
write!(f, "offscreen_buffer saved from previous render")?;
}
}
}
ok!()
}
}
impl<S, AS> GlobalData<S, AS>
where
S: Debug + Default + Clone + Sync + Send,
AS: Debug + Default + Clone + Sync + Send,
{
pub fn try_to_create_instance(
main_thread_channel_sender: Sender<TerminalWindowMainThreadSignal<AS>>,
state: S,
initial_size: Size,
output_device: OutputDevice,
offscreen_buffer_pool: OffscreenBufferPool,
) -> CommonResult<GlobalData<S, AS>>
where
AS: Debug + Default + Clone + Sync + Send,
{
let mut it = GlobalData {
window_size: Size::default(),
maybe_saved_offscreen_buffer: Option::default(),
state,
main_thread_channel_sender,
output_device,
offscreen_buffer_pool,
hud_report: TelemetryReportLineStorage::new(),
spinner_helper: SpinnerHelper::default(),
};
it.set_size(initial_size);
Ok(it)
}
pub fn set_size(&mut self, new_size: Size) {
self.window_size = new_size;
DEBUG_TUI_MOD.then(|| {
tracing::info!(
message = "main_event_loop -> Resize ⇲",
new_size = ?new_size
);
});
}
pub fn get_size(&self) -> Size { self.window_size }
pub fn set_hud_report(&mut self, new: TelemetryHudReport) {
use std::fmt::Write;
self.hud_report.clear();
write!(self.hud_report, "{new}").ok();
}
const EMPTY_HUD_REPORT_STATIC: &str = "⮺ Collecting data ⠎";
const EMPTY_HUD_REPORT_PREFIX_SPINNER: &str = "⮺ Collecting data ";
pub fn get_hud_report_no_spinner(&self) -> &str {
if self.hud_report.is_empty() {
Self::EMPTY_HUD_REPORT_STATIC
} else {
&self.hud_report
}
}
pub fn get_hud_report_with_spinner(&mut self) -> &str {
use std::fmt::Write;
if self.hud_report.is_empty() {
let count = self.spinner_helper.count;
let style = &mut self.spinner_helper.spinner_style;
let spinner_glyph = spinner_impl::spinner_render::get_next_tick_glyph(
style,
count.as_usize(),
);
self.spinner_helper.empty_message.clear();
write!(
self.spinner_helper.empty_message,
"{a}{b}",
a = Self::EMPTY_HUD_REPORT_PREFIX_SPINNER,
b = spinner_glyph,
).ok();
self.spinner_helper.count += 1;
&self.spinner_helper.empty_message
} else {
&self.hud_report
}
}
}