Merge branch 'master' into feat-window-actions
@@ -4,9 +4,11 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Example how to show a confirm dialog before exiting an application.
|
||||
|
||||
```sh
|
||||
cargo run -p confirm_exit
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/confirm_exit/screenshot.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
@@ -2,13 +2,16 @@
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() {
|
||||
let options = eframe::NativeOptions::default();
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
initial_window_size: Some(egui::vec2(320.0, 240.0)),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"Confirm exit",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
@@ -4,11 +4,13 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe", features = ["glow"] }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
egui_glow = { path = "../../crates/egui_glow" }
|
||||
glow = "0.11"
|
||||
|
||||
@@ -13,3 +13,5 @@ If you are content of having egui sit on top of a 3D background, take a look at:
|
||||
```sh
|
||||
cargo run -p custom_3d_glow
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/custom_3d_glow/screenshot.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
@@ -6,7 +6,7 @@ use eframe::egui;
|
||||
use egui::mutex::Mutex;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
initial_window_size: Some(egui::vec2(350.0, 380.0)),
|
||||
multisampling: 8,
|
||||
@@ -17,7 +17,7 @@ fn main() {
|
||||
"Custom 3D painting in eframe using glow",
|
||||
options,
|
||||
Box::new(|cc| Box::new(MyApp::new(cc))),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
struct MyApp {
|
||||
@@ -145,9 +145,11 @@ impl RotatingTriangle {
|
||||
.expect("Cannot create shader");
|
||||
gl.shader_source(shader, &format!("{}\n{}", shader_version, shader_source));
|
||||
gl.compile_shader(shader);
|
||||
if !gl.get_shader_compile_status(shader) {
|
||||
panic!("{}", gl.get_shader_info_log(shader));
|
||||
}
|
||||
assert!(
|
||||
gl.get_shader_compile_status(shader),
|
||||
"Failed to compile {shader_type}: {}",
|
||||
gl.get_shader_info_log(shader)
|
||||
);
|
||||
gl.attach_shader(program, shader);
|
||||
shader
|
||||
})
|
||||
|
||||
@@ -4,19 +4,21 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe", features = ["glow"] }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
egui_glow = { path = "../../crates/egui_glow" }
|
||||
glow = "0.11"
|
||||
three-d = { version = "0.13", default-features = false }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies] # Web dependencies
|
||||
wasm-bindgen = "0.2" # Core bindings
|
||||
wasm-bindgen-futures = "0.4" # Core bindings
|
||||
console_error_panic_hook = "0.1" # For logging
|
||||
wasm-bindgen = "0.2" # Core bindings
|
||||
wasm-bindgen-futures = "0.4" # Core bindings
|
||||
|
||||
@@ -18,3 +18,5 @@ cargo run -p custom_3d_three-d
|
||||
```
|
||||
wasm-pack build examples/custom_3d_three-d --target web
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/custom_3d_three-d/screenshot.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
@@ -1,3 +1,5 @@
|
||||
#![allow(special_module_name)]
|
||||
|
||||
mod main;
|
||||
|
||||
// Entry point for wasm
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use eframe::egui;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
initial_window_size: Some(egui::vec2(550.0, 610.0)),
|
||||
multisampling: 8,
|
||||
@@ -16,7 +16,7 @@ fn main() {
|
||||
"Custom 3D painting in eframe!",
|
||||
options,
|
||||
Box::new(|cc| Box::new(MyApp::new(cc))),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
pub struct MyApp {
|
||||
|
||||
@@ -4,9 +4,11 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Example of how to use custom fonts.
|
||||
|
||||
```sh
|
||||
cargo run -p custom_font
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/custom_font/screenshot.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
@@ -2,13 +2,16 @@
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() {
|
||||
let options = eframe::NativeOptions::default();
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
initial_window_size: Some(egui::vec2(320.0, 240.0)),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"egui example: custom font",
|
||||
options,
|
||||
Box::new(|cc| Box::new(MyApp::new(cc))),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
fn setup_custom_fonts(ctx: &egui::Context) {
|
||||
|
||||
@@ -4,9 +4,11 @@ version = "0.1.0"
|
||||
authors = ["tami5 <kkharji@proton.me>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Example how to define custom test styles.
|
||||
|
||||
```sh
|
||||
cargo run -p custom_font_style
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/custom_font_style/screenshot.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
@@ -14,7 +14,7 @@ fn heading3() -> TextStyle {
|
||||
}
|
||||
|
||||
fn configure_text_styles(ctx: &egui::Context) {
|
||||
use FontFamily::Proportional;
|
||||
use FontFamily::{Monospace, Proportional};
|
||||
|
||||
let mut style = (*ctx.style()).clone();
|
||||
style.text_styles = [
|
||||
@@ -22,7 +22,7 @@ fn configure_text_styles(ctx: &egui::Context) {
|
||||
(heading2(), FontId::new(22.0, Proportional)),
|
||||
(heading3(), FontId::new(19.0, Proportional)),
|
||||
(TextStyle::Body, FontId::new(16.0, Proportional)),
|
||||
(TextStyle::Monospace, FontId::new(12.0, Proportional)),
|
||||
(TextStyle::Monospace, FontId::new(12.0, Monospace)),
|
||||
(TextStyle::Button, FontId::new(12.0, Proportional)),
|
||||
(TextStyle::Small, FontId::new(8.0, Proportional)),
|
||||
]
|
||||
@@ -36,7 +36,7 @@ fn content(ui: &mut egui::Ui) {
|
||||
ui.label(LOREM_IPSUM);
|
||||
ui.add_space(15.);
|
||||
ui.label(RichText::new("Sub Heading").text_style(heading2()).strong());
|
||||
ui.label(LOREM_IPSUM);
|
||||
ui.monospace(LOREM_IPSUM);
|
||||
ui.add_space(15.);
|
||||
ui.label(RichText::new("Context").text_style(heading3()).strong());
|
||||
ui.add_space(5.);
|
||||
@@ -58,14 +58,14 @@ impl eframe::App for MyApp {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions::default();
|
||||
|
||||
eframe::run_native(
|
||||
"egui example: global font style",
|
||||
options,
|
||||
Box::new(|cc| Box::new(MyApp::new(cc))),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
pub const LOREM_IPSUM: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
|
||||
|
||||
@@ -4,9 +4,11 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Example how to show a custom window frame instead of the default OS window chrome decorations.
|
||||
|
||||
```sh
|
||||
cargo run -p custom_window_frame
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/custom_window_frame/screenshot.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
@@ -4,20 +4,21 @@
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
// Hide the OS-specific "chrome" around the window:
|
||||
decorated: false,
|
||||
// To have rounded corners we need transparency:
|
||||
transparent: true,
|
||||
min_window_size: Some(egui::vec2(320.0, 100.0)),
|
||||
initial_window_size: Some(egui::vec2(320.0, 240.0)),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"Custom window frame", // unused title
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -26,8 +27,8 @@ struct MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn clear_color(&self, _visuals: &egui::Visuals) -> egui::Rgba {
|
||||
egui::Rgba::TRANSPARENT // Make sure we don't paint anything behind the rounded corners
|
||||
fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] {
|
||||
egui::Rgba::TRANSPARENT.to_array() // Make sure we don't paint anything behind the rounded corners
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
|
||||
|
||||
@@ -4,13 +4,15 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
egui_extras = { path = "../../crates/egui_extras", features = ["image"] }
|
||||
ehttp = "0.2"
|
||||
image = { version = "0.24", default-features = false, features = ["jpeg"] }
|
||||
poll-promise = "0.1"
|
||||
poll-promise = "0.2"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Example how to download and show an image with eframe/egui.
|
||||
|
||||
```sh
|
||||
cargo run -p download_image
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/download_image/screenshot.png
Normal file
|
After Width: | Height: | Size: 353 KiB |
@@ -4,13 +4,13 @@ use eframe::egui;
|
||||
use egui_extras::RetainedImage;
|
||||
use poll_promise::Promise;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions::default();
|
||||
eframe::run_native(
|
||||
"Download and show an image with eframe/egui",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
@@ -4,10 +4,12 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
rfd = "0.10"
|
||||
|
||||
@@ -3,3 +3,5 @@ How to show a file dialog using [`rfd`](https://github.com/PolyMeilex/rfd).
|
||||
```sh
|
||||
cargo run -p file_dialog
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/file_dialog/screenshot.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
@@ -2,16 +2,17 @@
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
drag_and_drop_support: true,
|
||||
initial_window_size: Some(egui::vec2(320.0, 240.0)),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"Native file dialogs and drag-and-drop files",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -64,9 +65,11 @@ impl eframe::App for MyApp {
|
||||
preview_files_being_dropped(ctx);
|
||||
|
||||
// Collect dropped files:
|
||||
if !ctx.input().raw.dropped_files.is_empty() {
|
||||
self.dropped_files = ctx.input().raw.dropped_files.clone();
|
||||
}
|
||||
ctx.input(|i| {
|
||||
if !i.raw.dropped_files.is_empty() {
|
||||
self.dropped_files = i.raw.dropped_files.clone();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,22 +78,25 @@ fn preview_files_being_dropped(ctx: &egui::Context) {
|
||||
use egui::*;
|
||||
use std::fmt::Write as _;
|
||||
|
||||
if !ctx.input().raw.hovered_files.is_empty() {
|
||||
let mut text = "Dropping files:\n".to_owned();
|
||||
for file in &ctx.input().raw.hovered_files {
|
||||
if let Some(path) = &file.path {
|
||||
write!(text, "\n{}", path.display()).ok();
|
||||
} else if !file.mime.is_empty() {
|
||||
write!(text, "\n{}", file.mime).ok();
|
||||
} else {
|
||||
text += "\n???";
|
||||
if !ctx.input(|i| i.raw.hovered_files.is_empty()) {
|
||||
let text = ctx.input(|i| {
|
||||
let mut text = "Dropping files:\n".to_owned();
|
||||
for file in &i.raw.hovered_files {
|
||||
if let Some(path) = &file.path {
|
||||
write!(text, "\n{}", path.display()).ok();
|
||||
} else if !file.mime.is_empty() {
|
||||
write!(text, "\n{}", file.mime).ok();
|
||||
} else {
|
||||
text += "\n???";
|
||||
}
|
||||
}
|
||||
}
|
||||
text
|
||||
});
|
||||
|
||||
let painter =
|
||||
ctx.layer_painter(LayerId::new(Order::Foreground, Id::new("file_drop_target")));
|
||||
|
||||
let screen_rect = ctx.input().screen_rect();
|
||||
let screen_rect = ctx.screen_rect();
|
||||
painter.rect_filled(screen_rect, 0.0, Color32::from_black_alpha(192));
|
||||
painter.text(
|
||||
screen_rect.center(),
|
||||
|
||||
@@ -4,10 +4,12 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
tracing-subscriber = "0.3"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Example showing some UI controls like `Label`, `TextEdit`, `Slider`, `Button`.
|
||||
|
||||
```sh
|
||||
cargo run -p hello_world
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/hello_world/screenshot.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
@@ -2,16 +2,19 @@
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
// Log to stdout (if you run with `RUST_LOG=debug`).
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let options = eframe::NativeOptions::default();
|
||||
let options = eframe::NativeOptions {
|
||||
initial_window_size: Some(egui::vec2(320.0, 240.0)),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"My egui App",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
struct MyApp {
|
||||
@@ -33,8 +36,9 @@ impl eframe::App for MyApp {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("My egui Application");
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Your name: ");
|
||||
ui.text_edit_singleline(&mut self.name);
|
||||
let name_label = ui.label("Your name: ");
|
||||
ui.text_edit_singleline(&mut self.name)
|
||||
.labelled_by(name_label.id);
|
||||
});
|
||||
ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));
|
||||
if ui.button("Click each year").clicked() {
|
||||
|
||||
16
examples/hello_world_par/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "hello_world_par"
|
||||
version = "0.1.0"
|
||||
authors = ["Maxim Osipenko <maxim1999max@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe", default-features = false, features = [
|
||||
# accesskit struggles with threading
|
||||
"default_fonts",
|
||||
"wgpu",
|
||||
] }
|
||||
5
examples/hello_world_par/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
This example shows that you can use egui in parallel from multiple threads.
|
||||
|
||||
```sh
|
||||
cargo run -p hello_world_par
|
||||
```
|
||||
132
examples/hello_world_par/src/main.rs
Normal file
@@ -0,0 +1,132 @@
|
||||
//! This example shows that you can use egui in parallel from multiple threads.
|
||||
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
|
||||
use std::sync::mpsc;
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
initial_window_size: Some(egui::vec2(1024.0, 768.0)),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"My parallel egui App",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::new())),
|
||||
)
|
||||
}
|
||||
|
||||
/// State per thread.
|
||||
struct ThreadState {
|
||||
thread_nr: usize,
|
||||
title: String,
|
||||
name: String,
|
||||
age: u32,
|
||||
}
|
||||
|
||||
impl ThreadState {
|
||||
fn new(thread_nr: usize) -> Self {
|
||||
let title = format!("Background thread {thread_nr}");
|
||||
Self {
|
||||
thread_nr,
|
||||
title,
|
||||
name: "Arthur".into(),
|
||||
age: 12 + thread_nr as u32 * 10,
|
||||
}
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context) {
|
||||
let pos = egui::pos2(16.0, 128.0 * (self.thread_nr as f32 + 1.0));
|
||||
egui::Window::new(&self.title)
|
||||
.default_pos(pos)
|
||||
.show(ctx, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Your name: ");
|
||||
ui.text_edit_singleline(&mut self.name);
|
||||
});
|
||||
ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));
|
||||
if ui.button("Click each year").clicked() {
|
||||
self.age += 1;
|
||||
}
|
||||
ui.label(format!("Hello '{}', age {}", self.name, self.age));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn new_worker(
|
||||
thread_nr: usize,
|
||||
on_done_tx: mpsc::SyncSender<()>,
|
||||
) -> (JoinHandle<()>, mpsc::SyncSender<egui::Context>) {
|
||||
let (show_tx, show_rc) = mpsc::sync_channel(0);
|
||||
let handle = std::thread::Builder::new()
|
||||
.name(format!("EguiPanelWorker {}", thread_nr))
|
||||
.spawn(move || {
|
||||
let mut state = ThreadState::new(thread_nr);
|
||||
while let Ok(ctx) = show_rc.recv() {
|
||||
state.show(&ctx);
|
||||
let _ = on_done_tx.send(());
|
||||
}
|
||||
})
|
||||
.expect("failed to spawn thread");
|
||||
(handle, show_tx)
|
||||
}
|
||||
|
||||
struct MyApp {
|
||||
threads: Vec<(JoinHandle<()>, mpsc::SyncSender<egui::Context>)>,
|
||||
on_done_tx: mpsc::SyncSender<()>,
|
||||
on_done_rc: mpsc::Receiver<()>,
|
||||
}
|
||||
|
||||
impl MyApp {
|
||||
fn new() -> Self {
|
||||
let threads = Vec::with_capacity(3);
|
||||
let (on_done_tx, on_done_rc) = mpsc::sync_channel(0);
|
||||
|
||||
let mut slf = Self {
|
||||
threads,
|
||||
on_done_tx,
|
||||
on_done_rc,
|
||||
};
|
||||
|
||||
slf.spawn_thread();
|
||||
slf.spawn_thread();
|
||||
|
||||
slf
|
||||
}
|
||||
|
||||
fn spawn_thread(&mut self) {
|
||||
let thread_nr = self.threads.len();
|
||||
self.threads
|
||||
.push(new_worker(thread_nr, self.on_done_tx.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Drop for MyApp {
|
||||
fn drop(&mut self) {
|
||||
for (handle, show_tx) in self.threads.drain(..) {
|
||||
std::mem::drop(show_tx);
|
||||
handle.join().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::Window::new("Main thread").show(ctx, |ui| {
|
||||
if ui.button("Spawn another thread").clicked() {
|
||||
self.spawn_thread();
|
||||
}
|
||||
});
|
||||
|
||||
for (_handle, show_tx) in &self.threads {
|
||||
let _ = show_tx.send(ctx.clone());
|
||||
}
|
||||
|
||||
for _ in 0..self.threads.len() {
|
||||
let _ = self.on_done_rc.recv();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
examples/keyboard_events/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "keyboard_events"
|
||||
version = "0.1.0"
|
||||
authors = ["Jose Palazon <jose@palako.com>"]
|
||||
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"
|
||||
5
examples/keyboard_events/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
```sh
|
||||
cargo run -p keyboard_events
|
||||
```
|
||||
|
||||

|
||||
BIN
examples/keyboard_events/screenshot.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
48
examples/keyboard_events/src/main.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
|
||||
use eframe::egui;
|
||||
use egui::*;
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
// Log to stdout (if you run with `RUST_LOG=debug`).
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let options = eframe::NativeOptions::default();
|
||||
eframe::run_native(
|
||||
"Keyboard events",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(Content::default())),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Content {
|
||||
text: String,
|
||||
}
|
||||
|
||||
impl eframe::App for Content {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("Press/Hold/Release example. Press A to test.");
|
||||
if ui.button("Clear").clicked() {
|
||||
self.text.clear();
|
||||
}
|
||||
ScrollArea::vertical()
|
||||
.auto_shrink([false; 2])
|
||||
.stick_to_bottom(true)
|
||||
.show(ui, |ui| {
|
||||
ui.label(&self.text);
|
||||
});
|
||||
|
||||
if ctx.input(|i| i.key_pressed(Key::A)) {
|
||||
self.text.push_str("\nPressed");
|
||||
}
|
||||
if ctx.input(|i| i.key_down(Key::A)) {
|
||||
self.text.push_str("\nHeld");
|
||||
ui.ctx().request_repaint(); // make sure we note the holding.
|
||||
}
|
||||
if ctx.input(|i| i.key_released(Key::A)) {
|
||||
self.text.push_str("\nReleased");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,13 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe", features = ["puffin"] }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
puffin = "0.14"
|
||||
puffin_http = "0.11"
|
||||
|
||||
@@ -7,3 +7,5 @@ cargo run -p puffin_profiler &
|
||||
cargo install puffin_viewer
|
||||
puffin_viewer --url 127.0.0.1:8585
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/puffin_profiler/screenshot.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
@@ -2,7 +2,7 @@
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
start_puffin_server(); // NOTE: you may only want to call this if the users specifies some flag or clicks a button!
|
||||
|
||||
let options = eframe::NativeOptions::default();
|
||||
@@ -10,7 +10,7 @@ fn main() {
|
||||
"My egui App",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -28,7 +28,7 @@ impl eframe::App for MyApp {
|
||||
ui.horizontal(|ui| {
|
||||
ui.monospace(cmd);
|
||||
if ui.small_button("📋").clicked() {
|
||||
ui.output().copied_text = cmd.into();
|
||||
ui.output_mut(|o| o.copied_text = cmd.into());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
egui_extras = { path = "../../crates/egui_extras", features = ["image"] }
|
||||
image = { version = "0.24", default-features = false, features = ["png"] }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Example how to show an image with eframe/egui.
|
||||
|
||||
```sh
|
||||
cargo run -p retained_image
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/retained_image/screenshot.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
@@ -3,9 +3,9 @@
|
||||
use eframe::egui;
|
||||
use egui_extras::RetainedImage;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
initial_window_size: Some(egui::vec2(500.0, 900.0)),
|
||||
initial_window_size: Some(egui::vec2(300.0, 900.0)),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ fn main() {
|
||||
"Show an image with eframe/egui",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
struct MyApp {
|
||||
|
||||
@@ -4,11 +4,12 @@ version = "0.1.0"
|
||||
authors = ["René Rössler <rene@freshx.de>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
egui_extras = { path = "../../crates/egui_extras", features = ["image"] }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
itertools = "0.10.3"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
Example how to take screenshots and display them with eframe/egui.
|
||||
|
||||
```sh
|
||||
cargo run -p screenshot
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/screenshot/screenshot.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
@@ -4,15 +4,15 @@ use eframe::{
|
||||
egui::{self, ColorImage},
|
||||
glow::{self, HasContext},
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use itertools::Itertools as _;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions::default();
|
||||
eframe::run_native(
|
||||
"Take screenshots and display with eframe/egui",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -74,23 +74,25 @@ impl eframe::App for MyApp {
|
||||
|
||||
self.take_screenshot = false;
|
||||
if let Some(gl) = frame.gl() {
|
||||
let mut buf = vec![0u8; screen_size_px[0] as usize * screen_size_px[1] as usize * 4];
|
||||
let [w, h] = screen_size_px;
|
||||
let mut buf = vec![0u8; w as usize * h as usize * 4];
|
||||
let pixels = glow::PixelPackData::Slice(&mut buf[..]);
|
||||
unsafe {
|
||||
gl.read_pixels(
|
||||
0,
|
||||
0,
|
||||
screen_size_px[0] as i32,
|
||||
screen_size_px[1] as i32,
|
||||
w as i32,
|
||||
h as i32,
|
||||
glow::RGBA,
|
||||
glow::UNSIGNED_BYTE,
|
||||
pixels,
|
||||
);
|
||||
}
|
||||
|
||||
// Flip vertically:
|
||||
let mut rows: Vec<Vec<u8>> = buf
|
||||
.into_iter()
|
||||
.chunks(screen_size_px[0] as usize * 4)
|
||||
.chunks(w as usize * 4)
|
||||
.into_iter()
|
||||
.map(|chunk| chunk.collect())
|
||||
.collect();
|
||||
|
||||
@@ -4,9 +4,11 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
@@ -6,3 +6,5 @@ See also <https://github.com/emilk/egui/issues/1918>.
|
||||
```sh
|
||||
cargo run -p serial_windows
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/serial_windows/screenshot.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
@@ -2,13 +2,14 @@
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
if cfg!(target_os = "macos") {
|
||||
eprintln!("WARNING: this example does not work on Mac! See https://github.com/emilk/egui/issues/1918");
|
||||
}
|
||||
|
||||
let options = eframe::NativeOptions {
|
||||
run_and_return: true,
|
||||
initial_window_size: Some(egui::vec2(320.0, 240.0)),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -17,7 +18,7 @@ fn main() {
|
||||
"First Window",
|
||||
options.clone(),
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)?;
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||
|
||||
@@ -26,7 +27,7 @@ fn main() {
|
||||
"Second Window",
|
||||
options.clone(),
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)?;
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||
|
||||
@@ -35,7 +36,7 @@ fn main() {
|
||||
"Third Window",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
@@ -4,10 +4,12 @@ version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.62"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
eframe = { path = "../../crates/eframe", features = [
|
||||
"__screenshot", # __screenshot is so we can dump a ascreenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
egui_extras = { path = "../../crates/egui_extras", features = ["svg"] }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Example how to show an SVG image.
|
||||
|
||||
|
||||
```sh
|
||||
cargo run -p svg
|
||||
```
|
||||
|
||||

|
||||
|
||||
BIN
examples/svg/screenshot.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
@@ -6,7 +6,7 @@
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
let options = eframe::NativeOptions {
|
||||
initial_window_size: Some(egui::vec2(1000.0, 700.0)),
|
||||
..Default::default()
|
||||
@@ -15,7 +15,7 @@ fn main() {
|
||||
"svg example",
|
||||
options,
|
||||
Box::new(|_cc| Box::new(MyApp::default())),
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
struct MyApp {
|
||||
|
||||