feat(plot): crosshair with an interpolated per-signal hover readout
This commit is contained in:
1 parent
a153b73ead
commit
fd0c471430
11 files changed
+809
-22
No files matched your search
@@ -113,6 +113,10 @@ void Controller::set_viewport(Rect px) {
|
||||
// transforms read.
|
||||
plot_->set_viewport(px);
|
||||
plot_->layout();
|
||||
// A resize moves the axes (and with them the data under a stationary pointer), so the
|
||||
// crosshair is re-placed against the new rect -- and cleared if the pointer is now outside
|
||||
// it, which is the same rule as a pointer that left.
|
||||
if (has_pointer_) update_crosshair(pointer_x_, pointer_y_);
|
||||
// The hover the layout is part of: a handle under the pointer may be somewhere
|
||||
// else now, and the highlight the renderer draws reads what this publishes.
|
||||
publish_hot();
|
||||
@@ -132,6 +136,11 @@ void Controller::on_pointer(const PointerEvent& raw) {
|
||||
} else if (e.down && mode_ != DragMode::None) {
|
||||
update_drag(e);
|
||||
}
|
||||
// The crosshair is placed (or cleared) from the pointer's own position, after the gesture
|
||||
// above: a press does not clear it -- the pointer is still over the axes, still pointing at
|
||||
// whatever it just grabbed -- and a drag keeps it re-anchored to the pointer as the data
|
||||
// moves under it.
|
||||
update_crosshair(e.x, e.y);
|
||||
// Every exit above ends here: a hover that moved, a gesture that opened, and a
|
||||
// gesture that closed all change what is under the pointer, and the publish is
|
||||
// what makes the renderer's highlight (and a host's resize cursor) follow.
|
||||
@@ -174,6 +183,11 @@ void Controller::on_wheel(const WheelEvent& raw) {
|
||||
// emphasizes the handle the pointer is over *now*, rather than the one it was over before,
|
||||
// without waiting for the mouse to move again.
|
||||
plot_->layout();
|
||||
// The data under the pointer moved with the ranges, so the crosshair -- which is a data
|
||||
// coordinate -- is re-anchored to the pointer rather than left on the value it was placed
|
||||
// at: it follows the pointer, and this is the one thing that moves the data without moving
|
||||
// the pointer.
|
||||
if (has_pointer_) update_crosshair(pointer_x_, pointer_y_);
|
||||
publish_hot();
|
||||
}
|
||||
|
||||
@@ -206,11 +220,31 @@ void Controller::on_key(const KeyEvent& e) {
|
||||
// A key stroke that moved a range moved the geometry under a stationary pointer, exactly
|
||||
// as a wheel notch does: refresh the layout and republish what is hot, so the highlight a
|
||||
// frame draws is the handle the pointer is over now (see on_wheel). A key this controller
|
||||
// has no gesture for changes nothing and returns above.
|
||||
// has no gesture for changes nothing and returns above -- and so does not touch the
|
||||
// crosshair either.
|
||||
plot_->layout();
|
||||
if (has_pointer_) update_crosshair(pointer_x_, pointer_y_);
|
||||
publish_hot();
|
||||
}
|
||||
|
||||
void Controller::update_crosshair(f32 px, f32 py) {
|
||||
// Inside the data area the crosshair is at the coordinates under the pointer; outside it
|
||||
// there is no data to read, so there is no crosshair -- the null answer, rather than a
|
||||
// value clamped to the nearest edge of the window.
|
||||
const PlotLayout& layout = std::as_const(*plot_).layout();
|
||||
if (!layout.axes.contains(px, py)) {
|
||||
plot_->clear_crosshair();
|
||||
return;
|
||||
}
|
||||
// Both coordinates, on the primary axis pair (the same pair the grid and a region's fill
|
||||
// are placed through): a pointer over the axes knows its x and its y, so a single plot's
|
||||
// crosshair is the full cross. A `Figure` is driven by `Figure::set_crosshair()` instead,
|
||||
// which applies one x to every row and draws no horizontal line -- its rows share x and
|
||||
// not y.
|
||||
plot_->set_crosshair(plot_->x_transform(0u).to_data_x(static_cast<f64>(px)),
|
||||
plot_->y_transform(0u).to_data_y(static_cast<f64>(py)), true);
|
||||
}
|
||||
|
||||
u64 Controller::hovered_cursor() const {
|
||||
if (!has_pointer_) return kInvalid;
|
||||
return cursor_at(pointer_x_, pointer_y_);
|
||||
|
||||
Reference in new issue
Block a user