Skip to content

Commit

Permalink
feat(plots): plot can cycle through the lines
Browse files Browse the repository at this point in the history
  • Loading branch information
spmadden committed Dec 22, 2024
1 parent 023bc48 commit 5bc9bb3
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 16 deletions.
33 changes: 25 additions & 8 deletions libraries/egui_extras/examples/plotsperf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//

use eframe::{App, CreationContext, Frame, HardwareAcceleration, Renderer};
use egui::{CentralPanel, Context, ThemePreference, Vec2, ViewportBuilder};
use egui::{CentralPanel, Context, ThemePreference, Ui, Vec2, ViewportBuilder};
use irox_egui_extras::logplot::{
x_axis_time_millis_formatter, y_axis_units_formatter, BasicPlot, LineWithErrorBars, PlotPoint,
};
Expand All @@ -17,7 +17,7 @@ use irox_time::Duration;
use irox_tools::random::PRNG;
use irox_units::quantities::Units;
use log::error;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread::JoinHandle;

Expand Down Expand Up @@ -64,7 +64,7 @@ pub fn main() {
};
}
const NUM_LINES_PER_PLOT: usize = 16;
const NUM_PLOTS: usize = 1;
const NUM_PLOTS: usize = 3;
const DATA_RATE: Duration = Duration::from_millis(10); // 100 hz data
const MAX_DATA_TO_KEEP: Duration = Duration::from_minutes(5);
const AVERAGING_WINDOW: Duration = Duration::from_seconds(1);
Expand All @@ -82,8 +82,7 @@ pub struct PlotOpts {
}
impl Drop for PlotOpts {
fn drop(&mut self) {
self.running
.store(false, std::sync::atomic::Ordering::Relaxed);
self.running.store(false, Ordering::Relaxed);
for handle in self.handles.drain(..) {
let _ = handle.join();
}
Expand All @@ -107,6 +106,7 @@ impl TestApp {
for _pidx in 0..NUM_PLOTS {
plots.push(Self::spawn_thread(running.clone(), &cc.egui_ctx, num_lines));
num_lines /= 2;
// num_lines *= 2;
}

Self { plots, running }
Expand All @@ -116,6 +116,9 @@ impl TestApp {
let mut plot = BasicPlot::new(ctx)
.with_x_axis_formatter(x_axis_time_millis_formatter())
.with_y_axis_formatter(y_axis_units_formatter(Units::Volt));
plot.line_highlight_focus_duration = Duration::from_seconds(1);
plot.rotate_line_highlights = true;

let mut handles = Vec::new();
let mut line_off = LINE_CTR;
for lidx in 0..num_lines {
Expand Down Expand Up @@ -196,8 +199,7 @@ impl TestApp {
}
impl Drop for TestApp {
fn drop(&mut self) {
self.running
.store(false, std::sync::atomic::Ordering::Relaxed);
self.running.store(false, Ordering::Relaxed);
}
}

Expand All @@ -215,4 +217,19 @@ impl App for TestApp {
});
}
}
impl ToolApp for TestApp {}
impl ToolApp for TestApp {
fn bottom_bar(&mut self, ui: &mut Ui) {
let mut rotate_highlights = false;
for plot in &self.plots {
rotate_highlights |= plot.plot.rotate_line_highlights;
}
if ui
.checkbox(&mut rotate_highlights, "Cycle highlights")
.changed()
{
for plot in &mut self.plots {
plot.plot.rotate_line_highlights = rotate_highlights;
}
}
}
}
54 changes: 46 additions & 8 deletions libraries/egui_extras/src/logplot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ pub struct BasicPlot {
pub title: Option<String>,

last_render_size: Rect2D,
pub rotate_line_highlights: bool,
pub line_highlight_focus_duration: Duration,
pause_line_highlight_for_hover: bool,
last_line_highlight_index: usize,
last_line_highlight_time: UnixTimestamp,
}
macro_rules! scale_y {
($self:ident, $ax:ident,$pos:ident) => {{
Expand Down Expand Up @@ -638,6 +643,23 @@ impl BasicPlot {
Pos2::new(x_axis_x_max, y_axis_y_max),
);

if self.rotate_line_highlights && !self.pause_line_highlight_for_hover {
let now = UnixTimestamp::now();
if now - self.line_highlight_focus_duration > self.last_line_highlight_time {
self.last_line_highlight_time = now;
self.last_line_highlight_index += 1;
if self.last_line_highlight_index >= self.lines.len() {
self.last_line_highlight_index = 0;
}
for line in &mut self.lines {
line.is_hovered = false;
}
if let Some(line) = self.lines.get_mut(self.last_line_highlight_index) {
line.is_hovered = true;
}
}
}

let lr = rect.into();
if lr != self.last_render_size || self.any_lines_changed() {
profile_scope!("update range", self.name.as_str());
Expand Down Expand Up @@ -815,6 +837,11 @@ impl BasicPlot {

// draw the points as individual line segments
let mut start_text = rect.left_bottom();
let text_rect = Align2::LEFT_BOTTOM.anchor_size(
Pos2::new(start_text.x, start_text.y),
Vec2::new(rect.width(), 12.),
);
let mut any_hovered = false;
for line in &mut self.lines {
profile_scope!("draw controls", line.name.as_str());
let visible = line.visible.load(Ordering::Relaxed);
Expand All @@ -825,27 +852,38 @@ impl BasicPlot {
let galley =
painter.layout_no_wrap(line.name.to_string(), line.text_font.clone(), color);
let used = Align2::LEFT_BOTTOM.anchor_size(start_text, galley.size());
let mut hovered = false;
if let Some(pos) = response.hover_pos() {
let mut hovered = false;
let hvr = ui.visuals().widgets.hovered;
let fill = hvr.bg_fill;
let rnd = hvr.rounding;
let strk = hvr.bg_stroke;
if used.contains(pos) {
let hvr = ui.visuals().widgets.hovered;
let fill = hvr.bg_fill;
let rnd = hvr.rounding;
let strk = hvr.bg_stroke;
painter.rect(used, rnd, fill, strk);

hovered = true;
any_hovered = true;
if response.clicked() {
line.visible.swap(!visible, Ordering::Relaxed);
}
}
}
if line.is_hovered != hovered {
line.is_hovered = hovered;
if text_rect.contains(pos) {
any_hovered = true;
line.is_hovered = hovered;
} else if !self.rotate_line_highlights {
// clear off the automatic hovering (if left)
line.is_hovered = false;
}
}
painter.galley(used.min, galley, color);
start_text.x += used.width() + 10.;
}
self.pause_line_highlight_for_hover = any_hovered;
if !any_hovered && !self.rotate_line_highlights {
for line in &mut self.lines {
line.is_hovered = false;
}
}

self.draw_cursor(ui, &mut response, &mut painter, closest_hover, &grid_bounds);

Expand Down

0 comments on commit 5bc9bb3

Please sign in to comment.