Skip to content

Commit

Permalink
Removes App trait (#1189)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Dec 17, 2024
1 parent 102ebc5 commit d81f3dd
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 66 deletions.
58 changes: 24 additions & 34 deletions gui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use self::data::{DataError, DataMgr};
use self::graphics::{Graphics, GraphicsError, PhysicalDevice};
use self::profile::Profile;
use self::setup::{run_setup, SetupError};
use self::ui::{ErrorWindow, MainWindow, ProfileModel, ResolutionModel, RuntimeExt, SlintBackend};
use self::ui::{MainWindow, ProfileModel, ResolutionModel, RuntimeExt, SlintBackend};
use clap::{Parser, ValueEnum};
use debug::DebugServer;
use erdp::ErrorDisplay;
use slint::{ComponentHandle, ModelRc, SharedString, VecModel};
use slint::{ComponentHandle, ModelRc, SharedString, VecModel, WindowHandle};
use std::cell::Cell;
use std::error::Error;
use std::net::SocketAddrV4;
Expand Down Expand Up @@ -75,10 +75,22 @@ fn main() -> ExitCode {
}

// Run.
let app = Rc::new(App { args, exe });
let main = async move {
let e = match run(args, exe).await {
Ok(_) => return ExitCode::SUCCESS,
Err(e) => e,
};

// Show error window.
let msg = format!("An unexpected error has occurred: {}.", e.display());

self::ui::error::<WindowHandle>(None, msg).await;

match self::rt::run(app.clone(), run(app)) {
Ok(_) => ExitCode::SUCCESS,
ExitCode::FAILURE
};

match self::rt::run(main) {
Ok(v) => v,
Err(e) => {
error(format!(
"Failed to run application runtime: {}.",
Expand All @@ -90,7 +102,7 @@ fn main() -> ExitCode {
}
}

async fn run(app: Rc<App>) -> Result<(), ProgramError> {
async fn run(args: ProgramArgs, exe: PathBuf) -> Result<(), ProgramError> {
// Setup Slint back-end. This need to be done before using any Slint API.
slint::platform::set_platform(Box::new(SlintBackend::new())).unwrap();

Expand All @@ -108,9 +120,9 @@ async fn run(app: Rc<App>) -> Result<(), ProgramError> {
};

// Get kernel path.
let kernel = app.args.kernel.as_ref().cloned().unwrap_or_else(|| {
let kernel = args.kernel.as_ref().cloned().unwrap_or_else(|| {
// Get kernel directory.
let mut path = app.exe.parent().unwrap().to_owned();
let mut path = exe.parent().unwrap().to_owned();

#[cfg(target_os = "windows")]
path.push("share");
Expand Down Expand Up @@ -158,11 +170,11 @@ async fn run(app: Rc<App>) -> Result<(), ProgramError> {
}

// Get profile to use.
let (profile, debug) = if let Some(v) = app.args.debug {
let (profile, debug) = if let Some(v) = args.debug {
// TODO: Select last used profile.
(profiles.pop().unwrap(), Some(v))
} else {
let (profile, exit) = match run_launcher(&graphics, &data, profiles)? {
let (profile, exit) = match run_launcher(&graphics, &data, profiles).await? {
Some(v) => v,
None => return Ok(()),
};
Expand Down Expand Up @@ -195,7 +207,7 @@ async fn run(app: Rc<App>) -> Result<(), ProgramError> {
todo!()
}

fn run_launcher(
async fn run_launcher(
graphics: &impl Graphics,
data: &Arc<DataMgr>,
profiles: Vec<Profile>,
Expand Down Expand Up @@ -285,7 +297,7 @@ fn run_launcher(
profiles.select(row, &win);

// Run the window.
win.run().map_err(ProgramError::RunMainWindow)?;
win.exec().await.map_err(ProgramError::RunMainWindow)?;

// Update selected profile.
let profile = win.get_selected_profile();
Expand Down Expand Up @@ -335,28 +347,6 @@ enum ProgramMode {
PanicHandler,
}

/// Implementation of [`self::rt::App`] for main program mode.
struct App {
args: ProgramArgs,
exe: PathBuf,
}

impl self::rt::App for App {
async fn error(&self, e: impl Error) {
// Show error window.
let win = ErrorWindow::new().unwrap();

win.set_message(format!("An unexpected error has occurred: {}.", e.display()).into());
win.on_close({
let win = win.as_weak();

move || win.unwrap().hide().unwrap()
});

win.exec().await.unwrap();
}
}

/// Represents an error when our program fails.
#[derive(Debug, Error)]
enum ProgramError {
Expand Down
6 changes: 0 additions & 6 deletions gui/src/rt/app.rs

This file was deleted.

37 changes: 12 additions & 25 deletions gui/src/rt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
pub use self::app::*;
pub use self::window::*;

use self::context::Context;
use self::event::WindowEvent;
use self::task::TaskList;
use self::waker::Waker;
use std::cell::Cell;
use std::collections::HashMap;
use std::error::Error;
use std::future::Future;
Expand All @@ -16,32 +16,22 @@ use winit::error::{EventLoopError, OsError};
use winit::event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy};
use winit::window::{Window, WindowAttributes, WindowId};

mod app;
mod context;
mod event;
mod task;
mod waker;
mod window;

pub fn run<E, A>(
app: Rc<A>,
main: impl Future<Output = Result<(), E>> + 'static,
) -> Result<(), RuntimeError>
where
E: Error,
A: App,
{
pub fn run<T: 'static>(main: impl Future<Output = T> + 'static) -> Result<T, RuntimeError> {
// Setup winit event loop.
let mut el = EventLoop::<Event>::with_user_event();
let el = el.build().map_err(RuntimeError::CreateEventLoop)?;
let exit: Rc<Cell<Option<Result<T, RuntimeError>>>> = Rc::default();
let main = {
let app = app.clone();
let exit = exit.clone();

async move {
if let Err(e) = main.await {
app.error(e).await;
}

exit.set(Some(Ok(main.await)));
Context::with(|cx| cx.el.exit());
}
};
Expand All @@ -56,15 +46,12 @@ where
main,
windows: HashMap::default(),
on_close: WindowEvent::default(),
error: None,
exit,
};

el.run_app(&mut rt).map_err(RuntimeError::RunEventLoop)?;

match rt.error {
Some(e) => Err(e),
None => Ok(()),
}
rt.exit.take().unwrap()
}

/// # Panics
Expand Down Expand Up @@ -109,16 +96,16 @@ pub fn on_close(win: WindowId) -> impl Future<Output = ()> {
}

/// Implementation of [`ApplicationHandler`] to drive [`Future`].
struct Runtime {
struct Runtime<T> {
el: EventLoopProxy<Event>,
tasks: TaskList,
main: u64,
windows: HashMap<WindowId, Weak<dyn RuntimeWindow>>,
on_close: WindowEvent<()>,
error: Option<RuntimeError>,
exit: Rc<Cell<Option<Result<T, RuntimeError>>>>,
}

impl Runtime {
impl<T> Runtime<T> {
fn dispatch_task(&mut self, el: &ActiveEventLoop, id: u64) -> bool {
// Take target task so can mutable borrow the task list for context.
let mut task = match self.tasks.remove(id) {
Expand Down Expand Up @@ -181,7 +168,7 @@ impl Runtime {
}
}

impl ApplicationHandler<Event> for Runtime {
impl<T> ApplicationHandler<Event> for Runtime<T> {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
assert!(self.dispatch_task(event_loop, self.main));
}
Expand Down Expand Up @@ -233,7 +220,7 @@ impl ApplicationHandler<Event> for Runtime {
};

// Store error then exit.
self.error = Some(e);
self.exit.set(Some(Err(e)));

el.exit();
}
Expand Down
19 changes: 18 additions & 1 deletion gui/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,28 @@ pub use self::profile::*;

use i_slint_core::window::WindowInner;
use i_slint_core::InternalToken;
use slint::ComponentHandle;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use slint::{ComponentHandle, SharedString};

mod backend;
mod profile;

pub async fn error<T>(parent: Option<&T>, msg: impl Into<SharedString>)
where
T: HasDisplayHandle + HasWindowHandle,
{
let win = ErrorWindow::new().unwrap();

win.set_message(msg.into());
win.on_close({
let win = win.as_weak();

move || win.unwrap().hide().unwrap()
});

win.exec().await.unwrap();
}

/// Provides methods for [`ComponentHandle`] to work with our async runtime.
pub trait RuntimeExt: ComponentHandle {
async fn exec(&self) -> Result<(), slint::PlatformError>;
Expand Down

0 comments on commit d81f3dd

Please sign in to comment.