eframe: allow aborting an exit event (#1038)
This commit is contained in:
parent
87ac7446da
commit
ab77099781
4 changed files with 79 additions and 4 deletions
|
@ -9,6 +9,7 @@ NOTE: [`egui_web`](egui_web/CHANGELOG.md), [`egui-winit`](egui-winit/CHANGELOG.m
|
|||
* The default native backend is now `egui_glow` (instead of `egui_glium`) ([#1020](https://github.com/emilk/egui/pull/1020)).
|
||||
* The default web painter is now `egui_glow` (instead of WebGL) ([#1020](https://github.com/emilk/egui/pull/1020)).
|
||||
* Fix horizontal scrolling direction on Linux.
|
||||
* Added `App::on_exit_event` ([#1038](https://github.com/emilk/egui/pull/1038))
|
||||
|
||||
|
||||
## 0.16.0 - 2021-12-29
|
||||
|
|
49
eframe/examples/confirm_exit.rs
Normal file
49
eframe/examples/confirm_exit.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
|
||||
use eframe::{egui, epi};
|
||||
|
||||
#[derive(Default)]
|
||||
struct MyApp {
|
||||
can_exit: bool,
|
||||
is_exiting: bool,
|
||||
}
|
||||
|
||||
impl epi::App for MyApp {
|
||||
fn name(&self) -> &str {
|
||||
"Confirm exit"
|
||||
}
|
||||
|
||||
fn on_exit_event(&mut self) -> bool {
|
||||
self.is_exiting = true;
|
||||
self.can_exit
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &epi::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("Try to close the window");
|
||||
});
|
||||
|
||||
if self.is_exiting {
|
||||
egui::Window::new("Do you want to quit?")
|
||||
.collapsible(false)
|
||||
.resizable(false)
|
||||
.show(ctx, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Yes!").clicked() {
|
||||
self.can_exit = true;
|
||||
frame.quit();
|
||||
}
|
||||
|
||||
if ui.button("Not yet").clicked() {
|
||||
self.is_exiting = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let options = eframe::NativeOptions::default();
|
||||
eframe::run_native(Box::new(MyApp::default()), options);
|
||||
}
|
|
@ -240,7 +240,11 @@ impl EpiIntegration {
|
|||
self.app
|
||||
.setup(&self.egui_ctx, &self.frame, self.persistence.storage());
|
||||
let app_output = self.frame.take_app_output();
|
||||
self.quit |= app_output.quit;
|
||||
|
||||
if app_output.quit {
|
||||
self.quit = self.app.on_exit_event();
|
||||
}
|
||||
|
||||
crate::epi::handle_app_output(window, self.egui_ctx.pixels_per_point(), app_output);
|
||||
}
|
||||
|
||||
|
@ -260,7 +264,12 @@ impl EpiIntegration {
|
|||
|
||||
pub fn on_event(&mut self, event: &winit::event::WindowEvent<'_>) {
|
||||
use winit::event::WindowEvent;
|
||||
self.quit |= matches!(event, WindowEvent::CloseRequested | WindowEvent::Destroyed);
|
||||
if *event == WindowEvent::CloseRequested {
|
||||
self.quit = self.app.on_exit_event();
|
||||
} else if *event == WindowEvent::Destroyed {
|
||||
self.quit = true;
|
||||
}
|
||||
|
||||
self.egui_winit.on_event(&self.egui_ctx, event);
|
||||
}
|
||||
|
||||
|
@ -282,7 +291,10 @@ impl EpiIntegration {
|
|||
.handle_output(window, &self.egui_ctx, egui_output);
|
||||
|
||||
let app_output = self.frame.take_app_output();
|
||||
self.quit |= app_output.quit;
|
||||
|
||||
if app_output.quit {
|
||||
self.quit = self.app.on_exit_event();
|
||||
}
|
||||
|
||||
crate::epi::handle_app_output(window, self.egui_ctx.pixels_per_point(), app_output);
|
||||
|
||||
|
|
|
@ -144,7 +144,20 @@ pub trait App {
|
|||
/// where `APPNAME` is what is returned by [`Self::name()`].
|
||||
fn save(&mut self, _storage: &mut dyn Storage) {}
|
||||
|
||||
/// Called once on shutdown (before or after [`Self::save`])
|
||||
/// Called before an exit that can be aborted.
|
||||
/// By returning `false` the exit will be aborted. To continue the exit return `true`.
|
||||
///
|
||||
/// A scenario where this method will be run is after pressing the close button on a native
|
||||
/// window, which allows you to ask the user whether they want to do something before exiting.
|
||||
/// See the example `eframe/examples/confirm_exit.rs` for practical usage.
|
||||
///
|
||||
/// It will _not_ be called on the web or when the window is forcefully closed.
|
||||
fn on_exit_event(&mut self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Called once on shutdown (before or after [`Self::save`]). If you need to abort an exit use
|
||||
/// [`Self::on_exit_event`]
|
||||
fn on_exit(&mut self) {}
|
||||
|
||||
// ---------
|
||||
|
|
Loading…
Reference in a new issue