mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 05:40:03 -04:00
Merge branch 'main' into lucas/experiments/helpful-id-debug
# Conflicts: # crates/egui/src/containers/combo_box.rs # crates/egui/src/id.rs # crates/egui/src/lib.rs # crates/egui/src/ui.rs # crates/egui/src/ui_builder.rs
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
# `egui` and `eframe` examples
|
||||
All the examples in this folder uses [`eframe`](https://github.com/emilk/egui/tree/master/crates/eframe) to set up a window for [`egui`](https://github.com/emilk/egui/). Some examples are specific to `eframe`, but many are applicable to any `egui` integration.
|
||||
All the examples in this folder uses [`eframe`](https://github.com/emilk/egui/tree/main/crates/eframe) to set up a window for [`egui`](https://github.com/emilk/egui/). Some examples are specific to `eframe`, but many are applicable to any `egui` integration.
|
||||
|
||||
There are a lot more examples at <https://www.egui.rs>, and it has links to the source code of each example.
|
||||
|
||||
Also check out the official docs at <https://docs.rs/egui> and <https://docs.rs/eframe>.
|
||||
|
||||
Note that all the examples on `master` are for the latest `master` version of `egui`.
|
||||
Note that all the examples on `main` are for the latest `main` version of `egui`.
|
||||
|
||||
If you want to look for examples for a specific version of egui, go to that tag, e.g. <https://github.com/emilk/egui/tree/latest/examples>.
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "confirm_exit"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,10 +13,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3122591a76a063f1db0b88b54ecc4afe012ee27a1404c0948d0b9d639aeeece6
|
||||
size 3124
|
||||
oid sha256:79ee820be9374c44e684373acb62fe7bcfaa2347346d1aed8083a706f6cae8c9
|
||||
size 3798
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
@@ -23,16 +23,16 @@ struct MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("Try to close the window");
|
||||
});
|
||||
|
||||
if ctx.input(|i| i.viewport().close_requested()) {
|
||||
if ui.input(|i| i.viewport().close_requested()) {
|
||||
if self.allowed_to_close {
|
||||
// do nothing - we will close
|
||||
} else {
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::CancelClose);
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::CancelClose);
|
||||
self.show_confirmation_dialog = true;
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ impl eframe::App for MyApp {
|
||||
egui::Window::new("Do you want to quit?")
|
||||
.collapsible(false)
|
||||
.resizable(false)
|
||||
.show(ctx, |ui| {
|
||||
.show(ui.ctx(), |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("No").clicked() {
|
||||
self.show_confirmation_dialog = false;
|
||||
@@ -51,7 +51,7 @@ impl eframe::App for MyApp {
|
||||
if ui.button("Yes").clicked() {
|
||||
self.show_confirmation_dialog = false;
|
||||
self.allowed_to_close = true;
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "custom_3d_glow"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,10 +13,8 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"glow",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4dd5ffcf5a530f6fbe959fd74e2f5b4aeaee335baf79ad1cde8e42c34d84156c
|
||||
size 24590
|
||||
oid sha256:c02ea6a9b0f2d215255b5550237f3d9aa43b257849591cc8a1cd206f401c2747
|
||||
size 28455
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![allow(unsafe_code)]
|
||||
#![allow(clippy::undocumented_unsafe_blocks)]
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(unsafe_code)]
|
||||
#![expect(clippy::undocumented_unsafe_blocks)]
|
||||
|
||||
use eframe::{egui, egui_glow, glow};
|
||||
|
||||
@@ -43,8 +43,8 @@ impl MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 0.0;
|
||||
ui.label("The triangle is being painted using ");
|
||||
@@ -75,7 +75,7 @@ impl MyApp {
|
||||
|
||||
// Clone locals so we can move them into the paint callback:
|
||||
let angle = self.angle;
|
||||
let rotating_triangle = self.rotating_triangle.clone();
|
||||
let rotating_triangle = Arc::clone(&self.rotating_triangle);
|
||||
|
||||
let callback = egui::PaintCallback {
|
||||
rect,
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "custom_font"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,10 +13,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d0ab12a55c0d87f044ef7675f5b94b39977f2c5d3a2ea74eb843dfc85d5b9f31
|
||||
size 5645
|
||||
oid sha256:c13f5b5f70c194316bbb116700619fd1611f423ae86244d1668f21ba622aaa45
|
||||
size 7104
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::{
|
||||
egui,
|
||||
@@ -86,8 +86,8 @@ impl MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("egui using custom fonts");
|
||||
ui.text_edit_multiline(&mut self.text);
|
||||
});
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "custom_font_style"
|
||||
version = "0.1.0"
|
||||
authors = ["tami5 <kkharji@proton.me>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,10 +13,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5d443ef30cf12d2c4367135fd663270ed46f4864af2f3aae424610be86c73197
|
||||
size 66193
|
||||
oid sha256:3d705d757b1689f3730a673988ffd2b3f8c1729c8c84b4236cd72593420ff0bd
|
||||
size 109694
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
use egui::{FontFamily, FontId, RichText, TextStyle};
|
||||
@@ -65,8 +65,8 @@ impl MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, content);
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, content);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "custom_keypad"
|
||||
version = "0.1.0"
|
||||
authors = ["Varphone Wong <varphone@qq.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,14 +13,11 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
# For image support:
|
||||
egui_extras = { workspace = true, features = ["default", "image"] }
|
||||
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use eframe::egui::{self, pos2, vec2, Button, Ui, Vec2};
|
||||
use eframe::egui::{self, Button, Ui, Vec2, pos2, vec2};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
enum Transition {
|
||||
@@ -179,9 +179,9 @@ impl Keypad {
|
||||
)
|
||||
});
|
||||
|
||||
let mut is_first_show = false;
|
||||
if ctx.wants_keyboard_input() && state.focus != focus {
|
||||
let y = ctx.style().spacing.interact_size.y * 1.25;
|
||||
let is_first_show = ctx.egui_wants_keyboard_input() && state.focus != focus;
|
||||
if is_first_show {
|
||||
let y = ctx.global_style().spacing.interact_size.y * 1.25;
|
||||
state.open = true;
|
||||
state.start_pos = ctx.input(|i| {
|
||||
i.pointer
|
||||
@@ -189,7 +189,6 @@ impl Keypad {
|
||||
.map_or(pos2(100.0, 100.0), |p| p + vec2(0.0, y))
|
||||
});
|
||||
state.focus = focus;
|
||||
is_first_show = true;
|
||||
}
|
||||
|
||||
if state.close_on_next_frame {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
use eframe::egui;
|
||||
|
||||
mod keypad;
|
||||
@@ -44,11 +44,11 @@ impl Default for MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::Window::new("Custom Keypad")
|
||||
.default_pos([100.0, 100.0])
|
||||
.title_bar(true)
|
||||
.show(ctx, |ui| {
|
||||
.show(ui.ctx(), |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Your name: ");
|
||||
ui.text_edit_singleline(&mut self.name);
|
||||
@@ -60,7 +60,7 @@ impl eframe::App for MyApp {
|
||||
ui.label(format!("Hello '{}', age {}", self.name, self.age));
|
||||
});
|
||||
|
||||
self.keypad.show(ctx);
|
||||
self.keypad.show(ui.ctx());
|
||||
}
|
||||
|
||||
fn raw_input_hook(&mut self, ctx: &egui::Context, raw_input: &mut egui::RawInput) {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
name = "custom_style"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -16,13 +16,10 @@ ignored = ["image"] # We need the .png feature
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
egui_demo_lib.workspace = true
|
||||
egui_extras = { workspace = true, features = ["image"] }
|
||||
image = { workspace = true, features = ["png"] }
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui::{
|
||||
self, global_theme_preference_buttons, style::Selection, Color32, Stroke, Style, Theme,
|
||||
self, Color32, Stroke, Style, Theme, global_theme_preference_buttons, style::Selection,
|
||||
};
|
||||
use egui_demo_lib::{View, WidgetGallery};
|
||||
use egui_demo_lib::{View as _, WidgetGallery};
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
@@ -57,8 +57,8 @@ impl MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("egui using a customized style");
|
||||
ui.label("Switch between dark and light mode to see the different styles in action.");
|
||||
global_theme_preference_buttons(ui);
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "custom_window_frame"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,10 +13,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bfdf77d119ae7926f52ac781455c4b1574eea53276069614738ba8b13b9921ea
|
||||
size 6024
|
||||
oid sha256:8d153d2468d7099f2da099c5ea65329196a83baf112b292de1c5a6ce758dfced
|
||||
size 17635
|
||||
|
||||
@@ -31,8 +31,8 @@ impl eframe::App for MyApp {
|
||||
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) {
|
||||
custom_window_frame(ctx, "egui with custom frame", |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
custom_window_frame(ui, "egui with custom frame", |ui| {
|
||||
ui.label("This is just the contents of the window.");
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("egui theme:");
|
||||
@@ -42,18 +42,20 @@ impl eframe::App for MyApp {
|
||||
}
|
||||
}
|
||||
|
||||
fn custom_window_frame(ctx: &egui::Context, title: &str, add_contents: impl FnOnce(&mut egui::Ui)) {
|
||||
use egui::{CentralPanel, UiBuilder};
|
||||
fn custom_window_frame(ui: &mut egui::Ui, title: &str, add_contents: impl FnOnce(&mut egui::Ui)) {
|
||||
use egui::UiBuilder;
|
||||
|
||||
let panel_frame = egui::Frame::new()
|
||||
.fill(ctx.style().visuals.window_fill())
|
||||
.fill(ui.global_style().visuals.window_fill())
|
||||
.corner_radius(10)
|
||||
.stroke(ctx.style().visuals.widgets.noninteractive.fg_stroke)
|
||||
.stroke(ui.global_style().visuals.widgets.noninteractive.fg_stroke)
|
||||
.outer_margin(1); // so the stroke is within the bounds
|
||||
|
||||
CentralPanel::default().frame(panel_frame).show(ctx, |ui| {
|
||||
panel_frame.show(ui, |ui| {
|
||||
let app_rect = ui.max_rect();
|
||||
|
||||
ui.expand_to_include_rect(app_rect); // Expand frame to include it all
|
||||
|
||||
let title_bar_height = 32.0;
|
||||
let title_bar_rect = {
|
||||
let mut rect = app_rect;
|
||||
@@ -75,7 +77,7 @@ fn custom_window_frame(ctx: &egui::Context, title: &str, add_contents: impl FnOn
|
||||
}
|
||||
|
||||
fn title_bar_ui(ui: &mut egui::Ui, title_bar_rect: eframe::epaint::Rect, title: &str) {
|
||||
use egui::{vec2, Align2, FontId, Id, PointerButton, Sense, UiBuilder};
|
||||
use egui::{Align2, FontId, Id, PointerButton, Sense, UiBuilder, vec2};
|
||||
|
||||
let painter = ui.painter();
|
||||
|
||||
@@ -106,12 +108,11 @@ fn title_bar_ui(ui: &mut egui::Ui, title_bar_rect: eframe::epaint::Rect, title:
|
||||
// Interact with the title bar (drag to move window):
|
||||
if title_bar_response.double_clicked() {
|
||||
let is_maximized = ui.input(|i| i.viewport().maximized.unwrap_or(false));
|
||||
ui.ctx()
|
||||
.send_viewport_cmd(ViewportCommand::Maximized(!is_maximized));
|
||||
ui.send_viewport_cmd(ViewportCommand::Maximized(!is_maximized));
|
||||
}
|
||||
|
||||
if title_bar_response.drag_started_by(PointerButton::Primary) {
|
||||
ui.ctx().send_viewport_cmd(ViewportCommand::StartDrag);
|
||||
ui.send_viewport_cmd(ViewportCommand::StartDrag);
|
||||
}
|
||||
|
||||
ui.scope_builder(
|
||||
@@ -137,7 +138,7 @@ fn close_maximize_minimize(ui: &mut egui::Ui) {
|
||||
.add(Button::new(RichText::new("❌").size(button_height)))
|
||||
.on_hover_text("Close the window");
|
||||
if close_response.clicked() {
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
}
|
||||
|
||||
let is_maximized = ui.input(|i| i.viewport().maximized.unwrap_or(false));
|
||||
@@ -146,15 +147,14 @@ fn close_maximize_minimize(ui: &mut egui::Ui) {
|
||||
.add(Button::new(RichText::new("🗗").size(button_height)))
|
||||
.on_hover_text("Restore window");
|
||||
if maximized_response.clicked() {
|
||||
ui.ctx()
|
||||
.send_viewport_cmd(ViewportCommand::Maximized(false));
|
||||
ui.send_viewport_cmd(ViewportCommand::Maximized(false));
|
||||
}
|
||||
} else {
|
||||
let maximized_response = ui
|
||||
.add(Button::new(RichText::new("🗗").size(button_height)))
|
||||
.on_hover_text("Maximize window");
|
||||
if maximized_response.clicked() {
|
||||
ui.ctx().send_viewport_cmd(ViewportCommand::Maximized(true));
|
||||
ui.send_viewport_cmd(ViewportCommand::Maximized(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +162,6 @@ fn close_maximize_minimize(ui: &mut egui::Ui) {
|
||||
.add(Button::new(RichText::new("🗕").size(button_height)))
|
||||
.on_hover_text("Minimize the window");
|
||||
if minimized_response.clicked() {
|
||||
ui.ctx().send_viewport_cmd(ViewportCommand::Minimized(true));
|
||||
ui.send_viewport_cmd(ViewportCommand::Minimized(true));
|
||||
}
|
||||
}
|
||||
|
||||
22
examples/external_eventloop/Cargo.toml
Normal file
22
examples/external_eventloop/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "external_eventloop"
|
||||
version = "0.1.0"
|
||||
authors = ["Will Brown <opensource@rebeagle.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
winit.workspace = true
|
||||
7
examples/external_eventloop/README.md
Normal file
7
examples/external_eventloop/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
Example running an eframe application on an external eventloop.
|
||||
|
||||
This allows you to run your eframe application alongside other windows and/or toolkits on the same event loop.
|
||||
|
||||
```sh
|
||||
cargo run -p external_eventloop
|
||||
```
|
||||
3
examples/external_eventloop/screenshot.png
Normal file
3
examples/external_eventloop/screenshot.png
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:52c47927d0c4caace5e5489cb3c6e4880f4f29b34378e072222ad8492225fef0
|
||||
size 9366
|
||||
89
examples/external_eventloop/src/main.rs
Normal file
89
examples/external_eventloop/src/main.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![expect(rustdoc::missing_crate_level_docs, clippy::unwrap_used)] // it's an example
|
||||
|
||||
use eframe::{UserEvent, egui};
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
let options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let eventloop = EventLoop::<UserEvent>::with_user_event().build().unwrap();
|
||||
eventloop.set_control_flow(ControlFlow::Poll);
|
||||
|
||||
let mut winit_app = eframe::create_native(
|
||||
"External Eventloop Application",
|
||||
options,
|
||||
Box::new(|_| Ok(Box::<MyApp>::default())),
|
||||
&eventloop,
|
||||
);
|
||||
|
||||
eventloop.run_app(&mut winit_app)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct MyApp {
|
||||
value: Rc<Cell<u32>>,
|
||||
spin: bool,
|
||||
blinky: bool,
|
||||
}
|
||||
|
||||
impl Default for MyApp {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
value: Rc::new(Cell::new(42)),
|
||||
spin: false,
|
||||
blinky: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("My External Eventloop Application");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Increment Now").clicked() {
|
||||
self.value.set(self.value.get() + 1);
|
||||
}
|
||||
});
|
||||
ui.label(format!("Value: {}", self.value.get()));
|
||||
|
||||
if ui.button("Toggle Spinner").clicked() {
|
||||
self.spin = !self.spin;
|
||||
}
|
||||
|
||||
if ui.button("Toggle Blinky").clicked() {
|
||||
self.blinky = !self.blinky;
|
||||
}
|
||||
|
||||
if self.spin {
|
||||
ui.spinner();
|
||||
}
|
||||
|
||||
if self.blinky {
|
||||
let now = ui.input(|i| i.time);
|
||||
let blink = now % 1.0 < 0.5;
|
||||
egui::Frame::new()
|
||||
.inner_margin(3)
|
||||
.corner_radius(5)
|
||||
.fill(if blink {
|
||||
egui::Color32::RED
|
||||
} else {
|
||||
egui::Color32::TRANSPARENT
|
||||
})
|
||||
.show(ui, |ui| {
|
||||
ui.label("Blinky!");
|
||||
});
|
||||
|
||||
ui.request_repaint_after_secs((0.5 - (now % 0.5)) as f32);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
32
examples/external_eventloop_async/Cargo.toml
Normal file
32
examples/external_eventloop_async/Cargo.toml
Normal file
@@ -0,0 +1,32 @@
|
||||
[package]
|
||||
name = "external_eventloop_async"
|
||||
version = "0.1.0"
|
||||
authors = ["Will Brown <opensource@rebeagle.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[features]
|
||||
linux-example = []
|
||||
|
||||
[[bin]]
|
||||
name = "external_eventloop_async"
|
||||
required-features = ["linux-example"]
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
log.workspace = true
|
||||
|
||||
winit.workspace = true
|
||||
|
||||
tokio = { workspace = true, features = ["rt", "time", "net"] }
|
||||
10
examples/external_eventloop_async/README.md
Normal file
10
examples/external_eventloop_async/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
Example running an eframe application on an external eventloop on top of a tokio executor on Linux.
|
||||
|
||||
By running the event loop, eframe, and tokio in the same thread, one can leverage local async tasks.
|
||||
These tasks can share data with the UI without the need for locks or message passing.
|
||||
|
||||
In tokio CPU-bound async tasks can be run with `spawn_blocking` to avoid impacting the UI frame rate.
|
||||
|
||||
```sh
|
||||
cargo run -p external_eventloop_async --features linux-example
|
||||
```
|
||||
134
examples/external_eventloop_async/src/app.rs
Normal file
134
examples/external_eventloop_async/src/app.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
#![expect(clippy::unwrap_used)] // It's an example
|
||||
|
||||
use std::{cell::Cell, io, os::fd::AsRawFd as _, rc::Rc, time::Duration};
|
||||
|
||||
use tokio::task::LocalSet;
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
|
||||
use eframe::{EframePumpStatus, UserEvent, egui};
|
||||
|
||||
pub fn run() -> io::Result<()> {
|
||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
let options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut eventloop = EventLoop::<UserEvent>::with_user_event().build().unwrap();
|
||||
eventloop.set_control_flow(ControlFlow::Poll);
|
||||
|
||||
let mut winit_app = eframe::create_native(
|
||||
"External Eventloop Application",
|
||||
options,
|
||||
Box::new(|_| Ok(Box::<MyApp>::default())),
|
||||
&eventloop,
|
||||
);
|
||||
|
||||
let rt = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let local = LocalSet::new();
|
||||
local.block_on(&rt, async {
|
||||
let eventloop_fd = tokio::io::unix::AsyncFd::new(eventloop.as_raw_fd())?;
|
||||
let mut control_flow = ControlFlow::Poll;
|
||||
|
||||
loop {
|
||||
let mut guard = match control_flow {
|
||||
ControlFlow::Poll => None,
|
||||
ControlFlow::Wait => Some(eventloop_fd.readable().await?),
|
||||
ControlFlow::WaitUntil(deadline) => {
|
||||
tokio::time::timeout_at(deadline.into(), eventloop_fd.readable())
|
||||
.await
|
||||
.ok()
|
||||
.transpose()?
|
||||
}
|
||||
};
|
||||
|
||||
match winit_app.pump_eframe_app(&mut eventloop, None) {
|
||||
EframePumpStatus::Continue(next) => control_flow = next,
|
||||
EframePumpStatus::Exit(code) => {
|
||||
log::info!("exit code: {code}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut guard) = guard.take() {
|
||||
guard.clear_ready();
|
||||
}
|
||||
}
|
||||
|
||||
Ok::<_, io::Error>(())
|
||||
})
|
||||
}
|
||||
|
||||
struct MyApp {
|
||||
value: Rc<Cell<u32>>,
|
||||
spin: bool,
|
||||
blinky: bool,
|
||||
}
|
||||
|
||||
impl Default for MyApp {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
value: Rc::new(Cell::new(42)),
|
||||
spin: false,
|
||||
blinky: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("My External Eventloop Application");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Increment Now").clicked() {
|
||||
self.value.set(self.value.get() + 1);
|
||||
}
|
||||
if ui.button("Increment Later").clicked() {
|
||||
let value = Rc::clone(&self.value);
|
||||
let ctx = ui.ctx().clone();
|
||||
tokio::task::spawn_local(async move {
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
value.set(value.get() + 1);
|
||||
ctx.request_repaint();
|
||||
});
|
||||
}
|
||||
});
|
||||
ui.label(format!("Value: {}", self.value.get()));
|
||||
|
||||
if ui.button("Toggle Spinner").clicked() {
|
||||
self.spin = !self.spin;
|
||||
}
|
||||
|
||||
if ui.button("Toggle Blinky").clicked() {
|
||||
self.blinky = !self.blinky;
|
||||
}
|
||||
|
||||
if self.spin {
|
||||
ui.spinner();
|
||||
}
|
||||
|
||||
if self.blinky {
|
||||
let now = ui.input(|i| i.time);
|
||||
let blink = now % 1.0 < 0.5;
|
||||
egui::Frame::new()
|
||||
.inner_margin(3)
|
||||
.corner_radius(5)
|
||||
.fill(if blink {
|
||||
egui::Color32::RED
|
||||
} else {
|
||||
egui::Color32::TRANSPARENT
|
||||
})
|
||||
.show(ui, |ui| {
|
||||
ui.label("Blinky!");
|
||||
});
|
||||
|
||||
ui.request_repaint_after_secs((0.5 - (now % 0.5)) as f32);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
16
examples/external_eventloop_async/src/main.rs
Normal file
16
examples/external_eventloop_async/src/main.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod app;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn main() -> std::io::Result<()> {
|
||||
app::run()
|
||||
}
|
||||
|
||||
// Do not check `app` on unsupported platforms when check "--all-features" is used in CI.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn main() {
|
||||
#![expect(clippy::print_stdout)]
|
||||
println!("This example only supports Linux.");
|
||||
}
|
||||
@@ -3,8 +3,8 @@ name = "file_dialog"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,11 +13,8 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
] }
|
||||
rfd = "0.15.3"
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
rfd.workspace = true
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fb8e0b6d09f6d4c598f4a4d91f849a6221acbfaab55711f890b03d551967d3a8
|
||||
size 3996
|
||||
oid sha256:93689f54b621ab0e978a123492ba64615e67815c39df7e3869f233cdd16f6ded
|
||||
size 5558
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
@@ -25,14 +25,14 @@ struct MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("Drag-and-drop files onto the window!");
|
||||
|
||||
if ui.button("Open file…").clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().pick_file() {
|
||||
self.picked_path = Some(path.display().to_string());
|
||||
}
|
||||
if ui.button("Open file…").clicked()
|
||||
&& let Some(path) = rfd::FileDialog::new().pick_file()
|
||||
{
|
||||
self.picked_path = Some(path.display().to_string());
|
||||
}
|
||||
|
||||
if let Some(picked_path) = &self.picked_path {
|
||||
@@ -73,10 +73,10 @@ impl eframe::App for MyApp {
|
||||
}
|
||||
});
|
||||
|
||||
preview_files_being_dropped(ctx);
|
||||
preview_files_being_dropped(ui.ctx());
|
||||
|
||||
// Collect dropped files:
|
||||
ctx.input(|i| {
|
||||
ui.input(|i| {
|
||||
if !i.raw.dropped_files.is_empty() {
|
||||
self.dropped_files.clone_from(&i.raw.dropped_files);
|
||||
}
|
||||
@@ -107,13 +107,13 @@ fn preview_files_being_dropped(ctx: &egui::Context) {
|
||||
let painter =
|
||||
ctx.layer_painter(LayerId::new(Order::Foreground, Id::new("file_drop_target")));
|
||||
|
||||
let screen_rect = ctx.screen_rect();
|
||||
painter.rect_filled(screen_rect, 0.0, Color32::from_black_alpha(192));
|
||||
let content_rect = ctx.content_rect();
|
||||
painter.rect_filled(content_rect, 0.0, Color32::from_black_alpha(192));
|
||||
painter.text(
|
||||
screen_rect.center(),
|
||||
content_rect.center(),
|
||||
Align2::CENTER_CENTER,
|
||||
text,
|
||||
TextStyle::Heading.resolve(&ctx.style()),
|
||||
TextStyle::Heading.resolve(&ctx.global_style()),
|
||||
Color32::WHITE,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "hello_android"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
# `unsafe_code` is required for `#[no_mangle]`, disable workspace lints to workaround lint error.
|
||||
@@ -17,15 +17,19 @@ crate-type = ["cdylib", "lib"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = ["default", "android-native-activity"] }
|
||||
eframe = { workspace = true, default-features = false, features = [
|
||||
"default_fonts",
|
||||
"glow",
|
||||
"android-native-activity",
|
||||
] }
|
||||
egui_demo_lib = { workspace = true, features = ["chrono"] }
|
||||
|
||||
# For image support:
|
||||
egui_extras = { workspace = true, features = ["default", "image"] }
|
||||
|
||||
log = { workspace = true }
|
||||
winit = { workspace = true }
|
||||
android_logger = "0.14"
|
||||
android_logger.workspace = true
|
||||
log.workspace = true
|
||||
winit.workspace = true
|
||||
|
||||
[package.metadata.android]
|
||||
build_targets = ["armv7-linux-androideabi", "aarch64-linux-android"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use eframe::{egui, CreationContext};
|
||||
use eframe::{CreationContext, egui};
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[no_mangle]
|
||||
@@ -36,15 +36,17 @@ impl MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
// Reserve some space at the top so the demo ui isn't hidden behind the android status bar
|
||||
// TODO(lucasmerlin): This is a pretty big hack, should be fixed once safe_area implemented
|
||||
// for android:
|
||||
// https://github.com/rust-windowing/winit/issues/3910
|
||||
egui::TopBottomPanel::top("status_bar_space").show(ctx, |ui| {
|
||||
egui::Panel::top("status_bar_space").show_inside(ui, |ui| {
|
||||
ui.set_height(32.0);
|
||||
});
|
||||
|
||||
self.demo.ui(ctx);
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
self.demo.ui(ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "hello_world"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,14 +13,11 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
|
||||
# For image support:
|
||||
egui_extras = { workspace = true, features = ["default", "image"] }
|
||||
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
@@ -36,8 +36,8 @@ impl Default for MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("My egui Application");
|
||||
ui.horizontal(|ui| {
|
||||
let name_label = ui.label("Your name: ");
|
||||
|
||||
@@ -3,8 +3,8 @@ 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.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -17,16 +17,13 @@ ignored = ["winit"] # Just enable some features of it; see below
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, default-features = false, features = [
|
||||
# accesskit struggles with threading
|
||||
"default_fonts",
|
||||
"wayland",
|
||||
"x11",
|
||||
"wgpu",
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
# accesskit struggles with threading
|
||||
"default_fonts",
|
||||
"wayland",
|
||||
"x11",
|
||||
"wgpu",
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
# This is normally enabled by eframe/default, which is not being used here
|
||||
# because of accesskit, as mentioned above
|
||||
winit = { workspace = true, features = ["default"] }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! 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
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(clippy::unwrap_used)] // it's an example
|
||||
|
||||
use std::sync::mpsc;
|
||||
use std::thread::JoinHandle;
|
||||
@@ -116,15 +116,15 @@ impl std::ops::Drop for MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::Window::new("Main thread").show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::Window::new("Main thread").show(ui.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());
|
||||
let _ = show_tx.send(ui.ctx().clone());
|
||||
}
|
||||
|
||||
for _ in 0..self.threads.len() {
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "hello_world_simple"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,10 +13,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0bb13d0cb819d30ffbcd12d9327589a1e3ca226943cb381fa17eccfb8f7c06fb
|
||||
size 3229
|
||||
oid sha256:7cde6a351fbcf5a5d3b5474353c627a9c93801563880b7ff41dfa025da3c6d37
|
||||
size 8587
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
use eframe::egui::{Id, Ui};
|
||||
@@ -16,8 +16,8 @@ fn main() -> eframe::Result {
|
||||
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| {
|
||||
eframe::run_ui_native("My egui App", options, move |ui, _frame| {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("My egui Application");
|
||||
ui.horizontal(|ui| {
|
||||
let name_label = ui.label("Your name: ");
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "images"
|
||||
version = "0.1.0"
|
||||
authors = ["Jan Procházka <github.com/jprochazk>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -21,8 +21,5 @@ eframe = { workspace = true, features = [
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
egui_extras = { workspace = true, features = ["default", "all_loaders"] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
image = { workspace = true, features = ["jpeg", "png"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a836741d52e1972b2047cefaabf59f601637d430d4b41bf6407ebda4f7931dac
|
||||
size 273450
|
||||
oid sha256:aab48522ee4e3382982a0ee558a78e7b501ab4205c793a66078c6e74631bd7a5
|
||||
size 79718
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
@@ -24,8 +24,8 @@ fn main() -> eframe::Result {
|
||||
struct MyApp {}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
egui::ScrollArea::both().show(ui, |ui| {
|
||||
ui.image(egui::include_image!("cat.webp"))
|
||||
.on_hover_text_at_pointer("WebP");
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "keyboard_events"
|
||||
version = "0.1.0"
|
||||
authors = ["Jose Palazon <jose@palako.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,10 +13,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6cf53e0da26c4295bafe9cbb9ea0ad8c50933e29eb67467c3a11783697ec5494
|
||||
size 7525
|
||||
oid sha256:c4b314fc336e6cf027594b3ca123318bc4772fb611486170fd370cfa6a56edc5
|
||||
size 9599
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
use egui::{Key, ScrollArea};
|
||||
@@ -20,8 +20,8 @@ struct Content {
|
||||
}
|
||||
|
||||
impl eframe::App for Content {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("Press/Hold/Release example. Press A to test.");
|
||||
if ui.button("Clear").clicked() {
|
||||
self.text.clear();
|
||||
@@ -33,14 +33,14 @@ impl eframe::App for Content {
|
||||
ui.label(&self.text);
|
||||
});
|
||||
|
||||
if ctx.input(|i| i.key_pressed(Key::A)) {
|
||||
if ui.input(|i| i.key_pressed(Key::A)) {
|
||||
self.text.push_str("\nPressed");
|
||||
}
|
||||
if ctx.input(|i| i.key_down(Key::A)) {
|
||||
if ui.input(|i| i.key_down(Key::A)) {
|
||||
self.text.push_str("\nHeld");
|
||||
ui.ctx().request_repaint(); // make sure we note the holding.
|
||||
ui.request_repaint(); // make sure we note the holding.
|
||||
}
|
||||
if ctx.input(|i| i.key_released(Key::A)) {
|
||||
if ui.input(|i| i.key_released(Key::A)) {
|
||||
self.text.push_str("\nReleased");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "multiple_viewports"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -15,10 +15,7 @@ wgpu = ["eframe/wgpu"]
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use eframe::egui;
|
||||
@@ -35,8 +35,8 @@ struct MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("Hello from the root viewport");
|
||||
|
||||
ui.checkbox(
|
||||
@@ -44,55 +44,68 @@ impl eframe::App for MyApp {
|
||||
"Show immediate child viewport",
|
||||
);
|
||||
|
||||
let mut show_deferred_viewport = self.show_deferred_viewport.load(Ordering::Relaxed);
|
||||
ui.checkbox(&mut show_deferred_viewport, "Show deferred child viewport");
|
||||
self.show_deferred_viewport
|
||||
.store(show_deferred_viewport, Ordering::Relaxed);
|
||||
{
|
||||
let mut show_deferred_viewport =
|
||||
self.show_deferred_viewport.load(Ordering::Relaxed);
|
||||
ui.checkbox(&mut show_deferred_viewport, "Show deferred child viewport");
|
||||
self.show_deferred_viewport
|
||||
.store(show_deferred_viewport, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
ui.add_space(16.0);
|
||||
{
|
||||
let mut embedded = ui.embed_viewports();
|
||||
ui.checkbox(&mut embedded, "Embed all viewports");
|
||||
ui.set_embed_viewports(embedded);
|
||||
}
|
||||
});
|
||||
|
||||
if self.show_immediate_viewport {
|
||||
ctx.show_viewport_immediate(
|
||||
ui.ctx().show_viewport_immediate(
|
||||
egui::ViewportId::from_hash_of("immediate_viewport"),
|
||||
egui::ViewportBuilder::default()
|
||||
.with_title("Immediate Viewport")
|
||||
.with_inner_size([200.0, 100.0]),
|
||||
|ctx, class| {
|
||||
assert!(
|
||||
class == egui::ViewportClass::Immediate,
|
||||
"This egui backend doesn't support multiple viewports"
|
||||
);
|
||||
|ui, class| {
|
||||
if class == egui::ViewportClass::EmbeddedWindow {
|
||||
ui.label(
|
||||
"This viewport is embedded in the parent window, and cannot be moved outside of it.",
|
||||
);
|
||||
} else {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("Hello from immediate viewport");
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.label("Hello from immediate viewport");
|
||||
});
|
||||
|
||||
if ctx.input(|i| i.viewport().close_requested()) {
|
||||
// Tell parent viewport that we should not show next frame:
|
||||
self.show_immediate_viewport = false;
|
||||
if ui.input(|i| i.viewport().close_requested()) {
|
||||
// Tell parent viewport that we should not show next frame:
|
||||
self.show_immediate_viewport = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if self.show_deferred_viewport.load(Ordering::Relaxed) {
|
||||
let show_deferred_viewport = self.show_deferred_viewport.clone();
|
||||
ctx.show_viewport_deferred(
|
||||
let show_deferred_viewport = Arc::clone(&self.show_deferred_viewport);
|
||||
ui.ctx().show_viewport_deferred(
|
||||
egui::ViewportId::from_hash_of("deferred_viewport"),
|
||||
egui::ViewportBuilder::default()
|
||||
.with_title("Deferred Viewport")
|
||||
.with_inner_size([200.0, 100.0]),
|
||||
move |ctx, class| {
|
||||
assert!(
|
||||
class == egui::ViewportClass::Deferred,
|
||||
"This egui backend doesn't support multiple viewports"
|
||||
);
|
||||
move |ui, class| {
|
||||
if class == egui::ViewportClass::EmbeddedWindow {
|
||||
ui.label(
|
||||
"This viewport is embedded in the parent window, and cannot be moved outside of it.",
|
||||
);
|
||||
} else {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("Hello from deferred viewport");
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.label("Hello from deferred viewport");
|
||||
});
|
||||
if ctx.input(|i| i.viewport().close_requested()) {
|
||||
// Tell parent to close us.
|
||||
show_deferred_viewport.store(false, Ordering::Relaxed);
|
||||
if ui.input(|i| i.viewport().close_requested()) {
|
||||
// Tell parent to close us.
|
||||
show_deferred_viewport.store(false, Ordering::Relaxed);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -9,13 +9,10 @@ version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
|
||||
[lints]
|
||||
|
||||
@@ -3,3 +3,5 @@ Example of how to use menus, popups, context menus and tooltips.
|
||||
```sh
|
||||
cargo run -p popups
|
||||
```
|
||||
|
||||

|
||||
|
||||
3
examples/popups/screenshot.png
Normal file
3
examples/popups/screenshot.png
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fb79ed9f98a4e5b452f52c9d5a857126481aad7c98e871895b8eea90d89c61c7
|
||||
size 20053
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui::{CentralPanel, ComboBox, Popup, PopupCloseBehavior};
|
||||
|
||||
@@ -18,8 +18,8 @@ struct MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
||||
CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut eframe::egui::Ui, _frame: &mut eframe::Frame) {
|
||||
CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("PopupCloseBehavior::CloseOnClick popup");
|
||||
ComboBox::from_label("ComboBox")
|
||||
.selected_text(format!("{}", self.number))
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "puffin_profiler"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
@@ -20,14 +20,11 @@ wgpu = ["eframe/wgpu"]
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
] }
|
||||
log = { workspace = true }
|
||||
puffin = "0.19"
|
||||
puffin_http = "0.16"
|
||||
profiling = {workspace = true, features = ["profile-with-puffin"] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
log.workspace = true
|
||||
puffin.workspace = true
|
||||
puffin_http.workspace = true
|
||||
profiling = { workspace = true, features = ["profile-with-puffin"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:610b003b4c7715751d2d3753d304e2c5a0af17c9259fa24f21a97b33b9d0c3c7
|
||||
size 8549
|
||||
oid sha256:bfc5dcdf4e4a606cc5b656cfe61d9def9ce1a2eb515003a6a339fefc9335079e
|
||||
size 29711
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
let rust_log = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_owned());
|
||||
std::env::set_var("RUST_LOG", rust_log);
|
||||
|
||||
// SAFETY: we call this from the main thread without any other threads running.
|
||||
#[expect(unsafe_code)]
|
||||
unsafe {
|
||||
std::env::set_var("RUST_LOG", rust_log);
|
||||
};
|
||||
|
||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
start_puffin_server(); // NOTE: you may only want to call this if the users specifies some flag or clicks a button!
|
||||
|
||||
@@ -48,8 +54,8 @@ impl Default for MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.heading("Example of how to use the puffin profiler with egui");
|
||||
ui.separator();
|
||||
|
||||
@@ -59,7 +65,7 @@ impl eframe::App for MyApp {
|
||||
ui.horizontal(|ui| {
|
||||
ui.monospace(cmd);
|
||||
if ui.small_button("📋").clicked() {
|
||||
ui.ctx().copy_text(cmd.into());
|
||||
ui.copy_text(cmd.into());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -69,7 +75,7 @@ impl eframe::App for MyApp {
|
||||
ui.checkbox(&mut self.keep_repainting, "Keep repainting");
|
||||
if self.keep_repainting {
|
||||
ui.spinner();
|
||||
ui.ctx().request_repaint();
|
||||
ui.request_repaint();
|
||||
} else {
|
||||
ui.label("Repainting on events (e.g. mouse movement)");
|
||||
}
|
||||
@@ -97,12 +103,12 @@ impl eframe::App for MyApp {
|
||||
});
|
||||
|
||||
if self.show_immediate_viewport {
|
||||
ctx.show_viewport_immediate(
|
||||
ui.ctx().show_viewport_immediate(
|
||||
egui::ViewportId::from_hash_of("immediate_viewport"),
|
||||
egui::ViewportBuilder::default()
|
||||
.with_title("Immediate Viewport")
|
||||
.with_inner_size([200.0, 100.0]),
|
||||
|ctx, class| {
|
||||
|ui, class| {
|
||||
puffin::profile_scope!("immediate_viewport");
|
||||
|
||||
assert!(
|
||||
@@ -110,11 +116,11 @@ impl eframe::App for MyApp {
|
||||
"This egui backend doesn't support multiple viewports"
|
||||
);
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("Hello from immediate viewport");
|
||||
});
|
||||
|
||||
if ctx.input(|i| i.viewport().close_requested()) {
|
||||
if ui.input(|i| i.viewport().close_requested()) {
|
||||
// Tell parent viewport that we should not show next frame:
|
||||
self.show_immediate_viewport = false;
|
||||
}
|
||||
@@ -123,13 +129,13 @@ impl eframe::App for MyApp {
|
||||
}
|
||||
|
||||
if self.show_deferred_viewport.load(Ordering::Relaxed) {
|
||||
let show_deferred_viewport = self.show_deferred_viewport.clone();
|
||||
ctx.show_viewport_deferred(
|
||||
let show_deferred_viewport = Arc::clone(&self.show_deferred_viewport);
|
||||
ui.ctx().show_viewport_deferred(
|
||||
egui::ViewportId::from_hash_of("deferred_viewport"),
|
||||
egui::ViewportBuilder::default()
|
||||
.with_title("Deferred Viewport")
|
||||
.with_inner_size([200.0, 100.0]),
|
||||
move |ctx, class| {
|
||||
move |ui, class| {
|
||||
puffin::profile_scope!("deferred_viewport");
|
||||
|
||||
assert!(
|
||||
@@ -137,10 +143,10 @@ impl eframe::App for MyApp {
|
||||
"This egui backend doesn't support multiple viewports"
|
||||
);
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.label("Hello from deferred viewport");
|
||||
});
|
||||
if ctx.input(|i| i.viewport().close_requested()) {
|
||||
if ui.input(|i| i.viewport().close_requested()) {
|
||||
// Tell parent to close us.
|
||||
show_deferred_viewport.store(false, Ordering::Relaxed);
|
||||
}
|
||||
@@ -165,11 +171,11 @@ fn start_puffin_server() {
|
||||
|
||||
// We can store the server if we want, but in this case we just want
|
||||
// it to keep running. Dropping it closes the server, so let's not drop it!
|
||||
#[allow(clippy::mem_forget)]
|
||||
#[expect(clippy::mem_forget)]
|
||||
std::mem::forget(puffin_server);
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("Failed to start puffin server: {err}");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
[package]
|
||||
name = "screenshot"
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"René Rössler <rene@freshx.de>",
|
||||
"Andreas Faber <andreas.mfaber@gmail.com",
|
||||
]
|
||||
authors = ["René Rössler <rene@freshx.de>", "Andreas Faber <andreas.mfaber@gmail.com"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -16,12 +13,9 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
"wgpu",
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
"wgpu",
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
image = { workspace = true, features = ["png"] }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs, clippy::unwrap_used)] // it's an example
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -27,8 +27,8 @@ struct MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
if let Some(screenshot) = self.screenshot.take() {
|
||||
self.texture = Some(ui.ctx().load_texture(
|
||||
"screenshot",
|
||||
@@ -45,7 +45,7 @@ impl eframe::App for MyApp {
|
||||
|
||||
if ui.button("save to 'top_left.png'").clicked() {
|
||||
self.save_to_file = true;
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Screenshot(Default::default()));
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::Screenshot(Default::default()));
|
||||
}
|
||||
|
||||
ui.with_layout(egui::Layout::top_down(egui::Align::RIGHT), |ui| {
|
||||
@@ -54,17 +54,13 @@ impl eframe::App for MyApp {
|
||||
.add(egui::Label::new("hover me!").sense(egui::Sense::hover()))
|
||||
.hovered()
|
||||
{
|
||||
ctx.set_theme(egui::Theme::Dark);
|
||||
ui.ctx().set_theme(egui::Theme::Dark);
|
||||
} else {
|
||||
ctx.set_theme(egui::Theme::Light);
|
||||
};
|
||||
ctx.send_viewport_cmd(
|
||||
egui::ViewportCommand::Screenshot(Default::default()),
|
||||
);
|
||||
ui.ctx().set_theme(egui::Theme::Light);
|
||||
}
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::Screenshot(Default::default()));
|
||||
} else if ui.button("take screenshot!").clicked() {
|
||||
ctx.send_viewport_cmd(
|
||||
egui::ViewportCommand::Screenshot(Default::default()),
|
||||
);
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::Screenshot(Default::default()));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -96,12 +92,12 @@ impl eframe::App for MyApp {
|
||||
.unwrap();
|
||||
self.save_to_file = false;
|
||||
}
|
||||
self.screenshot = Some(image.clone());
|
||||
self.screenshot = Some(Arc::clone(image));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ctx.request_repaint();
|
||||
ui.request_repaint();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "serial_windows"
|
||||
version = "0.1.0"
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -13,11 +13,8 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
] }
|
||||
log = { workspace = true }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
log.workspace = true
|
||||
|
||||
@@ -7,8 +7,7 @@ Expected order of execution:
|
||||
- Similarly, when the second window is closed after a delay a third will be shown.
|
||||
- Once the third is closed the program will stop.
|
||||
|
||||
NOTE: this doesn't work on Mac due to <https://github.com/rust-windowing/winit/issues/2431>.
|
||||
See also <https://github.com/emilk/egui/issues/1918>.
|
||||
NOTE: this doesn't work on Mac. See also <https://github.com/emilk/egui/issues/1918>.
|
||||
|
||||
```sh
|
||||
cargo run -p serial_windows
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
|
||||
@@ -43,8 +43,8 @@ struct MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
let label_text = if self.has_next {
|
||||
"When this window is closed the next will be opened after a short delay"
|
||||
} else {
|
||||
@@ -54,7 +54,7 @@ impl eframe::App for MyApp {
|
||||
|
||||
if ui.button("Close").clicked() {
|
||||
log::info!("Pressed Close button");
|
||||
ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ name = "user_attention"
|
||||
version = "0.1.0"
|
||||
authors = ["TicClick <ya@ticclick.ch>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.81"
|
||||
edition = "2024"
|
||||
rust-version = "1.92"
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
@@ -12,10 +12,7 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
eframe = { workspace = true, features = [
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { version = "0.10", default-features = false, features = [
|
||||
"auto-color",
|
||||
"humantime",
|
||||
"default",
|
||||
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
|
||||
] }
|
||||
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:85a508fa7d16d9bc51f38d3531b30f024d8888f7f74bf2f351453fd13d13e0aa
|
||||
size 5928
|
||||
oid sha256:d3b56bdd917a8f789f5bad954bbd37fc27ddec404025dd0608894e5d50e9f37f
|
||||
size 7375
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
#![expect(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::{egui, CreationContext, NativeOptions};
|
||||
use egui::{Button, CentralPanel, Context, UserAttentionType};
|
||||
use eframe::{CreationContext, NativeOptions, egui};
|
||||
use egui::{Button, CentralPanel, UserAttentionType};
|
||||
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
@@ -55,28 +55,28 @@ impl Application {
|
||||
}
|
||||
|
||||
impl eframe::App for Application {
|
||||
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
|
||||
if let Some(request_at) = self.request_at {
|
||||
if request_at < SystemTime::now() {
|
||||
self.request_at = None;
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::RequestUserAttention(self.attention));
|
||||
if self.auto_reset {
|
||||
self.auto_reset = false;
|
||||
self.reset_at = Some(SystemTime::now() + Self::attention_reset_timeout());
|
||||
}
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
if let Some(request_at) = self.request_at
|
||||
&& request_at < SystemTime::now()
|
||||
{
|
||||
self.request_at = None;
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::RequestUserAttention(self.attention));
|
||||
if self.auto_reset {
|
||||
self.auto_reset = false;
|
||||
self.reset_at = Some(SystemTime::now() + Self::attention_reset_timeout());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(reset_at) = self.reset_at {
|
||||
if reset_at < SystemTime::now() {
|
||||
self.reset_at = None;
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::RequestUserAttention(
|
||||
UserAttentionType::Reset,
|
||||
));
|
||||
}
|
||||
if let Some(reset_at) = self.reset_at
|
||||
&& reset_at < SystemTime::now()
|
||||
{
|
||||
self.reset_at = None;
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::RequestUserAttention(
|
||||
UserAttentionType::Reset,
|
||||
));
|
||||
}
|
||||
|
||||
CentralPanel::default().show(ctx, |ui| {
|
||||
CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Attention type:");
|
||||
@@ -131,6 +131,6 @@ impl eframe::App for Application {
|
||||
});
|
||||
});
|
||||
|
||||
ctx.request_repaint_after(Self::repaint_max_timeout());
|
||||
ui.request_repaint_after(Self::repaint_max_timeout());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user