[egui_glium] Your app state will auto-save to a good directory
Directory found with https://docs.rs/directories-next/2.0.0/directories_next/struct.ProjectDirs.html#method.data_dir
This commit is contained in:
parent
89937bf636
commit
8f034d391d
5 changed files with 114 additions and 22 deletions
45
Cargo.lock
generated
45
Cargo.lock
generated
|
@ -33,7 +33,7 @@ version = "0.6.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75b7e6a93ecd6dbd2c225154d0fa7f86205574ecaa6c87429fb5f66ee677c44"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.0",
|
||||
"lazy_static",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -553,6 +553,27 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99de365f605554ae33f115102a02057d4fc18b01f3284d6870be0938743cfe7d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
|
@ -592,6 +613,7 @@ version = "0.5.0"
|
|||
dependencies = [
|
||||
"chrono",
|
||||
"clipboard",
|
||||
"directories-next",
|
||||
"egui",
|
||||
"glium",
|
||||
"serde",
|
||||
|
@ -669,6 +691,17 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.0"
|
||||
|
@ -1389,6 +1422,16 @@ version = "0.1.57"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
||||
dependencies = [
|
||||
"getrandom 0.1.15",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.2"
|
||||
|
|
|
@ -3,12 +3,6 @@
|
|||
#![warn(clippy::all)]
|
||||
|
||||
fn main() {
|
||||
// Persist app state to file:
|
||||
let storage = egui_glium::storage::FileStorage::from_path(".egui_demo_glium.json");
|
||||
|
||||
// Alternative: store nowhere
|
||||
// let storage = egui::app::DummyStorage::default();
|
||||
|
||||
let app: egui::DemoApp = egui::app::get_value(&storage, egui::app::APP_KEY).unwrap_or_default();
|
||||
egui_glium::run(Box::new(storage), Box::new(app));
|
||||
let app = egui::DemoApp::default();
|
||||
egui_glium::run(Box::new(app));
|
||||
}
|
||||
|
|
|
@ -7,8 +7,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
* `egui_glium` will auto-save your app state every 30 seconds.
|
||||
|
||||
### Changed
|
||||
|
||||
* `egui_glium` will now save you app state to [a better directory](https://docs.rs/directories-next/2.0.0/directories_next/struct.ProjectDirs.html#method.data_dir)
|
||||
* `egui_glium::run`: the parameter `app` now has signature `Box<dyn App>` (you need to add `Box::new(app)` to your code).
|
||||
* Window title is now passed via the `trait` function `egui::App::name()`
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ include = [ "**/*.rs", "Cargo.toml"]
|
|||
[dependencies]
|
||||
chrono = { version = "0.4" }
|
||||
clipboard = "0.5"
|
||||
directories-next = "2"
|
||||
egui = { version = "0.5.0", path = "../egui", features = ["serde", "serde_json"] }
|
||||
glium = "0.29"
|
||||
serde = "1"
|
||||
|
|
|
@ -63,18 +63,48 @@ fn create_display(
|
|||
glium::Display::new(window_builder, context_builder, &event_loop).unwrap()
|
||||
}
|
||||
|
||||
fn create_storage(app_name: &str) -> Option<Box<dyn egui::app::Storage>> {
|
||||
if let Some(proj_dirs) = directories_next::ProjectDirs::from("", "", app_name) {
|
||||
let data_dir = proj_dirs.data_dir().to_path_buf();
|
||||
if let Err(err) = std::fs::create_dir_all(&data_dir) {
|
||||
eprintln!(
|
||||
"Saving disabled: Failed to create app path at {:?}: {}",
|
||||
data_dir, err
|
||||
);
|
||||
None
|
||||
} else {
|
||||
let mut config_dir = data_dir;
|
||||
config_dir.push("app.json");
|
||||
let storage = crate::storage::FileStorage::from_path(config_dir);
|
||||
Some(Box::new(storage))
|
||||
}
|
||||
} else {
|
||||
eprintln!("Saving disabled: Failed to find path to data_dir.");
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Run an egui app
|
||||
pub fn run(mut storage: Box<dyn egui::app::Storage>, mut app: Box<dyn App>) -> ! {
|
||||
app.load(storage.as_ref());
|
||||
let window_settings: Option<WindowSettings> =
|
||||
egui::app::get_value(storage.as_ref(), WINDOW_KEY);
|
||||
pub fn run(mut app: Box<dyn App>) -> ! {
|
||||
let mut storage = create_storage(app.name());
|
||||
|
||||
if let Some(storage) = &mut storage {
|
||||
app.load(storage.as_ref());
|
||||
}
|
||||
|
||||
let window_settings: Option<WindowSettings> = storage
|
||||
.as_mut()
|
||||
.and_then(|storage| egui::app::get_value(storage.as_ref(), WINDOW_KEY));
|
||||
let event_loop = glutin::event_loop::EventLoop::with_user_event();
|
||||
let display = create_display(app.name(), window_settings, &event_loop);
|
||||
|
||||
let repaint_signal = std::sync::Arc::new(GliumRepaintSignal(event_loop.create_proxy()));
|
||||
|
||||
let mut ctx = egui::CtxRef::default();
|
||||
*ctx.memory() = egui::app::get_value(storage.as_ref(), EGUI_MEMORY_KEY).unwrap_or_default();
|
||||
*ctx.memory() = storage
|
||||
.as_mut()
|
||||
.and_then(|storage| egui::app::get_value(storage.as_ref(), EGUI_MEMORY_KEY))
|
||||
.unwrap_or_default();
|
||||
app.setup(&ctx);
|
||||
|
||||
let mut input_state = GliumInputState::from_pixels_per_point(native_pixels_per_point(&display));
|
||||
|
@ -84,6 +114,8 @@ pub fn run(mut storage: Box<dyn egui::app::Storage>, mut app: Box<dyn App>) -> !
|
|||
let mut painter = Painter::new(&display);
|
||||
let mut clipboard = init_clipboard();
|
||||
|
||||
let mut last_auto_save = Instant::now();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
let mut redraw = || {
|
||||
let frame_start = Instant::now();
|
||||
|
@ -153,6 +185,21 @@ pub fn run(mut storage: Box<dyn egui::app::Storage>, mut app: Box<dyn App>) -> !
|
|||
}
|
||||
|
||||
handle_output(egui_output, &display, clipboard.as_mut());
|
||||
|
||||
if let Some(storage) = &mut storage {
|
||||
let now = Instant::now();
|
||||
if now - last_auto_save > app.auto_save_interval() {
|
||||
egui::app::set_value(
|
||||
storage.as_mut(),
|
||||
WINDOW_KEY,
|
||||
&WindowSettings::from_display(&display),
|
||||
);
|
||||
egui::app::set_value(storage.as_mut(), EGUI_MEMORY_KEY, &*ctx.memory());
|
||||
app.save(storage.as_mut());
|
||||
storage.flush();
|
||||
last_auto_save = now;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match event {
|
||||
|
@ -167,15 +214,17 @@ pub fn run(mut storage: Box<dyn egui::app::Storage>, mut app: Box<dyn App>) -> !
|
|||
display.gl_window().window().request_redraw(); // TODO: ask Egui if the events warrants a repaint instead
|
||||
}
|
||||
glutin::event::Event::LoopDestroyed => {
|
||||
egui::app::set_value(
|
||||
storage.as_mut(),
|
||||
WINDOW_KEY,
|
||||
&WindowSettings::from_display(&display),
|
||||
);
|
||||
egui::app::set_value(storage.as_mut(), EGUI_MEMORY_KEY, &*ctx.memory());
|
||||
app.save(storage.as_mut());
|
||||
app.on_exit();
|
||||
storage.flush();
|
||||
if let Some(storage) = &mut storage {
|
||||
egui::app::set_value(
|
||||
storage.as_mut(),
|
||||
WINDOW_KEY,
|
||||
&WindowSettings::from_display(&display),
|
||||
);
|
||||
egui::app::set_value(storage.as_mut(), EGUI_MEMORY_KEY, &*ctx.memory());
|
||||
app.save(storage.as_mut());
|
||||
storage.flush();
|
||||
}
|
||||
}
|
||||
|
||||
glutin::event::Event::UserEvent(RequestRepaintEvent) => {
|
||||
|
|
Loading…
Reference in a new issue