use crate::gui::lifecycle::CloseSignal;
use crate::gui::window::WindowConfig;
use crate::plots::Figure;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex;
static WINDOW_ACTIVE: AtomicBool = AtomicBool::new(false);
static WINDOW_MANAGER: Mutex<()> = Mutex::new(());
pub fn show_plot_sequential(figure: Figure) -> Result<String, String> {
show_plot_sequential_with_signal(figure, None)
}
pub fn show_plot_sequential_with_signal(
figure: Figure,
close_signal: Option<CloseSignal>,
) -> Result<String, String> {
let _guard = WINDOW_MANAGER
.lock()
.map_err(|_| "Window manager lock failed".to_string())?;
if WINDOW_ACTIVE.load(Ordering::Acquire) {
return Err("Another plot window is already open. Please close it first.".to_string());
}
WINDOW_ACTIVE.store(true, Ordering::Release);
let result = show_plot_internal(figure, close_signal);
WINDOW_ACTIVE.store(false, Ordering::Release);
result
}
fn show_plot_internal(figure: Figure, close_signal: Option<CloseSignal>) -> Result<String, String> {
use crate::gui::PlotWindow;
let config = WindowConfig::default();
let handle = tokio::runtime::Handle::try_current();
match handle {
Ok(handle) => {
tokio::task::block_in_place(|| {
handle.block_on(async {
let mut window = PlotWindow::new(config)
.await
.map_err(|e| format!("Failed to create plot window: {e}"))?;
if let Some(signal) = close_signal.clone() {
window.install_close_signal(signal);
}
window.set_figure(figure);
window
.run()
.await
.map_err(|e| format!("Window execution failed: {e}"))?;
Ok("Plot window closed successfully".to_string())
})
})
}
Err(_) => {
let rt = tokio::runtime::Runtime::new()
.map_err(|e| format!("Failed to create async runtime: {e}"))?;
rt.block_on(async {
let mut window = PlotWindow::new(config)
.await
.map_err(|e| format!("Failed to create plot window: {e}"))?;
if let Some(signal) = close_signal {
window.install_close_signal(signal);
}
window.set_figure(figure);
window
.run()
.await
.map_err(|e| format!("Window execution failed: {e}"))?;
Ok("Plot window closed successfully".to_string())
})
}
}
}
pub fn is_window_available() -> bool {
!WINDOW_ACTIVE.load(Ordering::Acquire)
}