From ede9ca5de211e7e98bf82ffa07fc926f1ab2a583 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 14 Dec 2022 15:48:52 +0100 Subject: [PATCH] eframe: add a simplified native-only API for simple native apps --- Cargo.lock | 8 +++ crates/eframe/src/lib.rs | 58 +++++++++++++++++++++ examples/hello_world_simple/Cargo.toml | 15 ++++++ examples/hello_world_simple/README.md | 7 +++ examples/hello_world_simple/screenshot.png | Bin 0 -> 7671 bytes examples/hello_world_simple/src/main.rs | 33 ++++++++++++ 6 files changed, 121 insertions(+) create mode 100644 examples/hello_world_simple/Cargo.toml create mode 100644 examples/hello_world_simple/README.md create mode 100644 examples/hello_world_simple/screenshot.png create mode 100644 examples/hello_world_simple/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 36a4872b..4142002f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2171,6 +2171,14 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "hello_world_simple" +version = "0.1.0" +dependencies = [ + "eframe", + "tracing-subscriber", +] + [[package]] name = "hermit-abi" version = "0.1.19" diff --git a/crates/eframe/src/lib.rs b/crates/eframe/src/lib.rs index 28f2adb1..3a529910 100644 --- a/crates/eframe/src/lib.rs +++ b/crates/eframe/src/lib.rs @@ -54,6 +54,10 @@ //! } //! ``` //! +//! ## Simplified usage +//! If your app is only for native, and you don't need advanced features like state persistence, +//! then you can use the simpler function [`run_simple_native`]. +//! //! ## Feature flags #![cfg_attr(feature = "document-features", doc = document_features::document_features!())] //! @@ -209,6 +213,60 @@ pub fn run_native( // ---------------------------------------------------------------------------- +/// The simplest way to get started when writing a native app. +/// +/// This does NOT support persistence. For that you need to use [`run_native`]. +/// +/// # Example +/// ``` no_run +/// // Our application state: +/// let mut name = "Arthur".to_owned(); +/// let mut age = 42; +/// +/// let options = eframe::NativeOptions::default(); +/// eframe::run_simple_native("My egui App", options, move |ctx, _frame| { +/// egui::CentralPanel::default().show(ctx, |ui| { +/// ui.heading("My egui Application"); +/// ui.horizontal(|ui| { +/// let name_label = ui.label("Your name: "); +/// ui.text_edit_singleline(&mut name) +/// .labelled_by(name_label.id); +/// }); +/// ui.add(egui::Slider::new(&mut age, 0..=120).text("age")); +/// if ui.button("Click each year").clicked() { +/// age += 1; +/// } +/// ui.label(format!("Hello '{}', age {}", name, age)); +/// }); +/// }) +/// ``` +/// +/// # Errors +/// This function can fail if we fail to set up a graphics context. +#[cfg(not(target_arch = "wasm32"))] +pub fn run_simple_native( + app_name: &str, + native_options: NativeOptions, + update_fun: impl FnMut(&egui::Context, &mut Frame) + 'static, +) -> Result<()> { + struct SimpleApp { + update_fun: U, + } + impl App for SimpleApp { + fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) { + (self.update_fun)(ctx, frame); + } + } + + run_native( + app_name, + native_options, + Box::new(|_cc| Box::new(SimpleApp { update_fun })), + ) +} + +// ---------------------------------------------------------------------------- + /// The different problems that can occur when trying to run `eframe`. #[derive(thiserror::Error, Debug)] pub enum EframeError { diff --git a/examples/hello_world_simple/Cargo.toml b/examples/hello_world_simple/Cargo.toml new file mode 100644 index 00000000..6c06c174 --- /dev/null +++ b/examples/hello_world_simple/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "hello_world_simple" +version = "0.1.0" +authors = ["Emil Ernerfeldt "] +license = "MIT OR Apache-2.0" +edition = "2021" +rust-version = "1.65" +publish = false + + +[dependencies] +eframe = { path = "../../crates/eframe", features = [ + "__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO +] } +tracing-subscriber = "0.3" diff --git a/examples/hello_world_simple/README.md b/examples/hello_world_simple/README.md new file mode 100644 index 00000000..08c58a7d --- /dev/null +++ b/examples/hello_world_simple/README.md @@ -0,0 +1,7 @@ +Example showing some UI controls like `Label`, `TextEdit`, `Slider`, `Button`. + +```sh +cargo run -p hello_world +``` + +![](screenshot.png) diff --git a/examples/hello_world_simple/screenshot.png b/examples/hello_world_simple/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..765339d401b9bd00ca9f7ae69d702ab946c0466d GIT binary patch literal 7671 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 literal 0 HcmV?d00001 diff --git a/examples/hello_world_simple/src/main.rs b/examples/hello_world_simple/src/main.rs new file mode 100644 index 00000000..998d84a0 --- /dev/null +++ b/examples/hello_world_simple/src/main.rs @@ -0,0 +1,33 @@ +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release + +use eframe::egui; + +fn main() -> Result<(), eframe::EframeError> { + // Log to stdout (if you run with `RUST_LOG=debug`). + tracing_subscriber::fmt::init(); + + let options = eframe::NativeOptions { + initial_window_size: Some(egui::vec2(320.0, 240.0)), + ..Default::default() + }; + + // Our application state: + let mut name = "Arthur".to_owned(); + let mut age = 42; + + eframe::run_simple_native("My egui App", options, move |ctx, _frame| { + egui::CentralPanel::default().show(ctx, |ui| { + ui.heading("My egui Application"); + ui.horizontal(|ui| { + let name_label = ui.label("Your name: "); + ui.text_edit_singleline(&mut name) + .labelled_by(name_label.id); + }); + ui.add(egui::Slider::new(&mut age, 0..=120).text("age")); + if ui.button("Click each year").clicked() { + age += 1; + } + ui.label(format!("Hello '{}', age {}", name, age)); + }); + }) +}