test(input): pin the dragged nearest-tick ruler's snap on drop
This commit is contained in:
1 parent
d2ba67921e
commit
2307aa1158
1 file changed
+47
-1
@@ -366,7 +366,7 @@ PLOT_TEST(key_f_auto_fits_traces) {
|
|||||||
/// The grab radius is a distance the user aims with, so it must be the same
|
/// The grab radius is a distance the user aims with, so it must be the same
|
||||||
/// *physical* distance at any DPI: the controller compares device-pixel coordinates
|
/// *physical* distance at any DPI: the controller compares device-pixel coordinates
|
||||||
/// against `logical * Plot::ui_scale()`. The press positions below are the same
|
/// against `logical * Plot::ui_scale()`. The press positions below are the same
|
||||||
/// logical distance (0.9 and 1.1 of the 5 px radius) from the cursor at both scales,
|
/// logical distance (0.9 and 1.1 of the 7 px radius) from the cursor at both scales,
|
||||||
/// so the same press grabs -- and the same press just outside does not.
|
/// so the same press grabs -- and the same press just outside does not.
|
||||||
PLOT_TEST(grab_radius_scales_with_dpi) {
|
PLOT_TEST(grab_radius_scales_with_dpi) {
|
||||||
for (const f32 scale : {1.0f, 2.0f}) {
|
for (const f32 scale : {1.0f, 2.0f}) {
|
||||||
@@ -1053,6 +1053,52 @@ PLOT_TEST(horizontal_ruler_follows_the_pointer_on_an_inverted_y_range) {
|
|||||||
PLOT_CHECK(f.plot.cursor(ruler).y > 50.0);
|
PLOT_CHECK(f.plot.cursor(ruler).y > 50.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The horizontal half of `cursor_snaps_when_the_drag_ends`: an `HRulerSnap::NearestTick` ruler
|
||||||
|
/// dragged through the controller writes the free pointer row for the whole gesture and lands on
|
||||||
|
/// a y tick only on release -- the snap-on-drop a marker now uses, which a ruler did *not* before
|
||||||
|
/// (it snapped continuously inside `set_cursor_y`). This is the case that catches a regression
|
||||||
|
/// to that continuous behaviour: mid-drag the stored y is on no tick and equals the pointer's row,
|
||||||
|
/// and only the drop moves it to the grid.
|
||||||
|
PLOT_TEST(a_dragged_nearest_tick_ruler_snaps_only_when_the_drag_ends) {
|
||||||
|
Fixture f;
|
||||||
|
f.ay = f.plot.add_y_axis({"v", {0.0, 100.0}, false, plot::AxisPlace::Left, false});
|
||||||
|
const u32 ruler = f.plot.add_h_ruler(40.0, plot::Color::hex(0x35D0A8));
|
||||||
|
f.plot.set_cursor_h_snap(ruler, plot::HRulerSnap::NearestTick);
|
||||||
|
f.plot.layout();
|
||||||
|
|
||||||
|
const std::vector<plot::Tick>& ticks = f.plot.y_axis(f.ay).ticks;
|
||||||
|
PLOT_CHECK(ticks.size() >= 3u);
|
||||||
|
// A row between two adjacent ticks, nearer the lower-valued one (the larger screen row).
|
||||||
|
const f64 lo = ticks[1].value;
|
||||||
|
const f64 hi = ticks[2].value;
|
||||||
|
PLOT_CHECK(lo < hi);
|
||||||
|
const f64 between = lo + 0.4 * (hi - lo); // equal to no tick, nearer `lo`
|
||||||
|
const auto is_tick = [&ticks](f64 y) {
|
||||||
|
for (const plot::Tick& t : ticks) {
|
||||||
|
if (std::fabs(t.value - y) < 1e-9) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
PLOT_CHECK(!is_tick(between));
|
||||||
|
|
||||||
|
const f32 column = screen_x_of(f.plot, f.ax, 70.0);
|
||||||
|
const f32 to = static_cast<f32>(row_of(f.plot, f.ay, between));
|
||||||
|
const f32 from = static_cast<f32>(row_of(f.plot, f.ay, f.plot.cursor(ruler).y));
|
||||||
|
|
||||||
|
press(f.controller, column, from);
|
||||||
|
PLOT_CHECK(f.controller.drag_mode() == plot::input::DragMode::MoveCursor);
|
||||||
|
PLOT_CHECK(f.controller.grabbed_cursor() == ruler);
|
||||||
|
move_to(f.controller, column, to);
|
||||||
|
// Mid-drag the stored y is the free pointer row and on no tick: the snap has not run.
|
||||||
|
PLOT_CHECK_NEAR(f.plot.cursor(ruler).y, data_at_row(f.plot, f.ay, to), 1e-9);
|
||||||
|
PLOT_CHECK(!is_tick(f.plot.cursor(ruler).y));
|
||||||
|
|
||||||
|
// The drop commits the snap: the stored y is the nearest tick and it was not before.
|
||||||
|
release(f.controller, column, to);
|
||||||
|
PLOT_CHECK_NEAR(f.plot.cursor(ruler).y, lo, 1e-9);
|
||||||
|
PLOT_CHECK(is_tick(f.plot.cursor(ruler).y));
|
||||||
|
}
|
||||||
|
|
||||||
/// Nearest-first resolution *across* orientations: a pointer within reach of both a marker and a
|
/// Nearest-first resolution *across* orientations: a pointer within reach of both a marker and a
|
||||||
/// ruler takes the nearer of the two, so neither widens the other's target -- which is what lets
|
/// ruler takes the nearer of the two, so neither widens the other's target -- which is what lets
|
||||||
/// one hit test serve two instruments. Each press below is 1 px from its winner and 4 px from the
|
/// one hit test serve two instruments. Each press below is 1 px from its winner and 4 px from the
|
||||||
|
|||||||
Reference in new issue
Block a user