mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 14:49:06 -04:00
eframe: Replace Frame::update with fn logic and fn ui (#7775)
* Part of https://github.com/emilk/egui/issues/5113 * Part of https://github.com/emilk/egui/issues/3524 ## What This deprecates `eframe::App::update` and replaces it with two new functions: ```rs pub trait App { /// Called just before `ui`, and in the future this will /// also be called for background apps when needed. fn logic(&mut self, ctx: &egui::Context, frame: &mut Frame) { } /// Show your user interface to the user. fn ui(&mut self, ui: &mut egui::Ui, frame: &mut Frame); … } ``` Similarly, `Context::run` is deprecated in favor of `Context::run_ui`. `Plugin`s are now handed a `Ui` instead of just a `Context` in `on_begin/end_frame`. ## TODO …either in this PR or a later one * [x] Deprecate `App::update` * [x] Deprecate `Context::run` * [x] Change plugins to get a `Ui` * [x] Update kittest * [x] Change viewports to get UI:s (`show_viewport_immediate` etc) - https://github.com/emilk/egui/pull/7779 ## Later PRs * [ ] Deprecate `Panel::show` * [ ] Deprecate `CentralPanel::show` * [ ] Deprecate `CentralPanel` ?
This commit is contained in:
@@ -135,6 +135,31 @@ impl CreationContext<'_> {
|
||||
|
||||
/// Implement this trait to write apps that can be compiled for both web/wasm and desktop/native using [`eframe`](https://github.com/emilk/egui/tree/main/crates/eframe).
|
||||
pub trait App {
|
||||
/// Called once before each call to [`Self::ui`],
|
||||
/// and additionally also called when the UI is hidden, but [`egui::Context::request_repaint`] was called.
|
||||
///
|
||||
/// You may NOT show any ui or do any painting during the call to [`Self::logic`].
|
||||
///
|
||||
/// The [`egui::Context`] can be cloned and saved if you like.
|
||||
///
|
||||
/// To force another call to [`Self::logic`], call [`egui::Context::request_repaint`] at any time (e.g. from another thread).
|
||||
fn logic(&mut self, ctx: &egui::Context, frame: &mut Frame) {
|
||||
_ = (ctx, frame);
|
||||
}
|
||||
|
||||
/// Called each time the UI needs repainting, which may be many times per second.
|
||||
///
|
||||
/// The given [`egui::Ui`] has no margin or background color.
|
||||
/// You can wrap your UI code in [`egui::CentralPanel`] or a [`egui::Frame::central_panel`] to remedy this.
|
||||
///
|
||||
/// The [`egui::Ui::ctx`] can be cloned and saved if you like.
|
||||
/// To force a repaint, call [`egui::Context::request_repaint`] at any time (e.g. from another thread).
|
||||
///
|
||||
/// This is called for the root viewport ([`egui::ViewportId::ROOT`]).
|
||||
/// Use [`egui::Context::show_viewport_deferred`] to spawn additional viewports (windows).
|
||||
/// (A "viewport" in egui means an native OS window).
|
||||
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut Frame);
|
||||
|
||||
/// Called each time the UI needs repainting, which may be many times per second.
|
||||
///
|
||||
/// Put your widgets into a [`egui::Panel`], [`egui::CentralPanel`], [`egui::Window`] or [`egui::Area`].
|
||||
@@ -146,7 +171,10 @@ pub trait App {
|
||||
/// This is called for the root viewport ([`egui::ViewportId::ROOT`]).
|
||||
/// Use [`egui::Context::show_viewport_deferred`] to spawn additional viewports (windows).
|
||||
/// (A "viewport" in egui means an native OS window).
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut Frame);
|
||||
#[deprecated = "Use Self::ui instead"]
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) {
|
||||
_ = (ctx, frame);
|
||||
}
|
||||
|
||||
/// Get a handle to the app.
|
||||
///
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
//!
|
||||
//! impl MyEguiApp {
|
||||
//! fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
||||
//! // Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_visuals.
|
||||
//! // Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_global_style.
|
||||
//! // Restore app state using cc.storage (requires the "persistence" feature).
|
||||
//! // Use the cc.gl (a glow::Context) to create graphics shaders and buffers that you can use
|
||||
//! // for e.g. egui::PaintCallback.
|
||||
@@ -44,8 +44,8 @@
|
||||
//! }
|
||||
//!
|
||||
//! impl eframe::App for MyEguiApp {
|
||||
//! 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("Hello World!");
|
||||
//! });
|
||||
//! }
|
||||
@@ -232,7 +232,7 @@ pub mod icon_data;
|
||||
///
|
||||
/// impl MyEguiApp {
|
||||
/// fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
||||
/// // Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_visuals.
|
||||
/// // Customize egui here with cc.egui_ctx.set_fonts and cc.egui_ctx.set_global_style.
|
||||
/// // Restore app state using cc.storage (requires the "persistence" feature).
|
||||
/// // Use the cc.gl (a glow::Context) to create graphics shaders and buffers that you can use
|
||||
/// // for e.g. egui::PaintCallback.
|
||||
@@ -241,8 +241,8 @@ pub mod icon_data;
|
||||
/// }
|
||||
///
|
||||
/// impl eframe::App for MyEguiApp {
|
||||
/// 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("Hello World!");
|
||||
/// });
|
||||
/// }
|
||||
@@ -312,8 +312,8 @@ pub fn run_native(
|
||||
/// }
|
||||
///
|
||||
/// impl eframe::App for MyEguiApp {
|
||||
/// 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("Hello World!");
|
||||
/// });
|
||||
/// }
|
||||
@@ -399,8 +399,9 @@ fn init_native(app_name: &str, native_options: &mut NativeOptions) -> Renderer {
|
||||
/// let mut age = 42;
|
||||
///
|
||||
/// let options = eframe::NativeOptions::default();
|
||||
/// eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
||||
/// egui::CentralPanel::default().show(ctx, |ui| {
|
||||
/// eframe::run_ui_native("My egui App", options, move |ui, _frame| {
|
||||
/// // Wrap everything in a CentralPanel so we get some margins and a background color:
|
||||
/// egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
/// ui.heading("My egui Application");
|
||||
/// ui.horizontal(|ui| {
|
||||
/// let name_label = ui.label("Your name: ");
|
||||
@@ -421,6 +422,65 @@ fn init_native(app_name: &str, native_options: &mut NativeOptions) -> Renderer {
|
||||
/// This function can fail if we fail to set up a graphics context.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
|
||||
pub fn run_ui_native(
|
||||
app_name: &str,
|
||||
native_options: NativeOptions,
|
||||
ui_fun: impl FnMut(&mut egui::Ui, &mut Frame) + 'static,
|
||||
) -> Result {
|
||||
struct SimpleApp<U> {
|
||||
ui_fun: U,
|
||||
}
|
||||
|
||||
impl<U: FnMut(&mut egui::Ui, &mut Frame) + 'static> App for SimpleApp<U> {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut Frame) {
|
||||
(self.ui_fun)(ui, frame);
|
||||
}
|
||||
}
|
||||
|
||||
run_native(
|
||||
app_name,
|
||||
native_options,
|
||||
Box::new(|_cc| Ok(Box::new(SimpleApp { ui_fun }))),
|
||||
)
|
||||
}
|
||||
|
||||
/// The simplest way to get started when writing a native app.
|
||||
///
|
||||
/// This does NOT support persistence of custom user data. For that you need to use [`run_native`].
|
||||
/// However, it DOES support persistence of egui data (window positions and sizes, how far the user has scrolled in a
|
||||
/// [`ScrollArea`](egui::ScrollArea), etc.) if the persistence feature is enabled.
|
||||
///
|
||||
/// # Example
|
||||
/// ``` no_run
|
||||
/// fn main() -> eframe::Result {
|
||||
/// // Our application state:
|
||||
/// let mut name = "Arthur".to_owned();
|
||||
/// let mut age = 42;
|
||||
///
|
||||
/// let options = eframe::NativeOptions::default();
|
||||
/// eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
||||
/// egui::CentralPanel::default().show(ctx, |ui| {
|
||||
/// ui.heading("My egui Application");
|
||||
/// ui.horizontal(|ui| {
|
||||
/// let name_label = ui.label("Your name: ");
|
||||
/// ui.text_edit_singleline(&mut name)
|
||||
/// .labelled_by(name_label.id);
|
||||
/// });
|
||||
/// ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
||||
/// if ui.button("Increment").clicked() {
|
||||
/// age += 1;
|
||||
/// }
|
||||
/// ui.label(format!("Hello '{name}', age {age}"));
|
||||
/// });
|
||||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Errors
|
||||
/// This function can fail if we fail to set up a graphics context.
|
||||
#[deprecated = "Use run_ui_native instead"]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
|
||||
pub fn run_simple_native(
|
||||
app_name: &str,
|
||||
native_options: NativeOptions,
|
||||
@@ -431,6 +491,8 @@ pub fn run_simple_native(
|
||||
}
|
||||
|
||||
impl<U: FnMut(&egui::Context, &mut Frame) + 'static> App for SimpleApp<U> {
|
||||
fn ui(&mut self, _ui: &mut egui::Ui, _frame: &mut Frame) {}
|
||||
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut Frame) {
|
||||
(self.update_fun)(ctx, frame);
|
||||
}
|
||||
|
||||
@@ -272,14 +272,27 @@ impl EpiIntegration {
|
||||
|
||||
app.raw_input_hook(&self.egui_ctx, &mut raw_input);
|
||||
|
||||
let full_output = self.egui_ctx.run(raw_input, |egui_ctx| {
|
||||
let full_output = self.egui_ctx.run_ui(raw_input, |ui| {
|
||||
if let Some(viewport_ui_cb) = viewport_ui_cb {
|
||||
// Child viewport
|
||||
profiling::scope!("viewport_callback");
|
||||
viewport_ui_cb(egui_ctx);
|
||||
viewport_ui_cb(ui);
|
||||
} else {
|
||||
profiling::scope!("App::update");
|
||||
app.update(egui_ctx, &mut self.frame);
|
||||
{
|
||||
profiling::scope!("App::logic");
|
||||
app.logic(ui.ctx(), &mut self.frame);
|
||||
}
|
||||
|
||||
{
|
||||
profiling::scope!("App::update");
|
||||
#[expect(deprecated)]
|
||||
app.update(ui.ctx(), &mut self.frame);
|
||||
}
|
||||
|
||||
{
|
||||
profiling::scope!("App::ui");
|
||||
app.ui(ui, &mut self.frame);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1362,7 +1362,7 @@ fn initialize_or_update_viewport(
|
||||
ids: ViewportIdPair,
|
||||
class: ViewportClass,
|
||||
mut builder: ViewportBuilder,
|
||||
viewport_ui_cb: Option<Arc<dyn Fn(&egui::Context) + Send + Sync>>,
|
||||
viewport_ui_cb: Option<Arc<dyn Fn(&mut egui::Ui) + Send + Sync>>,
|
||||
) -> &mut Viewport {
|
||||
profiling::function_scope!();
|
||||
|
||||
@@ -1494,8 +1494,8 @@ fn render_immediate_viewport(
|
||||
shapes,
|
||||
pixels_per_point,
|
||||
viewport_output,
|
||||
} = egui_ctx.run(input, |ctx| {
|
||||
viewport_ui_cb(ctx);
|
||||
} = egui_ctx.run_ui(input, |ui| {
|
||||
viewport_ui_cb(ui);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
@@ -1027,8 +1027,8 @@ fn render_immediate_viewport(
|
||||
shapes,
|
||||
pixels_per_point,
|
||||
viewport_output,
|
||||
} = egui_ctx.run(input, |ctx| {
|
||||
viewport_ui_cb(ctx);
|
||||
} = egui_ctx.run_ui(input, |ui| {
|
||||
viewport_ui_cb(ui);
|
||||
});
|
||||
|
||||
// ------------------------------------------
|
||||
@@ -1155,7 +1155,7 @@ fn initialize_or_update_viewport<'a>(
|
||||
ids: ViewportIdPair,
|
||||
class: ViewportClass,
|
||||
mut builder: ViewportBuilder,
|
||||
viewport_ui_cb: Option<Arc<dyn Fn(&egui::Context) + Send + Sync>>,
|
||||
viewport_ui_cb: Option<Arc<dyn Fn(&mut egui::Ui) + Send + Sync>>,
|
||||
painter: &mut egui_wgpu::winit::Painter,
|
||||
) -> &'a mut Viewport {
|
||||
use std::collections::btree_map::Entry;
|
||||
|
||||
@@ -273,8 +273,13 @@ impl AppRunner {
|
||||
|
||||
self.app.raw_input_hook(&self.egui_ctx, &mut raw_input);
|
||||
|
||||
let full_output = self.egui_ctx.run(raw_input, |egui_ctx| {
|
||||
self.app.update(egui_ctx, &mut self.frame);
|
||||
let full_output = self.egui_ctx.run_ui(raw_input, |ui| {
|
||||
self.app.logic(ui.ctx(), &mut self.frame);
|
||||
|
||||
#[expect(deprecated)]
|
||||
self.app.update(ui.ctx(), &mut self.frame);
|
||||
|
||||
self.app.ui(ui, &mut self.frame);
|
||||
});
|
||||
let egui::FullOutput {
|
||||
platform_output,
|
||||
|
||||
@@ -291,13 +291,13 @@ impl<'a> PanelSizer<'a> {
|
||||
/// See the [module level docs](crate::containers::panel) for more details.
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ctx(|ctx| {
|
||||
/// egui::Panel::left("my_left_panel").show(ctx, |ui| {
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// egui::Panel::left("my_left_panel").show_inside(ui, |ui| {
|
||||
/// ui.label("Hello World!");
|
||||
/// });
|
||||
/// # });
|
||||
/// ```
|
||||
#[must_use = "You should call .show()"]
|
||||
#[must_use = "You should call .show_inside()"]
|
||||
pub struct Panel {
|
||||
side: PanelSide,
|
||||
id: Id,
|
||||
@@ -963,16 +963,16 @@ impl Panel {
|
||||
/// See the [module level docs](crate::containers::panel) for more details.
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ctx(|ctx| {
|
||||
/// egui::Panel::top("my_panel").show(ctx, |ui| {
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// egui::Panel::top("my_panel").show_inside(ui, |ui| {
|
||||
/// ui.label("Hello World! From `Panel`, that must be before `CentralPanel`!");
|
||||
/// });
|
||||
/// egui::CentralPanel::default().show(ctx, |ui| {
|
||||
/// egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
/// ui.label("Hello World!");
|
||||
/// });
|
||||
/// # });
|
||||
/// ```
|
||||
#[must_use = "You should call .show()"]
|
||||
#[must_use = "You should call .show_inside()"]
|
||||
#[derive(Default)]
|
||||
pub struct CentralPanel {
|
||||
frame: Option<Frame>,
|
||||
|
||||
@@ -790,9 +790,13 @@ impl Context {
|
||||
|
||||
#[must_use]
|
||||
fn run_ui_dyn(&self, new_input: RawInput, run_ui: &mut dyn FnMut(&mut Ui)) -> FullOutput {
|
||||
let plugins = self.read(|ctx| ctx.plugins.ordered_plugins());
|
||||
#[expect(deprecated)]
|
||||
self.run(new_input, |ctx| {
|
||||
crate::CentralPanel::no_frame().show(ctx, |ui| {
|
||||
plugins.on_begin_pass(ui);
|
||||
run_ui(ui);
|
||||
plugins.on_end_pass(ui);
|
||||
});
|
||||
})
|
||||
}
|
||||
@@ -824,6 +828,7 @@ impl Context {
|
||||
/// ## See also
|
||||
/// * [`Self::run_ui`]
|
||||
#[must_use]
|
||||
#[deprecated = "Call run_ui instead"]
|
||||
pub fn run(&self, new_input: RawInput, mut run_ui: impl FnMut(&Self)) -> FullOutput {
|
||||
self.run_dyn(new_input, &mut run_ui)
|
||||
}
|
||||
@@ -924,9 +929,6 @@ impl Context {
|
||||
plugins.on_input(&mut new_input);
|
||||
|
||||
self.write(|ctx| ctx.begin_pass(new_input));
|
||||
|
||||
// Plugins run just after the pass starts:
|
||||
plugins.on_begin_pass(self);
|
||||
}
|
||||
|
||||
/// See [`Self::begin_pass`].
|
||||
@@ -2378,15 +2380,14 @@ impl Context {
|
||||
crate::gui_zoom::zoom_with_keyboard(self);
|
||||
}
|
||||
|
||||
// Plugins run just before the pass ends.
|
||||
let plugins = self.read(|ctx| ctx.plugins.ordered_plugins());
|
||||
plugins.on_end_pass(self);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self.debug_painting();
|
||||
|
||||
let mut output = self.write(|ctx| ctx.end_pass());
|
||||
|
||||
let plugins = self.read(|ctx| ctx.plugins.ordered_plugins());
|
||||
plugins.on_output(&mut output);
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
@@ -4039,10 +4040,8 @@ impl Context {
|
||||
viewport.class = ViewportClass::Deferred;
|
||||
viewport.builder = viewport_builder;
|
||||
viewport.used = true;
|
||||
viewport.viewport_ui_cb = Some(Arc::new(move |ctx| {
|
||||
crate::CentralPanel::no_frame().show(ctx, |ui| {
|
||||
(viewport_ui_cb)(ui, ViewportClass::Deferred);
|
||||
});
|
||||
viewport.viewport_ui_cb = Some(Arc::new(move |ui| {
|
||||
(viewport_ui_cb)(ui, ViewportClass::Deferred);
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -4118,10 +4117,8 @@ impl Context {
|
||||
let viewport = ImmediateViewport {
|
||||
ids,
|
||||
builder,
|
||||
viewport_ui_cb: Box::new(move |ctx| {
|
||||
crate::CentralPanel::no_frame().show(ctx, |ui| {
|
||||
*out = Some((viewport_ui_cb)(ui, ViewportClass::Immediate));
|
||||
});
|
||||
viewport_ui_cb: Box::new(move |ui| {
|
||||
*out = Some((viewport_ui_cb)(ui, ViewportClass::Immediate));
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -4246,11 +4243,11 @@ mod test {
|
||||
// A single call, no request to discard:
|
||||
{
|
||||
let mut num_calls = 0;
|
||||
let output = ctx.run(Default::default(), |ctx| {
|
||||
let output = ctx.run_ui(Default::default(), |ui| {
|
||||
num_calls += 1;
|
||||
assert_eq!(ctx.output(|o| o.num_completed_passes), 0);
|
||||
assert!(!ctx.output(|o| o.requested_discard()));
|
||||
assert!(!ctx.will_discard());
|
||||
assert_eq!(ui.output(|o| o.num_completed_passes), 0);
|
||||
assert!(!ui.output(|o| o.requested_discard()));
|
||||
assert!(!ui.will_discard());
|
||||
});
|
||||
assert_eq!(num_calls, 1);
|
||||
assert_eq!(output.platform_output.num_completed_passes, 1);
|
||||
@@ -4260,10 +4257,10 @@ mod test {
|
||||
// A single call, with a denied request to discard:
|
||||
{
|
||||
let mut num_calls = 0;
|
||||
let output = ctx.run(Default::default(), |ctx| {
|
||||
let output = ctx.run_ui(Default::default(), |ui| {
|
||||
num_calls += 1;
|
||||
ctx.request_discard("test");
|
||||
assert!(!ctx.will_discard(), "The request should have been denied");
|
||||
ui.request_discard("test");
|
||||
assert!(!ui.will_discard(), "The request should have been denied");
|
||||
});
|
||||
assert_eq!(num_calls, 1);
|
||||
assert_eq!(output.platform_output.num_completed_passes, 1);
|
||||
@@ -4291,10 +4288,10 @@ mod test {
|
||||
// Normal single pass:
|
||||
{
|
||||
let mut num_calls = 0;
|
||||
let output = ctx.run(Default::default(), |ctx| {
|
||||
assert_eq!(ctx.output(|o| o.num_completed_passes), 0);
|
||||
assert!(!ctx.output(|o| o.requested_discard()));
|
||||
assert!(!ctx.will_discard());
|
||||
let output = ctx.run_ui(Default::default(), |ui| {
|
||||
assert_eq!(ui.output(|o| o.num_completed_passes), 0);
|
||||
assert!(!ui.output(|o| o.requested_discard()));
|
||||
assert!(!ui.will_discard());
|
||||
num_calls += 1;
|
||||
});
|
||||
assert_eq!(num_calls, 1);
|
||||
@@ -4305,13 +4302,13 @@ mod test {
|
||||
// Request discard once:
|
||||
{
|
||||
let mut num_calls = 0;
|
||||
let output = ctx.run(Default::default(), |ctx| {
|
||||
assert_eq!(ctx.output(|o| o.num_completed_passes), num_calls);
|
||||
let output = ctx.run_ui(Default::default(), |ui| {
|
||||
assert_eq!(ui.output(|o| o.num_completed_passes), num_calls);
|
||||
|
||||
assert!(!ctx.will_discard());
|
||||
assert!(!ui.will_discard());
|
||||
if num_calls == 0 {
|
||||
ctx.request_discard("test");
|
||||
assert!(ctx.will_discard());
|
||||
ui.request_discard("test");
|
||||
assert!(ui.will_discard());
|
||||
}
|
||||
|
||||
num_calls += 1;
|
||||
@@ -4327,15 +4324,15 @@ mod test {
|
||||
// Request discard twice:
|
||||
{
|
||||
let mut num_calls = 0;
|
||||
let output = ctx.run(Default::default(), |ctx| {
|
||||
assert_eq!(ctx.output(|o| o.num_completed_passes), num_calls);
|
||||
let output = ctx.run_ui(Default::default(), |ui| {
|
||||
assert_eq!(ui.output(|o| o.num_completed_passes), num_calls);
|
||||
|
||||
assert!(!ctx.will_discard());
|
||||
ctx.request_discard("test");
|
||||
assert!(!ui.will_discard());
|
||||
ui.request_discard("test");
|
||||
if num_calls == 0 {
|
||||
assert!(ctx.will_discard(), "First request granted");
|
||||
assert!(ui.will_discard(), "First request granted");
|
||||
} else {
|
||||
assert!(!ctx.will_discard(), "Second request should be denied");
|
||||
assert!(!ui.will_discard(), "Second request should be denied");
|
||||
}
|
||||
|
||||
num_calls += 1;
|
||||
@@ -4357,13 +4354,13 @@ mod test {
|
||||
// Request discard three times:
|
||||
{
|
||||
let mut num_calls = 0;
|
||||
let output = ctx.run(Default::default(), |ctx| {
|
||||
assert_eq!(ctx.output(|o| o.num_completed_passes), num_calls);
|
||||
let output = ctx.run_ui(Default::default(), |ui| {
|
||||
assert_eq!(ui.output(|o| o.num_completed_passes), num_calls);
|
||||
|
||||
assert!(!ctx.will_discard());
|
||||
assert!(!ui.will_discard());
|
||||
if num_calls <= 2 {
|
||||
ctx.request_discard("test");
|
||||
assert!(ctx.will_discard());
|
||||
ui.request_discard("test");
|
||||
assert!(ui.will_discard());
|
||||
}
|
||||
|
||||
num_calls += 1;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! to get callbacks on certain events ([`Plugin::on_begin_pass`], [`Plugin::on_end_pass`]).
|
||||
|
||||
use crate::{
|
||||
Align, Align2, Color32, Context, FontFamily, FontId, Plugin, Rect, Shape, Vec2, WidgetText,
|
||||
Align, Align2, Color32, Context, FontFamily, FontId, Plugin, Rect, Shape, Ui, Vec2, WidgetText,
|
||||
text,
|
||||
};
|
||||
|
||||
@@ -57,9 +57,9 @@ impl Plugin for DebugTextPlugin {
|
||||
"DebugTextPlugin"
|
||||
}
|
||||
|
||||
fn on_end_pass(&mut self, ctx: &Context) {
|
||||
fn on_end_pass(&mut self, ui: &mut Ui) {
|
||||
let entries = std::mem::take(&mut self.entries);
|
||||
Self::paint_entries(ctx, entries);
|
||||
Self::paint_entries(ui, entries);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{any::Any, sync::Arc};
|
||||
|
||||
use crate::{Context, CursorIcon, Plugin};
|
||||
use crate::{Context, CursorIcon, Plugin, Ui};
|
||||
|
||||
/// Plugin for tracking drag-and-drop payload.
|
||||
///
|
||||
@@ -32,12 +32,12 @@ impl Plugin for DragAndDrop {
|
||||
/// Interrupt drag-and-drop if the user presses the escape key.
|
||||
///
|
||||
/// This needs to happen at frame start so we can properly capture the escape key.
|
||||
fn on_begin_pass(&mut self, ctx: &Context) {
|
||||
fn on_begin_pass(&mut self, ui: &mut Ui) {
|
||||
let has_any_payload = self.payload.is_some();
|
||||
|
||||
if has_any_payload {
|
||||
let abort_dnd_due_to_escape_key =
|
||||
ctx.input_mut(|i| i.consume_key(crate::Modifiers::NONE, crate::Key::Escape));
|
||||
ui.input_mut(|i| i.consume_key(crate::Modifiers::NONE, crate::Key::Escape));
|
||||
|
||||
if abort_dnd_due_to_escape_key {
|
||||
self.payload = None;
|
||||
@@ -50,18 +50,18 @@ impl Plugin for DragAndDrop {
|
||||
/// This is a catch-all safety net in case user code doesn't capture the drag payload itself.
|
||||
/// This must happen at end-of-frame such that we don't shadow the mouse release event from user
|
||||
/// code.
|
||||
fn on_end_pass(&mut self, ctx: &Context) {
|
||||
fn on_end_pass(&mut self, ui: &mut Ui) {
|
||||
let has_any_payload = self.payload.is_some();
|
||||
|
||||
if has_any_payload {
|
||||
let abort_dnd_due_to_mouse_release = ctx.input_mut(|i| i.pointer.any_released());
|
||||
let abort_dnd_due_to_mouse_release = ui.input_mut(|i| i.pointer.any_released());
|
||||
|
||||
if abort_dnd_due_to_mouse_release {
|
||||
self.payload = None;
|
||||
} else {
|
||||
// We set the cursor icon only if its default, as the user code might have
|
||||
// explicitly set it already.
|
||||
ctx.output_mut(|o| {
|
||||
ui.output_mut(|o| {
|
||||
if o.cursor_icon == CursorIcon::Default {
|
||||
o.cursor_icon = CursorIcon::Grabbing;
|
||||
}
|
||||
|
||||
@@ -43,23 +43,6 @@
|
||||
//! In some GUI frameworks this would require defining multiple types and functions with callbacks or message handlers,
|
||||
//! but thanks to `egui` being immediate mode everything is one self-contained function!
|
||||
//!
|
||||
//! ### Getting a [`Ui`]
|
||||
//!
|
||||
//! Use one of [`Panel`], [`CentralPanel`], [`Window`] or [`Area`] to
|
||||
//! get access to an [`Ui`] where you can put widgets. For example:
|
||||
//!
|
||||
//! ```
|
||||
//! # egui::__run_test_ctx(|ctx| {
|
||||
//! egui::CentralPanel::default().show(&ctx, |ui| {
|
||||
//! ui.add(egui::Label::new("Hello World!"));
|
||||
//! ui.label("A shorter and more convenient way to add a label.");
|
||||
//! if ui.button("Click me").clicked() {
|
||||
//! // take some action here
|
||||
//! }
|
||||
//! });
|
||||
//! # });
|
||||
//! ```
|
||||
//!
|
||||
//! ### Quick start
|
||||
//!
|
||||
//! ```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{Context, FullOutput, RawInput};
|
||||
use crate::{Context, FullOutput, RawInput, Ui};
|
||||
use ahash::HashMap;
|
||||
use epaint::mutex::{Mutex, MutexGuard};
|
||||
use std::sync::Arc;
|
||||
@@ -23,13 +23,13 @@ pub trait Plugin: Send + Sync + std::any::Any + 'static {
|
||||
|
||||
/// Called at the start of each pass.
|
||||
///
|
||||
/// Can be used to show ui, e.g. a [`crate::Window`] or [`crate::SidePanel`].
|
||||
fn on_begin_pass(&mut self, ctx: &Context) {}
|
||||
/// Can be used to show ui, e.g. a [`crate::Window`] or [`crate::Panel`].
|
||||
fn on_begin_pass(&mut self, ui: &mut Ui) {}
|
||||
|
||||
/// Called at the end of each pass.
|
||||
///
|
||||
/// Can be used to show ui, e.g. a [`crate::Window`].
|
||||
fn on_end_pass(&mut self, ctx: &Context) {}
|
||||
fn on_end_pass(&mut self, ui: &mut Ui) {}
|
||||
|
||||
/// Called just before the input is processed.
|
||||
///
|
||||
@@ -147,17 +147,17 @@ impl PluginsOrdered {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_begin_pass(&self, ctx: &Context) {
|
||||
pub fn on_begin_pass(&self, ui: &mut Ui) {
|
||||
profiling::scope!("plugins", "on_begin_pass");
|
||||
self.for_each_dyn(|p| {
|
||||
p.on_begin_pass(ctx);
|
||||
p.on_begin_pass(ui);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn on_end_pass(&self, ctx: &Context) {
|
||||
pub fn on_end_pass(&self, ui: &mut Ui) {
|
||||
profiling::scope!("plugins", "on_end_pass");
|
||||
self.for_each_dyn(|p| {
|
||||
p.on_end_pass(ctx);
|
||||
p.on_end_pass(ui);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ impl Plugins {
|
||||
}
|
||||
|
||||
/// Generic event callback.
|
||||
pub type ContextCallback = Arc<dyn Fn(&Context) + Send + Sync>;
|
||||
pub type ContextCallback = Arc<dyn Fn(&mut Ui) + Send + Sync>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct CallbackPlugin {
|
||||
@@ -227,21 +227,21 @@ impl Plugin for CallbackPlugin {
|
||||
"CallbackPlugins"
|
||||
}
|
||||
|
||||
fn on_begin_pass(&mut self, ctx: &Context) {
|
||||
fn on_begin_pass(&mut self, ui: &mut Ui) {
|
||||
profiling::function_scope!();
|
||||
|
||||
for (_debug_name, cb) in &self.on_begin_plugins {
|
||||
profiling::scope!("on_begin_pass", *_debug_name);
|
||||
(cb)(ctx);
|
||||
(cb)(ui);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_end_pass(&mut self, ctx: &Context) {
|
||||
fn on_end_pass(&mut self, ui: &mut Ui) {
|
||||
profiling::function_scope!();
|
||||
|
||||
for (_debug_name, cb) in &self.on_end_plugins {
|
||||
profiling::scope!("on_end_pass", *_debug_name);
|
||||
(cb)(ctx);
|
||||
(cb)(ui);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,8 +128,8 @@ impl Plugin for LabelSelectionState {
|
||||
"LabelSelectionState"
|
||||
}
|
||||
|
||||
fn on_begin_pass(&mut self, ctx: &Context) {
|
||||
if ctx.input(|i| i.pointer.any_pressed() && !i.modifiers.shift) {
|
||||
fn on_begin_pass(&mut self, ui: &mut Ui) {
|
||||
if ui.input(|i| i.pointer.any_pressed() && !i.modifiers.shift) {
|
||||
// Maybe a new selection is about to begin, but the old one is over:
|
||||
// state.selection = None; // TODO(emilk): this makes sense, but doesn't work as expected.
|
||||
}
|
||||
@@ -145,9 +145,9 @@ impl Plugin for LabelSelectionState {
|
||||
self.painted_selections.clear();
|
||||
}
|
||||
|
||||
fn on_end_pass(&mut self, ctx: &Context) {
|
||||
fn on_end_pass(&mut self, ui: &mut Ui) {
|
||||
if self.is_dragging {
|
||||
ctx.set_cursor_icon(CursorIcon::Text);
|
||||
ui.set_cursor_icon(CursorIcon::Text);
|
||||
}
|
||||
|
||||
if !self.has_reached_primary || !self.has_reached_secondary {
|
||||
@@ -159,7 +159,7 @@ impl Plugin for LabelSelectionState {
|
||||
if let Some(selection) = prev_selection {
|
||||
// This was the first frame of glitch, so hide the
|
||||
// glitching by removing all painted selections:
|
||||
ctx.graphics_mut(|layers| {
|
||||
ui.graphics_mut(|layers| {
|
||||
if let Some(list) = layers.get_mut(selection.layer_id) {
|
||||
for (shape_idx, row_selections) in self.painted_selections.drain(..) {
|
||||
list.mutate_shape(shape_idx, |shape| {
|
||||
@@ -190,21 +190,21 @@ impl Plugin for LabelSelectionState {
|
||||
}
|
||||
}
|
||||
|
||||
let pressed_escape = ctx.input(|i| i.key_pressed(crate::Key::Escape));
|
||||
let clicked_something_else = ctx.input(|i| i.pointer.any_pressed()) && !self.any_hovered;
|
||||
let pressed_escape = ui.input(|i| i.key_pressed(crate::Key::Escape));
|
||||
let clicked_something_else = ui.input(|i| i.pointer.any_pressed()) && !self.any_hovered;
|
||||
let delected_everything = pressed_escape || clicked_something_else;
|
||||
|
||||
if delected_everything {
|
||||
self.selection = None;
|
||||
}
|
||||
|
||||
if ctx.input(|i| i.pointer.any_released()) {
|
||||
if ui.input(|i| i.pointer.any_released()) {
|
||||
self.is_dragging = false;
|
||||
}
|
||||
|
||||
let text_to_copy = std::mem::take(&mut self.text_to_copy);
|
||||
if !text_to_copy.is_empty() {
|
||||
ctx.copy_text(text_to_copy);
|
||||
ui.copy_text(text_to_copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ use std::sync::Arc;
|
||||
|
||||
use epaint::{Pos2, Vec2};
|
||||
|
||||
use crate::{Context, Id};
|
||||
use crate::{Context, Id, Ui};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -263,7 +263,7 @@ impl ViewportIdPair {
|
||||
}
|
||||
|
||||
/// The user-code that shows the ui in the viewport, used for deferred viewports.
|
||||
pub type DeferredViewportUiCallback = dyn Fn(&Context) + Sync + Send;
|
||||
pub type DeferredViewportUiCallback = dyn Fn(&mut Ui) + Sync + Send;
|
||||
|
||||
/// Render the given viewport, calling the given ui callback.
|
||||
pub type ImmediateViewportRendererCallback = dyn for<'a> Fn(&Context, ImmediateViewport<'a>);
|
||||
@@ -1251,5 +1251,5 @@ pub struct ImmediateViewport<'a> {
|
||||
pub builder: ViewportBuilder,
|
||||
|
||||
/// The user-code that shows the GUI.
|
||||
pub viewport_ui_cb: Box<dyn FnMut(&Context) + 'a>,
|
||||
pub viewport_ui_cb: Box<dyn FnMut(&mut Ui) + 'a>,
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ use accesskit_consumer::{FilterResult, Node, Tree, TreeChangeHandler};
|
||||
|
||||
use eframe::epaint::text::TextWrapMode;
|
||||
use egui::{
|
||||
Button, Color32, Context, Event, Frame, FullOutput, Id, Key, KeyboardShortcut, Label,
|
||||
Modifiers, Panel, RawInput, RichText, ScrollArea, Ui, collapsing_header::CollapsingState,
|
||||
Button, Color32, Event, Frame, FullOutput, Id, Key, KeyboardShortcut, Label, Modifiers, Panel,
|
||||
RawInput, RichText, ScrollArea, Ui, collapsing_header::CollapsingState,
|
||||
};
|
||||
|
||||
/// This [`egui::Plugin`] adds an inspector Panel.
|
||||
/// This [`egui::Plugin`] adds an inspector panel.
|
||||
///
|
||||
/// It can be opened with the `(Cmd/Ctrl)+Alt+I`. It shows the current AccessKit tree and details
|
||||
/// for the selected node.
|
||||
@@ -71,8 +71,8 @@ impl egui::Plugin for AccessibilityInspectorPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_begin_pass(&mut self, ctx: &Context) {
|
||||
if ctx.input_mut(|i| {
|
||||
fn on_begin_pass(&mut self, ui: &mut Ui) {
|
||||
if ui.input_mut(|i| {
|
||||
i.consume_shortcut(&KeyboardShortcut::new(
|
||||
Modifiers::COMMAND | Modifiers::ALT,
|
||||
Key::I,
|
||||
@@ -85,9 +85,9 @@ impl egui::Plugin for AccessibilityInspectorPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.enable_accesskit();
|
||||
ui.enable_accesskit();
|
||||
|
||||
Panel::right(Self::id()).show(ctx, |ui| {
|
||||
Panel::right(Self::id()).show_inside(ui, |ui| {
|
||||
ui.heading("🔎 AccessKit Inspector");
|
||||
if let Some(selected_node) = self.selected_node {
|
||||
Panel::bottom(Self::id().with("details_panel"))
|
||||
|
||||
@@ -271,7 +271,7 @@ impl eframe::App for WrapApp {
|
||||
color.to_normalized_gamma_f32()
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
if let Some(anchor) = frame
|
||||
.info()
|
||||
@@ -285,36 +285,36 @@ impl eframe::App for WrapApp {
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if ctx.input_mut(|i| i.consume_key(egui::Modifiers::NONE, egui::Key::F11)) {
|
||||
let fullscreen = ctx.input(|i| i.viewport().fullscreen.unwrap_or(false));
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(!fullscreen));
|
||||
if ui.input_mut(|i| i.consume_key(egui::Modifiers::NONE, egui::Key::F11)) {
|
||||
let fullscreen = ui.input(|i| i.viewport().fullscreen.unwrap_or(false));
|
||||
ui.send_viewport_cmd(egui::ViewportCommand::Fullscreen(!fullscreen));
|
||||
}
|
||||
|
||||
let mut cmd = Command::Nothing;
|
||||
egui::Panel::top("wrap_app_top_bar")
|
||||
.frame(egui::Frame::new().inner_margin(4))
|
||||
.show(ctx, |ui| {
|
||||
.show_inside(ui, |ui| {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
ui.visuals_mut().button_frame = false;
|
||||
self.bar_contents(ui, frame, &mut cmd);
|
||||
});
|
||||
});
|
||||
|
||||
self.state.backend_panel.update(ctx, frame);
|
||||
self.state.backend_panel.update(ui.ctx(), frame);
|
||||
|
||||
egui::CentralPanel::no_frame().show(ctx, |ui| {
|
||||
if !is_mobile(ctx) {
|
||||
egui::CentralPanel::no_frame().show_inside(ui, |ui| {
|
||||
if !is_mobile(ui.ctx()) {
|
||||
cmd = self.backend_panel(ui, frame);
|
||||
}
|
||||
|
||||
self.show_selected_app(ui, frame);
|
||||
});
|
||||
|
||||
self.state.backend_panel.end_of_frame(ctx);
|
||||
self.state.backend_panel.end_of_frame(ui.ctx());
|
||||
|
||||
self.ui_file_drag_and_drop(ctx);
|
||||
self.ui_file_drag_and_drop(ui.ctx());
|
||||
|
||||
self.run_cmd(ctx, cmd);
|
||||
self.run_cmd(ui.ctx(), cmd);
|
||||
}
|
||||
|
||||
#[cfg(feature = "glow")]
|
||||
|
||||
@@ -66,10 +66,10 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
|
||||
{
|
||||
let ctx = egui::Context::default();
|
||||
let _ = ctx.run(RawInput::default(), |ctx| {
|
||||
let _ = ctx.run_ui(RawInput::default(), |ui| {
|
||||
c.bench_function("label &str", |b| {
|
||||
b.iter_batched_ref(
|
||||
|| create_benchmark_ui(ctx),
|
||||
|| create_benchmark_ui(ui),
|
||||
|ui| {
|
||||
ui.label("the quick brown fox jumps over the lazy dog");
|
||||
},
|
||||
@@ -78,7 +78,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
});
|
||||
c.bench_function("label format!", |b| {
|
||||
b.iter_batched_ref(
|
||||
|| create_benchmark_ui(ctx),
|
||||
|| create_benchmark_ui(ui),
|
||||
|ui| {
|
||||
ui.label("the quick brown fox jumps over the lazy dog".to_owned());
|
||||
},
|
||||
@@ -90,7 +90,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
|
||||
{
|
||||
let ctx = egui::Context::default();
|
||||
let _ = ctx.run(RawInput::default(), |ctx| {
|
||||
let _ = ctx.run_ui(RawInput::default(), |ui| {
|
||||
let mut group = c.benchmark_group("button");
|
||||
|
||||
// To ensure we have a valid image, let's use the font texture. The size
|
||||
@@ -99,7 +99,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
|
||||
group.bench_function("1_button_text", |b| {
|
||||
b.iter_batched_ref(
|
||||
|| create_benchmark_ui(ctx),
|
||||
|| create_benchmark_ui(ui),
|
||||
|ui| {
|
||||
ui.add(Button::new("Hello World"));
|
||||
},
|
||||
@@ -108,7 +108,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
});
|
||||
group.bench_function("2_button_text_image", |b| {
|
||||
b.iter_batched_ref(
|
||||
|| create_benchmark_ui(ctx),
|
||||
|| create_benchmark_ui(ui),
|
||||
|ui| {
|
||||
ui.add(Button::image_and_text(image, "Hello World"));
|
||||
},
|
||||
@@ -117,7 +117,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
});
|
||||
group.bench_function("3_button_text_image_right_text", |b| {
|
||||
b.iter_batched_ref(
|
||||
|| create_benchmark_ui(ctx),
|
||||
|| create_benchmark_ui(ui),
|
||||
|ui| {
|
||||
ui.add(Button::image_and_text(image, "Hello World").right_text("⏵"));
|
||||
},
|
||||
@@ -126,7 +126,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
});
|
||||
group.bench_function("4_button_italic", |b| {
|
||||
b.iter_batched_ref(
|
||||
|| create_benchmark_ui(ctx),
|
||||
|| create_benchmark_ui(ui),
|
||||
|ui| {
|
||||
ui.add(Button::new(RichText::new("Hello World").italics()));
|
||||
},
|
||||
|
||||
@@ -372,7 +372,7 @@ fn file_menu_button(ui: &mut Ui) {
|
||||
mod tests {
|
||||
use crate::{Demo as _, demo::demo_app_windows::DemoGroups};
|
||||
|
||||
use egui_kittest::kittest::{NodeT as _, Queryable as _};
|
||||
use egui_kittest::kittest::Queryable as _;
|
||||
use egui_kittest::{Harness, OsThreshold, SnapshotOptions, SnapshotResults};
|
||||
|
||||
#[test]
|
||||
@@ -394,12 +394,15 @@ mod tests {
|
||||
|
||||
let name = remove_leading_emoji(demo.name());
|
||||
|
||||
let mut harness = Harness::new(|ctx| {
|
||||
egui_extras::install_image_loaders(ctx);
|
||||
demo.show(ctx, &mut true);
|
||||
let mut harness = Harness::new_ui(|ui| {
|
||||
egui_extras::install_image_loaders(ui);
|
||||
demo.show(ui, &mut true);
|
||||
});
|
||||
|
||||
let window = harness.queryable_node().children().next().unwrap();
|
||||
let window = harness
|
||||
.get_all_by_role(egui::accesskit::Role::Window)
|
||||
.next()
|
||||
.unwrap();
|
||||
// TODO(lucasmerlin): Windows should probably have a label?
|
||||
//let window = harness.get_by_label(name);
|
||||
|
||||
|
||||
@@ -176,9 +176,9 @@ mod tests {
|
||||
..Modals::default()
|
||||
};
|
||||
|
||||
let mut harness = Harness::new_state(
|
||||
|ctx, modals| {
|
||||
modals.show(ctx, &mut true);
|
||||
let mut harness = Harness::new_ui_state(
|
||||
|ui, modals| {
|
||||
modals.show(ui, &mut true);
|
||||
},
|
||||
initial_state,
|
||||
);
|
||||
@@ -204,9 +204,9 @@ mod tests {
|
||||
..Modals::default()
|
||||
};
|
||||
|
||||
let mut harness = Harness::new_state(
|
||||
|ctx, modals| {
|
||||
modals.show(ctx, &mut true);
|
||||
let mut harness = Harness::new_ui_state(
|
||||
|ui, modals| {
|
||||
modals.show(ui, &mut true);
|
||||
},
|
||||
initial_state,
|
||||
);
|
||||
@@ -228,9 +228,9 @@ mod tests {
|
||||
..Modals::default()
|
||||
};
|
||||
|
||||
let mut harness = Harness::new_state(
|
||||
|ctx, modals| {
|
||||
modals.show(ctx, &mut true);
|
||||
let mut harness = Harness::new_ui_state(
|
||||
|ui, modals| {
|
||||
modals.show(ui, &mut true);
|
||||
},
|
||||
initial_state,
|
||||
);
|
||||
@@ -258,9 +258,9 @@ mod tests {
|
||||
..Modals::default()
|
||||
};
|
||||
|
||||
let mut harness = Harness::new_state(
|
||||
|ctx, modals| {
|
||||
modals.show(ctx, &mut true);
|
||||
let mut harness = Harness::new_ui_state(
|
||||
|ui, modals| {
|
||||
modals.show(ui, &mut true);
|
||||
},
|
||||
initial_state,
|
||||
);
|
||||
|
||||
@@ -120,9 +120,9 @@ mod tests {
|
||||
#[test]
|
||||
pub fn should_type() {
|
||||
let text = "Hello, world!".to_owned();
|
||||
let mut harness = Harness::new_state(
|
||||
move |ctx, text| {
|
||||
CentralPanel::default().show(ctx, |ui| {
|
||||
let mut harness = Harness::new_ui_state(
|
||||
move |ui, text| {
|
||||
CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.text_edit_singleline(text);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -215,10 +215,11 @@ impl winit::application::ApplicationHandler<UserEvent> for GlowApp {
|
||||
let mut redraw = || {
|
||||
let mut quit = false;
|
||||
|
||||
self.egui_glow.as_mut().unwrap().run(
|
||||
self.gl_window.as_mut().unwrap().window(),
|
||||
|egui_ctx| {
|
||||
egui::Panel::left("my_side_panel").show(egui_ctx, |ui| {
|
||||
self.egui_glow
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.run(self.gl_window.as_mut().unwrap().window(), |ui| {
|
||||
egui::Panel::left("my_side_panel").show_inside(ui, |ui| {
|
||||
ui.heading("Hello World!");
|
||||
if ui.button("Quit").clicked() {
|
||||
quit = true;
|
||||
@@ -226,8 +227,7 @@ impl winit::application::ApplicationHandler<UserEvent> for GlowApp {
|
||||
|
||||
ui.color_edit_button_rgb(self.clear_color.as_mut().try_into().unwrap());
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
if quit {
|
||||
event_loop.exit();
|
||||
|
||||
@@ -65,7 +65,7 @@ impl EguiGlow {
|
||||
}
|
||||
|
||||
/// Call [`Self::paint`] later to paint.
|
||||
pub fn run(&mut self, window: &winit::window::Window, run_ui: impl FnMut(&egui::Context)) {
|
||||
pub fn run(&mut self, window: &winit::window::Window, run_ui: impl FnMut(&mut egui::Ui)) {
|
||||
let raw_input = self.egui_winit.take_egui_input(window);
|
||||
|
||||
let egui::FullOutput {
|
||||
@@ -74,7 +74,7 @@ impl EguiGlow {
|
||||
shapes,
|
||||
pixels_per_point,
|
||||
viewport_output,
|
||||
} = self.egui_ctx.run(raw_input, run_ui);
|
||||
} = self.egui_ctx.run_ui(raw_input, run_ui);
|
||||
|
||||
if viewport_output.len() > 1 {
|
||||
log::warn!("Multiple viewports not yet supported by EguiGlow");
|
||||
|
||||
@@ -24,58 +24,60 @@ pub(crate) enum AppKind<'a, State> {
|
||||
impl<State> AppKind<'_, State> {
|
||||
pub fn run(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &mut egui::Ui,
|
||||
state: &mut State,
|
||||
sizing_pass: bool,
|
||||
) -> Option<egui::Response> {
|
||||
match self {
|
||||
AppKind::Context(f) => {
|
||||
debug_assert!(!sizing_pass, "Context closures cannot do a sizing pass");
|
||||
f(ctx);
|
||||
f(ui);
|
||||
None
|
||||
}
|
||||
AppKind::ContextState(f) => {
|
||||
debug_assert!(!sizing_pass, "Context closures cannot do a sizing pass");
|
||||
f(ctx, state);
|
||||
f(ui, state);
|
||||
None
|
||||
}
|
||||
#[cfg(feature = "eframe")]
|
||||
AppKind::Eframe((get_app, frame)) => {
|
||||
let app = get_app(state);
|
||||
app.update(ctx, frame);
|
||||
|
||||
app.logic(ui, frame);
|
||||
|
||||
#[expect(deprecated)]
|
||||
app.update(ui, frame);
|
||||
|
||||
app.ui(ui, frame);
|
||||
|
||||
None
|
||||
}
|
||||
kind_ui => Some(kind_ui.run_ui(ctx, state, sizing_pass)),
|
||||
kind_ui => Some(kind_ui.run_ui(ui, state, sizing_pass)),
|
||||
}
|
||||
}
|
||||
|
||||
fn run_ui(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
ui: &mut egui::Ui,
|
||||
state: &mut State,
|
||||
sizing_pass: bool,
|
||||
) -> egui::Response {
|
||||
egui::CentralPanel::default()
|
||||
.frame(Frame::NONE)
|
||||
.show(ctx, |ui| {
|
||||
let mut builder = egui::UiBuilder::new();
|
||||
if sizing_pass {
|
||||
builder.sizing_pass = true;
|
||||
}
|
||||
ui.scope_builder(builder, |ui| {
|
||||
Frame::central_panel(ui.style())
|
||||
.outer_margin(8.0)
|
||||
.inner_margin(0.0)
|
||||
.show(ui, |ui| match self {
|
||||
AppKind::Ui(f) => f(ui),
|
||||
AppKind::UiState(f) => f(ui, state),
|
||||
_ => unreachable!(
|
||||
"run_ui should only be called with AppKind::Ui or AppKind UiState"
|
||||
),
|
||||
});
|
||||
})
|
||||
.response
|
||||
})
|
||||
.inner
|
||||
let mut builder = egui::UiBuilder::new();
|
||||
if sizing_pass {
|
||||
builder.sizing_pass = true;
|
||||
}
|
||||
ui.scope_builder(builder, |ui| {
|
||||
Frame::central_panel(ui.style())
|
||||
.outer_margin(8.0)
|
||||
.inner_margin(0.0)
|
||||
.show(ui, |ui| match self {
|
||||
AppKind::Ui(f) => f(ui),
|
||||
AppKind::UiState(f) => f(ui, state),
|
||||
_ => unreachable!(
|
||||
"run_ui should only be called with AppKind::Ui or AppKind UiState"
|
||||
),
|
||||
});
|
||||
})
|
||||
.response
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +167,7 @@ impl<State> HarnessBuilder<State> {
|
||||
/// assert_eq!(*harness.state(), true);
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[deprecated = "use `build_ui_state` instead"]
|
||||
pub fn build_state<'a>(
|
||||
self,
|
||||
app: impl FnMut(&egui::Context, &mut State) + 'a,
|
||||
@@ -251,6 +252,7 @@ impl HarnessBuilder {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[track_caller]
|
||||
#[deprecated = "use `build_ui` instead"]
|
||||
pub fn build<'a>(self, app: impl FnMut(&egui::Context) + 'a) -> Harness<'a> {
|
||||
Harness::from_builder(self, AppKind::Context(Box::new(app)), (), None)
|
||||
}
|
||||
|
||||
@@ -137,8 +137,8 @@ impl<'a, State> Harness<'a, State> {
|
||||
|
||||
// We need to run egui for a single frame so that the AccessKit state can be initialized
|
||||
// and users can immediately start querying for widgets.
|
||||
let mut output = ctx.run(input.clone(), |ctx| {
|
||||
response = app.run(ctx, &mut state, false);
|
||||
let mut output = ctx.run_ui(input.clone(), |ui| {
|
||||
response = app.run(ui, &mut state, false);
|
||||
});
|
||||
|
||||
renderer.handle_delta(&output.textures_delta);
|
||||
@@ -204,7 +204,9 @@ impl<'a, State> Harness<'a, State> {
|
||||
/// assert_eq!(*harness.state(), true);
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[deprecated = "use `new_ui_state` instead"]
|
||||
pub fn new_state(app: impl FnMut(&egui::Context, &mut State) + 'a, state: State) -> Self {
|
||||
#[expect(deprecated)]
|
||||
Self::builder().build_state(app, state)
|
||||
}
|
||||
|
||||
@@ -287,8 +289,8 @@ impl<'a, State> Harness<'a, State> {
|
||||
fn _step(&mut self, sizing_pass: bool) {
|
||||
self.input.predicted_dt = self.step_dt;
|
||||
|
||||
let mut output = self.ctx.run(self.input.take(), |ctx| {
|
||||
self.response = self.app.run(ctx, &mut self.state, sizing_pass);
|
||||
let mut output = self.ctx.run_ui(self.input.take(), |ui| {
|
||||
self.response = self.app.run(ui, &mut self.state, sizing_pass);
|
||||
});
|
||||
self.kittest.update(
|
||||
output
|
||||
@@ -735,7 +737,9 @@ impl<'a> Harness<'a> {
|
||||
/// });
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[deprecated = "use `new_ui` instead"]
|
||||
pub fn new(app: impl FnMut(&egui::Context) + 'a) -> Self {
|
||||
#[expect(deprecated)]
|
||||
Self::builder().build(app)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Tests the accesskit accessibility output of egui.
|
||||
|
||||
use egui::{
|
||||
CentralPanel, Context, RawInput, Window,
|
||||
CentralPanel, Context, RawInput, Ui, Window,
|
||||
accesskit::{NodeId, Role, TreeUpdate},
|
||||
};
|
||||
|
||||
@@ -12,8 +12,8 @@ use egui::{
|
||||
/// are put there because of the widgets rendered.
|
||||
#[test]
|
||||
fn empty_ui_should_return_tree_with_only_root_window() {
|
||||
let output = accesskit_output_single_egui_frame(|ctx| {
|
||||
CentralPanel::default().show(ctx, |_| {});
|
||||
let output = accesskit_output_single_egui_frame(|_ui| {
|
||||
// Nothing here beyond the default empty UI
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -42,8 +42,8 @@ fn empty_ui_should_return_tree_with_only_root_window() {
|
||||
fn button_node() {
|
||||
let button_text = "This is a test button!";
|
||||
|
||||
let output = accesskit_output_single_egui_frame(|ctx| {
|
||||
CentralPanel::default().show(ctx, |ui| ui.button(button_text));
|
||||
let output = accesskit_output_single_egui_frame(|ui| {
|
||||
CentralPanel::default().show_inside(ui, |ui| ui.button(button_text));
|
||||
});
|
||||
|
||||
let (_, button) = output
|
||||
@@ -60,8 +60,8 @@ fn button_node() {
|
||||
fn disabled_button_node() {
|
||||
let button_text = "This is a test button!";
|
||||
|
||||
let output = accesskit_output_single_egui_frame(|ctx| {
|
||||
CentralPanel::default().show(ctx, |ui| {
|
||||
let output = accesskit_output_single_egui_frame(|ui| {
|
||||
CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.add_enabled(false, egui::Button::new(button_text))
|
||||
});
|
||||
});
|
||||
@@ -81,8 +81,8 @@ fn toggle_button_node() {
|
||||
let button_text = "A toggle button";
|
||||
|
||||
let mut selected = false;
|
||||
let output = accesskit_output_single_egui_frame(|ctx| {
|
||||
CentralPanel::default().show(ctx, |ui| ui.toggle_value(&mut selected, button_text));
|
||||
let output = accesskit_output_single_egui_frame(|ui| {
|
||||
CentralPanel::default().show_inside(ui, |ui| ui.toggle_value(&mut selected, button_text));
|
||||
});
|
||||
|
||||
let (_, toggle) = output
|
||||
@@ -97,8 +97,8 @@ fn toggle_button_node() {
|
||||
|
||||
#[test]
|
||||
fn multiple_disabled_widgets() {
|
||||
let output = accesskit_output_single_egui_frame(|ctx| {
|
||||
CentralPanel::default().show(ctx, |ui| {
|
||||
let output = accesskit_output_single_egui_frame(|ui| {
|
||||
CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.add_enabled_ui(false, |ui| {
|
||||
let _ = ui.button("Button 1");
|
||||
let _ = ui.button("Button 2");
|
||||
@@ -120,12 +120,12 @@ fn multiple_disabled_widgets() {
|
||||
|
||||
#[test]
|
||||
fn window_children() {
|
||||
let output = accesskit_output_single_egui_frame(|ctx| {
|
||||
let output = accesskit_output_single_egui_frame(|ui| {
|
||||
let mut open = true;
|
||||
Window::new("test window")
|
||||
.open(&mut open)
|
||||
.resizable(false)
|
||||
.show(ctx, |ui| {
|
||||
.show(ui.ctx(), |ui| {
|
||||
let _ = ui.button("A button");
|
||||
});
|
||||
});
|
||||
@@ -138,13 +138,13 @@ fn window_children() {
|
||||
assert_button_exists(&output, "Hide", window_id);
|
||||
}
|
||||
|
||||
fn accesskit_output_single_egui_frame(run_ui: impl FnMut(&Context)) -> TreeUpdate {
|
||||
fn accesskit_output_single_egui_frame(run_ui: impl FnMut(&mut Ui)) -> TreeUpdate {
|
||||
let ctx = Context::default();
|
||||
// Disable animations, so we do not need to wait for animations to end to see the result.
|
||||
ctx.global_style_mut(|style| style.animation_time = 0.0);
|
||||
ctx.enable_accesskit();
|
||||
|
||||
let output = ctx.run(RawInput::default(), run_ui);
|
||||
let output = ctx.run_ui(RawInput::default(), run_ui);
|
||||
|
||||
output
|
||||
.platform_output
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ");
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.ctx(), "egui with custom frame", |ui| {
|
||||
ui.label("This is just the contents of the window.");
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("egui theme:");
|
||||
|
||||
@@ -44,8 +44,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 External Eventloop Application");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
@@ -82,7 +82,7 @@ impl eframe::App for MyApp {
|
||||
ui.label("Blinky!");
|
||||
});
|
||||
|
||||
ctx.request_repaint_after_secs((0.5 - (now % 0.5)) as f32);
|
||||
ui.request_repaint_after_secs((0.5 - (now % 0.5)) as f32);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,8 +76,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 External Eventloop Application");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
@@ -86,7 +86,7 @@ impl eframe::App for MyApp {
|
||||
}
|
||||
if ui.button("Increment Later").clicked() {
|
||||
let value = self.value.clone();
|
||||
let ctx = ctx.clone();
|
||||
let ctx = ui.ctx().clone();
|
||||
tokio::task::spawn_local(async move {
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
value.set(value.get() + 1);
|
||||
@@ -123,7 +123,7 @@ impl eframe::App for MyApp {
|
||||
ui.label("Blinky!");
|
||||
});
|
||||
|
||||
ctx.request_repaint_after_secs((0.5 - (now % 0.5)) as f32);
|
||||
ui.request_repaint_after_secs((0.5 - (now % 0.5)) as f32);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,8 +25,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("Drag-and-drop files onto the window!");
|
||||
|
||||
if ui.button("Open file…").clicked()
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -36,16 +36,16 @@ 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::Panel::top("status_bar_space").show(ctx, |ui| {
|
||||
egui::Panel::top("status_bar_space").show_inside(ui, |ui| {
|
||||
ui.set_height(32.0);
|
||||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
self.demo.ui(ui);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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: ");
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -15,8 +15,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: ");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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.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");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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(
|
||||
@@ -61,7 +61,7 @@ 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")
|
||||
@@ -87,7 +87,7 @@ 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(
|
||||
ui.ctx().show_viewport_deferred(
|
||||
egui::ViewportId::from_hash_of("deferred_viewport"),
|
||||
egui::ViewportBuilder::default()
|
||||
.with_title("Deferred Viewport")
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -54,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();
|
||||
|
||||
@@ -103,7 +103,7 @@ 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")
|
||||
@@ -130,7 +130,7 @@ 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(
|
||||
ui.ctx().show_viewport_deferred(
|
||||
egui::ViewportId::from_hash_of("deferred_viewport"),
|
||||
egui::ViewportBuilder::default()
|
||||
.with_title("Deferred Viewport")
|
||||
|
||||
@@ -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);
|
||||
ui.ctx().set_theme(egui::Theme::Light);
|
||||
}
|
||||
ctx.send_viewport_cmd(
|
||||
egui::ViewportCommand::Screenshot(Default::default()),
|
||||
);
|
||||
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()));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -101,7 +97,7 @@ impl eframe::App for MyApp {
|
||||
}
|
||||
});
|
||||
|
||||
ctx.request_repaint();
|
||||
ui.request_repaint();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::{CreationContext, NativeOptions, egui};
|
||||
use egui::{Button, CentralPanel, Context, UserAttentionType};
|
||||
use egui::{Button, CentralPanel, UserAttentionType};
|
||||
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
@@ -55,12 +55,12 @@ impl Application {
|
||||
}
|
||||
|
||||
impl eframe::App for Application {
|
||||
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
|
||||
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;
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::RequestUserAttention(self.attention));
|
||||
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());
|
||||
@@ -71,12 +71,12 @@ impl eframe::App for Application {
|
||||
&& reset_at < SystemTime::now()
|
||||
{
|
||||
self.reset_at = None;
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::RequestUserAttention(
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
struct MyTestApp {}
|
||||
|
||||
impl eframe::App for MyTestApp {
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
|
||||
use glow::HasContext as _;
|
||||
let gl = frame.gl().unwrap();
|
||||
|
||||
@@ -37,7 +37,7 @@ impl eframe::App for MyTestApp {
|
||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
egui::Window::new("Floating Window").show(ctx, |ui| {
|
||||
egui::Window::new("Floating Window").show(ui.ctx(), |ui| {
|
||||
ui.label("The background should be purple.");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ fn main() -> eframe::Result {
|
||||
env_logger::init(); // Use `RUST_LOG=debug` to see logs.
|
||||
|
||||
let options = eframe::NativeOptions::default();
|
||||
eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
||||
eframe::run_ui_native("My egui App", options, move |ui, _frame| {
|
||||
// A bottom panel to force the tooltips to consider if the fit below or under the widget:
|
||||
egui::Panel::bottom("bottom").show(ctx, |ui| {
|
||||
egui::Panel::bottom("bottom").show_inside(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.label("Single tooltips:");
|
||||
@@ -33,10 +33,10 @@ fn main() -> eframe::Result {
|
||||
});
|
||||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Reset egui memory").clicked() {
|
||||
ctx.memory_mut(|mem| *mem = Default::default());
|
||||
ui.memory_mut(|mem| *mem = Default::default());
|
||||
}
|
||||
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::BOTTOM), |ui| {
|
||||
|
||||
@@ -31,10 +31,10 @@ struct MyApp {
|
||||
}
|
||||
|
||||
impl eframe::App for MyApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
ctx.all_styles_mut(|style| style.interaction.tooltip_delay = 0.0);
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
ui.all_styles_mut(|style| style.interaction.tooltip_delay = 0.0);
|
||||
|
||||
egui::Panel::left("side_panel_left").show(ctx, |ui| {
|
||||
egui::Panel::left("side_panel_left").show_inside(ui, |ui| {
|
||||
ui.heading("Information");
|
||||
ui.label(
|
||||
"This is a demo/test environment of the `UiStack` feature. The tables display \
|
||||
@@ -49,7 +49,7 @@ impl eframe::App for MyApp {
|
||||
ui.checkbox(&mut self.show_memory, "📝 Memory");
|
||||
ui.add_space(10.0);
|
||||
if ui.button("Reset egui memory").clicked() {
|
||||
ctx.memory_mut(|mem| *mem = Default::default());
|
||||
ui.memory_mut(|mem| *mem = Default::default());
|
||||
}
|
||||
ui.add_space(20.0);
|
||||
|
||||
@@ -82,7 +82,7 @@ impl eframe::App for MyApp {
|
||||
});
|
||||
});
|
||||
|
||||
egui::Panel::right("side_panel_right").show(ctx, |ui| {
|
||||
egui::Panel::right("side_panel_right").show_inside(ui, |ui| {
|
||||
egui::ScrollArea::both().auto_shrink(false).show(ui, |ui| {
|
||||
stack_ui(ui);
|
||||
|
||||
@@ -92,7 +92,7 @@ impl eframe::App for MyApp {
|
||||
});
|
||||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
egui::CentralPanel::default().show_inside(ui, |ui| {
|
||||
egui::ScrollArea::both().auto_shrink(false).show(ui, |ui| {
|
||||
ui.label("stack here:");
|
||||
stack_ui(ui);
|
||||
@@ -172,7 +172,7 @@ impl eframe::App for MyApp {
|
||||
|
||||
egui::Panel::bottom("bottom_panel")
|
||||
.resizable(true)
|
||||
.show(ctx, |ui| {
|
||||
.show_inside(ui, |ui| {
|
||||
egui::ScrollArea::vertical()
|
||||
.auto_shrink(false)
|
||||
.show(ui, |ui| {
|
||||
@@ -186,30 +186,31 @@ impl eframe::App for MyApp {
|
||||
|
||||
egui::Window::new("Window")
|
||||
.pivot(egui::Align2::RIGHT_TOP)
|
||||
.show(ctx, |ui| {
|
||||
.show(ui.ctx(), |ui| {
|
||||
full_span_widget(ui, false);
|
||||
ui.add_space(20.0);
|
||||
stack_ui(ui);
|
||||
});
|
||||
|
||||
let ctx = ui.ctx().clone();
|
||||
egui::Window::new("🔧 Settings")
|
||||
.open(&mut self.show_settings)
|
||||
.vscroll(true)
|
||||
.show(ctx, |ui| {
|
||||
.show(&ctx, |ui| {
|
||||
ctx.settings_ui(ui);
|
||||
});
|
||||
|
||||
egui::Window::new("🔍 Inspection")
|
||||
.open(&mut self.show_inspection)
|
||||
.vscroll(true)
|
||||
.show(ctx, |ui| {
|
||||
.show(&ctx, |ui| {
|
||||
ctx.inspection_ui(ui);
|
||||
});
|
||||
|
||||
egui::Window::new("📝 Memory")
|
||||
.open(&mut self.show_memory)
|
||||
.resizable(false)
|
||||
.show(ctx, |ui| {
|
||||
.show(&ctx, |ui| {
|
||||
ctx.memory_ui(ui);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -153,18 +153,18 @@ impl Default for App {
|
||||
}
|
||||
|
||||
impl eframe::App for App {
|
||||
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("Root viewport");
|
||||
{
|
||||
let mut embed_viewports = ctx.embed_viewports();
|
||||
let mut embed_viewports = ui.embed_viewports();
|
||||
ui.checkbox(&mut embed_viewports, "Embed all viewports");
|
||||
if ui.button("Open all viewports").clicked() {
|
||||
for viewport in &self.top {
|
||||
viewport.write().set_visible_recursive(true);
|
||||
}
|
||||
}
|
||||
ctx.set_embed_viewports(embed_viewports);
|
||||
ui.set_embed_viewports(embed_viewports);
|
||||
}
|
||||
ui.checkbox(&mut self.close_button, "with close button");
|
||||
generic_ui(ui, &self.top, self.close_button);
|
||||
|
||||
Reference in New Issue
Block a user