mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -04:00
Allow for requesting the user's attention to the window (#2905)
* add method for requesting attention to the main window * use another enum member for user attention type instead of nested `Option`s (also, document the enum members now that they don't mirror `winit`) * update the docstring Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com> * add an example app for testing window attention requests * Apply suggestions from code review Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com> * remove `chrono` dependency and improve the attention example's readability --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
11
examples/user_attention/Cargo.toml
Normal file
11
examples/user_attention/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "user_attention"
|
||||
version = "0.1.0"
|
||||
authors = ["TicClick <ya@ticclick.ch>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
eframe = { path = "../../crates/eframe" }
|
||||
7
examples/user_attention/README.mg
Normal file
7
examples/user_attention/README.mg
Normal file
@@ -0,0 +1,7 @@
|
||||
An example of requesting a user's attention to the main window, and resetting the ongoing attention animations when necessary. Only works on native platforms.
|
||||
|
||||
```sh
|
||||
cargo run -p user_attention
|
||||
```
|
||||
|
||||

|
||||
BIN
examples/user_attention/screenshot.png
Normal file
BIN
examples/user_attention/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
130
examples/user_attention/src/main.rs
Normal file
130
examples/user_attention/src/main.rs
Normal file
@@ -0,0 +1,130 @@
|
||||
use eframe::egui::{Button, CentralPanel, Context, UserAttentionType};
|
||||
use eframe::{CreationContext, NativeOptions};
|
||||
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
fn repr(attention: UserAttentionType) -> String {
|
||||
format!("{:?}", attention)
|
||||
}
|
||||
|
||||
struct Application {
|
||||
attention: UserAttentionType,
|
||||
request_at: Option<SystemTime>,
|
||||
|
||||
auto_reset: bool,
|
||||
reset_at: Option<SystemTime>,
|
||||
}
|
||||
|
||||
impl Application {
|
||||
fn new(_cc: &CreationContext<'_>) -> Self {
|
||||
Self {
|
||||
attention: UserAttentionType::Informational,
|
||||
request_at: None,
|
||||
auto_reset: false,
|
||||
reset_at: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn attention_reset_timeout() -> Duration {
|
||||
Duration::from_secs(3)
|
||||
}
|
||||
|
||||
fn attention_request_timeout() -> Duration {
|
||||
Duration::from_secs(2)
|
||||
}
|
||||
|
||||
fn repaint_max_timeout() -> Duration {
|
||||
Duration::from_secs(1)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
frame.request_user_attention(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;
|
||||
frame.request_user_attention(UserAttentionType::Reset);
|
||||
}
|
||||
}
|
||||
|
||||
CentralPanel::default().show(ctx, |ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Attention type:");
|
||||
eframe::egui::ComboBox::new("attention", "")
|
||||
.selected_text(repr(self.attention))
|
||||
.show_ui(ui, |ui| {
|
||||
for kind in [
|
||||
UserAttentionType::Informational,
|
||||
UserAttentionType::Critical,
|
||||
] {
|
||||
ui.selectable_value(&mut self.attention, kind, repr(kind));
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
let button_enabled = self.request_at.is_none() && self.reset_at.is_none();
|
||||
let button_text = if button_enabled {
|
||||
format!(
|
||||
"Request in {} seconds",
|
||||
Self::attention_request_timeout().as_secs()
|
||||
)
|
||||
} else {
|
||||
match self.reset_at {
|
||||
None => "Unfocus the window, fast!".to_owned(),
|
||||
Some(t) => {
|
||||
if let Ok(elapsed) = t.duration_since(SystemTime::now()) {
|
||||
format!("Resetting attention in {} s...", elapsed.as_secs())
|
||||
} else {
|
||||
"Resetting attention...".to_owned()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let resp = ui
|
||||
.add_enabled(button_enabled, Button::new(button_text))
|
||||
.on_hover_text_at_pointer(
|
||||
"After clicking, unfocus the application's window to see the effect",
|
||||
);
|
||||
|
||||
ui.checkbox(
|
||||
&mut self.auto_reset,
|
||||
format!(
|
||||
"Reset after {} seconds",
|
||||
Self::attention_reset_timeout().as_secs()
|
||||
),
|
||||
);
|
||||
|
||||
if resp.clicked() {
|
||||
self.request_at = Some(SystemTime::now() + Self::attention_request_timeout());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ctx.request_repaint_after(Self::repaint_max_timeout());
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> eframe::Result<()> {
|
||||
let native_options = NativeOptions {
|
||||
initial_window_size: Some(eframe::egui::vec2(400., 200.)),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"User attention test",
|
||||
native_options,
|
||||
Box::new(|cc| Box::new(Application::new(cc))),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user