1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 14:50:03 -04:00

egui_kittest: Allow passing state to the app closure (#5313)

The allows us to pass any state to the ui closure. While it is possible
to just store state in the closure itself, accessing that state after
the harness was created to e.g. read or modify it would require interior
mutability. With this change there are new `Harness::new_state`,
`Harness::run_state`, ... methods that allow passing state on each run.

This builds on top of #5301, which should be merged first

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
lucasmerlin
2024-11-06 14:43:41 +01:00
committed by GitHub
parent fc743d63b4
commit 3c7ad0ee12
6 changed files with 215 additions and 56 deletions

View File

@@ -1,11 +1,15 @@
use egui::Frame;
type AppKindContextState<'a, State> = Box<dyn FnMut(&egui::Context, &mut State) + 'a>;
type AppKindUiState<'a, State> = Box<dyn FnMut(&mut egui::Ui, &mut State) + 'a>;
type AppKindContext<'a> = Box<dyn FnMut(&egui::Context) + 'a>;
type AppKindUi<'a> = Box<dyn FnMut(&mut egui::Ui) + 'a>;
pub(crate) enum AppKind<'a> {
pub(crate) enum AppKind<'a, State> {
Context(AppKindContext<'a>),
Ui(AppKindUi<'a>),
ContextState(AppKindContextState<'a, State>),
UiState(AppKindUiState<'a, State>),
}
// TODO(lucasmerlin): These aren't working unfortunately :(
@@ -32,28 +36,34 @@ pub(crate) enum AppKind<'a> {
// }
// }
impl<'a> AppKind<'a> {
pub fn run(&mut self, ctx: &egui::Context) -> Option<egui::Response> {
impl<'a, State> AppKind<'a, State> {
pub fn run(
&mut self,
ctx: &egui::Context,
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);
None
}
AppKind::Ui(f) => Some(Self::run_ui(f, ctx, false)),
}
}
pub(crate) fn run_sizing_pass(&mut self, ctx: &egui::Context) -> Option<egui::Response> {
match self {
AppKind::Context(f) => {
f(ctx);
AppKind::ContextState(f) => {
debug_assert!(!sizing_pass, "Context closures cannot do a sizing pass");
f(ctx, state);
None
}
AppKind::Ui(f) => Some(Self::run_ui(f, ctx, true)),
kind_ui => Some(kind_ui.run_ui(ctx, state, sizing_pass)),
}
}
fn run_ui(f: &mut AppKindUi<'a>, ctx: &egui::Context, sizing_pass: bool) -> egui::Response {
fn run_ui(
&mut self,
ctx: &egui::Context,
state: &mut State,
sizing_pass: bool,
) -> egui::Response {
egui::CentralPanel::default()
.frame(Frame::none())
.show(ctx, |ui| {
@@ -65,7 +75,11 @@ impl<'a> AppKind<'a> {
Frame::central_panel(ui.style())
.outer_margin(8.0)
.inner_margin(0.0)
.show(ui, |ui| f(ui));
.show(ui, |ui| match self {
AppKind::Ui(f) => f(ui),
AppKind::UiState(f) => f(ui, state),
_ => unreachable!(),
});
})
.response
})