runmat_plot/gui/
single_window_manager.rs1use crate::gui::lifecycle::CloseSignal;
7use crate::gui::window::WindowConfig;
8use crate::plots::Figure;
9use std::sync::atomic::{AtomicBool, Ordering};
10use std::sync::Mutex;
11
12static WINDOW_ACTIVE: AtomicBool = AtomicBool::new(false);
14
15static WINDOW_MANAGER: Mutex<()> = Mutex::new(());
17
18pub fn show_plot_sequential(figure: Figure) -> Result<String, String> {
20 show_plot_sequential_with_signal(figure, None)
21}
22
23pub fn show_plot_sequential_with_signal(
27 figure: Figure,
28 close_signal: Option<CloseSignal>,
29) -> Result<String, String> {
30 let title = figure.window_title(None);
31 show_plot_sequential_with_signal_and_title(figure, close_signal, Some(title))
32}
33
34pub fn show_plot_sequential_with_signal_and_title(
35 figure: Figure,
36 close_signal: Option<CloseSignal>,
37 window_title: Option<String>,
38) -> Result<String, String> {
39 let _guard = WINDOW_MANAGER
41 .lock()
42 .map_err(|_| "Window manager lock failed".to_string())?;
43
44 if WINDOW_ACTIVE.load(Ordering::Acquire) {
46 return Err("Another plot window is already open. Please close it first.".to_string());
47 }
48
49 WINDOW_ACTIVE.store(true, Ordering::Release);
51
52 let result = show_plot_internal(figure, close_signal, window_title);
53
54 WINDOW_ACTIVE.store(false, Ordering::Release);
56
57 result
58}
59
60fn show_plot_internal(
62 figure: Figure,
63 close_signal: Option<CloseSignal>,
64 window_title: Option<String>,
65) -> Result<String, String> {
66 use crate::gui::PlotWindow;
67
68 let mut config = WindowConfig::default();
70 if let Some(title) = window_title {
71 config.title = title;
72 }
73
74 let handle = tokio::runtime::Handle::try_current();
76
77 match handle {
78 Ok(handle) => {
79 tokio::task::block_in_place(|| {
81 handle.block_on(async {
82 let mut window = PlotWindow::new(config)
83 .await
84 .map_err(|e| format!("Failed to create plot window: {e}"))?;
85
86 if let Some(signal) = close_signal.clone() {
87 window.install_close_signal(signal);
88 }
89
90 window.set_figure(figure);
92
93 window
95 .run()
96 .await
97 .map_err(|e| format!("Window execution failed: {e}"))?;
98
99 Ok("Plot window closed successfully".to_string())
100 })
101 })
102 }
103 Err(_) => {
104 let rt = tokio::runtime::Runtime::new()
106 .map_err(|e| format!("Failed to create async runtime: {e}"))?;
107
108 rt.block_on(async {
109 let mut window = PlotWindow::new(config)
110 .await
111 .map_err(|e| format!("Failed to create plot window: {e}"))?;
112
113 if let Some(signal) = close_signal {
114 window.install_close_signal(signal);
115 }
116
117 window.set_figure(figure);
119
120 window
122 .run()
123 .await
124 .map_err(|e| format!("Window execution failed: {e}"))?;
125
126 Ok("Plot window closed successfully".to_string())
127 })
128 }
129 }
130}
131
132pub fn is_window_available() -> bool {
134 !WINDOW_ACTIVE.load(Ordering::Acquire)
135}