use std::cell::RefCell;
use par_term_config::Config;
use crate::SettingsUI;
thread_local! {
static DEFAULT: RefCell<Config> = RefCell::new(Config::default());
}
pub fn reset_button<T: PartialEq + Clone>(
ui: &mut egui::Ui,
settings: &mut SettingsUI,
changes_this_frame: &mut bool,
field: impl Fn(&mut Config) -> &mut T,
) {
let default = DEFAULT.with(|d| field(&mut d.borrow_mut()).clone());
let differs = *field(&mut settings.config) != default;
#[cfg(test)]
record(differs);
if differs
&& ui
.small_button("\u{21BA}")
.on_hover_text("Reset to default")
.clicked()
{
*field(&mut settings.config) = default;
settings.has_changes = true;
*changes_this_frame = true;
}
}
#[cfg(test)]
thread_local! {
static SHOWN: std::cell::RefCell<Vec<bool>> = const { std::cell::RefCell::new(Vec::new()) };
}
#[cfg(test)]
fn record(differs: bool) {
SHOWN.with(|s| s.borrow_mut().push(differs));
}
#[cfg(test)]
pub(crate) fn take_shown() -> Vec<bool> {
SHOWN.with(|s| std::mem::take(&mut *s.borrow_mut()))
}
#[cfg(test)]
mod tests {
use super::*;
fn frame(settings: &mut SettingsUI, changes: &mut bool) {
let ctx = egui::Context::default();
let mut output = ctx.run_ui(egui::RawInput::default(), |ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
reset_button(ui, settings, changes, |c| &mut c.window.window_opacity);
});
});
output.textures_delta.clear();
}
#[test]
fn reset_shows_only_when_the_value_differs_from_default() {
let mut settings = SettingsUI::new_for_tests(Config::default());
let mut changes = false;
take_shown();
frame(&mut settings, &mut changes);
assert_eq!(take_shown(), [false], "default value: no ↺");
settings.config.window.window_opacity = 0.42;
frame(&mut settings, &mut changes);
assert_eq!(take_shown(), [true], "changed value: ↺ shown");
}
#[test]
fn clicking_reset_restores_the_default_as_an_edit() {
let mut settings = SettingsUI::new_for_tests(Config::default());
settings.config.window.window_opacity = 0.42;
let mut changes = false;
let ctx = egui::Context::default();
fn run(
ctx: &egui::Context,
input: egui::RawInput,
settings: &mut SettingsUI,
changes: &mut bool,
) -> egui::Rect {
let mut rect = egui::Rect::NOTHING;
let mut output = ctx.run_ui(input, |ctx| {
egui::CentralPanel::default().show(ctx, |ui| {
reset_button(ui, settings, changes, |c| &mut c.window.window_opacity);
rect = ui.min_rect();
});
});
output.textures_delta.clear();
rect
}
let rect = run(&ctx, egui::RawInput::default(), &mut settings, &mut changes);
let at = rect.left_top() + egui::vec2(6.0, 6.0);
for event in [
egui::Event::PointerMoved(at),
egui::Event::PointerButton {
pos: at,
button: egui::PointerButton::Primary,
pressed: true,
modifiers: egui::Modifiers::NONE,
},
egui::Event::PointerButton {
pos: at,
button: egui::PointerButton::Primary,
pressed: false,
modifiers: egui::Modifiers::NONE,
},
] {
let input = egui::RawInput {
events: vec![event],
..Default::default()
};
run(&ctx, input, &mut settings, &mut changes);
}
assert_eq!(
settings.config.window.window_opacity,
Config::default().window.window_opacity
);
assert!(changes && settings.has_changes);
}
}