1#![doc = include_str!("../README.md")]
2
3use std::cell::RefCell;
4
5use winit::{
6 event_loop::{ControlFlow, EventLoop},
7 platform::run_on_demand::EventLoopExtRunOnDemand,
8};
9
10pub use dialog::Dialog;
11pub use egui;
12pub use egui::{Color32, RichText};
13pub use winit::{
14 self,
15 dpi::{LogicalSize, PhysicalSize},
16 window::{Icon, WindowAttributes},
17};
18
19pub mod dialog;
20mod renderer;
21mod window;
22
23thread_local! {
24static EVENT_LOOP: RefCell<Option<EventLoop<()>>> = const { RefCell::new(None) };
25}
26
27#[derive(thiserror::Error, Debug)]
29#[non_exhaustive]
30pub enum Error {
31 #[error("failed to run event loop {0:?}")]
32 EventLoop(#[from] winit::error::EventLoopError),
33 #[error("failed to find an appropriate wgpu adapter")]
34 FailedToFindAdapter,
35
36 #[error("failed select appropriate surface texture format")]
37 FailedToSelectSurfaceTextureFormat,
38
39 #[error("failed to request wgpu device {0:?}")]
40 FailedToRequestDevice(#[from] egui_wgpu::wgpu::RequestDeviceError),
41
42 #[error("failed to create wgpu surface {0:?}")]
43 FailedToCreateSurface(#[from] egui_wgpu::wgpu::CreateSurfaceError),
44
45 #[error("failed to acquire next swapchain texture {0:?}")]
46 SwapchainError(#[from] egui_wgpu::wgpu::SurfaceError),
47}
48pub type Result<T, E = Error> = std::result::Result<T, E>;
49
50pub fn create_window<F, R>(draw: F, info: WindowAttributes) -> Result<Option<R>>
61where
62 F: FnMut(&mut egui::Ui) -> Option<R>,
63{
64 EVENT_LOOP
66 .try_with(|ev_cell| {
67 let mut ev_cell = ev_cell.borrow_mut();
68 if ev_cell.is_none() {
69 let ev = EventLoop::new()?;
70 ev.set_control_flow(ControlFlow::Poll);
71 ev_cell.replace(ev);
72 }
73 let mut app = window::PopupWindow::new(draw, info);
74
75 ev_cell.as_mut().unwrap().run_app_on_demand(&mut app)?;
76
77 if let Some(e) = app.error {
78 Err(e)
79 } else {
80 Ok(app.draw_result)
81 }
82 })
83 .unwrap()
84}