use super::*;
fn cwp_layout(
picker: crate::ColorWheelPicker,
vp_w: f64,
vp_h: f64,
) -> (App, f64, f64, impl Fn(f64) -> f64) {
let mut app = App::new(Box::new(picker));
app.layout(Size::new(vp_w, vp_h));
let flip = move |y_up: f64| vp_h - y_up;
(app, vp_w, vp_h, flip)
}
#[test]
fn test_color_wheel_picker_drag_hue_updates_color() {
use crate::text::Font;
use crate::ColorWheelPicker;
use std::cell::Cell;
use std::rc::Rc;
use std::sync::Arc;
let font = Arc::new(Font::from_slice(TEST_FONT).unwrap());
let start = Color::rgba(1.0, 0.0, 0.0, 1.0); let last = Rc::new(Cell::new(start));
let last_cb = Rc::clone(&last);
let picker = ColorWheelPicker::new(start, Arc::clone(&font)).on_change(move |c| {
if let Some(col) = c {
last_cb.set(col);
}
});
const VP_W: f64 = 240.0;
const VP_H: f64 = 420.0;
let (mut app, _, vp_h, flip) = cwp_layout(picker, VP_W, VP_H);
let picker_h = crate::widgets::color_wheel_picker::picker_height(false, true);
let cy_up = picker_h - 10.0 - 200.0 * 0.5; let cx = VP_W * 0.5; let _ = cx; let cx = crate::widgets::color_wheel_picker::picker_width() * 0.5;
let ring_r = 0.5
* 200.0
* (crate::widgets::color_wheel_picker::WHEEL_OUTER_RATIO
+ crate::widgets::color_wheel_picker::WHEEL_INNER_RATIO)
* 0.5;
let angle = 120.0_f64.to_radians();
let target_x = cx + ring_r * angle.cos();
let target_y_up = cy_up + ring_r * angle.sin();
let target_screen_y = flip(target_y_up);
let _ = vp_h;
app.on_mouse_down(
target_x,
target_screen_y,
MouseButton::Left,
Modifiers::default(),
);
app.on_mouse_move(target_x, target_screen_y);
app.on_mouse_up(
target_x,
target_screen_y,
MouseButton::Left,
Modifiers::default(),
);
let got = last.get();
assert_ne!(
(start.r, start.g, start.b),
(got.r, got.g, got.b),
"hue drag must shift RGB (started at red, got {:?})",
(got.r, got.g, got.b),
);
}
#[test]
fn test_color_wheel_picker_no_color_returns_none() {
use crate::text::Font;
use crate::ColorWheelPicker;
use std::cell::Cell;
use std::rc::Rc;
use std::sync::Arc;
let font = Arc::new(Font::from_slice(TEST_FONT).unwrap());
let start = Color::rgba(0.2, 0.7, 0.4, 1.0);
let last_was_none = Rc::new(Cell::new(false));
let last_was_none_cb = Rc::clone(&last_was_none);
let picker = ColorWheelPicker::new(start, Arc::clone(&font))
.with_allow_none(true)
.on_change(move |c| {
last_was_none_cb.set(c.is_none());
});
const VP_W: f64 = 240.0;
const VP_H: f64 = 500.0;
let (mut app, _, _, flip) = cwp_layout(picker, VP_W, VP_H);
let picker_h = crate::widgets::color_wheel_picker::picker_height(true, true);
let y_top = picker_h - 10.0 - 200.0 - 6.0 - 22.0 - 6.0 - 26.0 - 6.0 - 32.0 - 6.0;
let nocolor_y_centre = y_top - 11.0;
let click_x = 20.0; let screen_y = flip(nocolor_y_centre);
app.on_mouse_down(click_x, screen_y, MouseButton::Left, Modifiers::default());
app.on_mouse_up(click_x, screen_y, MouseButton::Left, Modifiers::default());
app.layout(Size::new(VP_W, VP_H));
assert!(
last_was_none.get(),
"ticking 'No Color' must cause on_change to deliver None",
);
}
#[test]
fn test_color_wheel_picker_cancel_restores_original() {
use crate::text::Font;
use crate::ColorWheelPicker;
use std::cell::Cell;
use std::rc::Rc;
use std::sync::Arc;
let font = Arc::new(Font::from_slice(TEST_FONT).unwrap());
let start = Color::rgba(1.0, 0.0, 0.0, 1.0); let last = Rc::new(Cell::new(start));
let cancel_fired = Rc::new(Cell::new(false));
let last_cb = Rc::clone(&last);
let cancel_cb = Rc::clone(&cancel_fired);
let picker = ColorWheelPicker::new(start, Arc::clone(&font))
.on_change(move |c| {
if let Some(col) = c {
last_cb.set(col);
}
})
.on_cancel(move || cancel_cb.set(true));
const VP_W: f64 = 240.0;
const VP_H: f64 = 420.0;
let (mut app, _, _, flip) = cwp_layout(picker, VP_W, VP_H);
let picker_h = crate::widgets::color_wheel_picker::picker_height(false, true);
let cy_up = picker_h - 10.0 - 100.0;
let cx = crate::widgets::color_wheel_picker::picker_width() * 0.5;
let ring_r = 0.5
* 200.0
* (crate::widgets::color_wheel_picker::WHEEL_OUTER_RATIO
+ crate::widgets::color_wheel_picker::WHEEL_INNER_RATIO)
* 0.5;
let angle = 200.0_f64.to_radians();
let drag_x = cx + ring_r * angle.cos();
let drag_y = cy_up + ring_r * angle.sin();
let drag_screen_y = flip(drag_y);
app.on_mouse_down(
drag_x,
drag_screen_y,
MouseButton::Left,
Modifiers::default(),
);
app.on_mouse_up(
drag_x,
drag_screen_y,
MouseButton::Left,
Modifiers::default(),
);
let after_drag = last.get();
assert_ne!(
(start.r, start.g, start.b),
(after_drag.r, after_drag.g, after_drag.b),
"sanity: drag must have shifted hue before we test the restore",
);
let cancel_cx = 10.0 + 97.0 * 0.5; let cancel_cy_up = 10.0 + 30.0 * 0.5; let cancel_screen_y = flip(cancel_cy_up);
app.on_mouse_move(cancel_cx, cancel_screen_y);
app.on_mouse_down(
cancel_cx,
cancel_screen_y,
MouseButton::Left,
Modifiers::default(),
);
app.on_mouse_up(
cancel_cx,
cancel_screen_y,
MouseButton::Left,
Modifiers::default(),
);
app.layout(Size::new(VP_W, VP_H));
assert!(cancel_fired.get(), "Cancel button must fire on_cancel");
let restored = last.get();
let drift =
(restored.r - start.r).abs() + (restored.g - start.g).abs() + (restored.b - start.b).abs();
assert!(
drift < 1e-4,
"Cancel must restore the starting colour via on_change (got {:?})",
(restored.r, restored.g, restored.b),
);
}