mirror of
https://github.com/emilk/egui.git
synced 2026-09-03 15:20:05 -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:
@@ -1,23 +1,26 @@
|
||||
use crate::app_kind::AppKind;
|
||||
use crate::Harness;
|
||||
use egui::{Pos2, Rect, Vec2};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Builder for [`Harness`].
|
||||
pub struct HarnessBuilder {
|
||||
pub struct HarnessBuilder<State = ()> {
|
||||
pub(crate) screen_rect: Rect,
|
||||
pub(crate) pixels_per_point: f32,
|
||||
pub(crate) state: PhantomData<State>,
|
||||
}
|
||||
|
||||
impl Default for HarnessBuilder {
|
||||
impl<State> Default for HarnessBuilder<State> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
screen_rect: Rect::from_min_size(Pos2::ZERO, Vec2::new(800.0, 600.0)),
|
||||
pixels_per_point: 1.0,
|
||||
state: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HarnessBuilder {
|
||||
impl<State> HarnessBuilder<State> {
|
||||
/// Set the size of the window.
|
||||
#[inline]
|
||||
pub fn with_size(mut self, size: impl Into<Vec2>) -> Self {
|
||||
@@ -34,6 +37,69 @@ impl HarnessBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given app closure and a state.
|
||||
///
|
||||
/// The app closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you don't need to create Windows / Panels, you can use [`HarnessBuilder::build_ui`] instead.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui::CentralPanel;
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
/// let checked = false;
|
||||
/// let mut harness = Harness::builder()
|
||||
/// .with_size(egui::Vec2::new(300.0, 200.0))
|
||||
/// .build_state(|ctx, checked| {
|
||||
/// CentralPanel::default().show(ctx, |ui| {
|
||||
/// ui.checkbox(checked, "Check me!");
|
||||
/// });
|
||||
/// }, checked);
|
||||
///
|
||||
/// harness.get_by_name("Check me!").click();
|
||||
/// harness.run();
|
||||
///
|
||||
/// assert_eq!(*harness.state(), true);
|
||||
/// ```
|
||||
pub fn build_state<'a>(
|
||||
self,
|
||||
app: impl FnMut(&egui::Context, &mut State) + 'a,
|
||||
state: State,
|
||||
) -> Harness<'a, State> {
|
||||
Harness::from_builder(&self, AppKind::ContextState(Box::new(app)), state)
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given ui closure and a state.
|
||||
///
|
||||
/// The ui closure will immediately be called once to create the initial ui.
|
||||
///
|
||||
/// If you need to create Windows / Panels, you can use [`HarnessBuilder::build`] instead.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
/// let mut checked = false;
|
||||
/// let mut harness = Harness::builder()
|
||||
/// .with_size(egui::Vec2::new(300.0, 200.0))
|
||||
/// .build_ui_state(|ui, checked| {
|
||||
/// ui.checkbox(checked, "Check me!");
|
||||
/// }, checked);
|
||||
///
|
||||
/// harness.get_by_name("Check me!").click();
|
||||
/// harness.run();
|
||||
///
|
||||
/// assert_eq!(*harness.state(), true);
|
||||
/// ```
|
||||
pub fn build_ui_state<'a>(
|
||||
self,
|
||||
app: impl FnMut(&mut egui::Ui, &mut State) + 'a,
|
||||
state: State,
|
||||
) -> Harness<'a, State> {
|
||||
Harness::from_builder(&self, AppKind::UiState(Box::new(app)), state)
|
||||
}
|
||||
}
|
||||
|
||||
impl HarnessBuilder {
|
||||
/// Create a new Harness with the given app closure.
|
||||
///
|
||||
/// The app closure will immediately be called once to create the initial ui.
|
||||
@@ -43,7 +109,7 @@ impl HarnessBuilder {
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui::CentralPanel;
|
||||
/// # use egui_kittest::Harness;
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
/// let mut harness = Harness::builder()
|
||||
/// .with_size(egui::Vec2::new(300.0, 200.0))
|
||||
/// .build(|ctx| {
|
||||
@@ -53,7 +119,7 @@ impl HarnessBuilder {
|
||||
/// });
|
||||
/// ```
|
||||
pub fn build<'a>(self, app: impl FnMut(&egui::Context) + 'a) -> Harness<'a> {
|
||||
Harness::from_builder(&self, AppKind::Context(Box::new(app)))
|
||||
Harness::from_builder(&self, AppKind::Context(Box::new(app)), ())
|
||||
}
|
||||
|
||||
/// Create a new Harness with the given ui closure.
|
||||
@@ -64,7 +130,7 @@ impl HarnessBuilder {
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui_kittest::Harness;
|
||||
/// # use egui_kittest::{Harness, kittest::Queryable};
|
||||
/// let mut harness = Harness::builder()
|
||||
/// .with_size(egui::Vec2::new(300.0, 200.0))
|
||||
/// .build_ui(|ui| {
|
||||
@@ -72,6 +138,6 @@ impl HarnessBuilder {
|
||||
/// });
|
||||
/// ```
|
||||
pub fn build_ui<'a>(self, app: impl FnMut(&mut egui::Ui) + 'a) -> Harness<'a> {
|
||||
Harness::from_builder(&self, AppKind::Ui(Box::new(app)))
|
||||
Harness::from_builder(&self, AppKind::Ui(Box::new(app)), ())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user