Added stem plots and legend entry hover checking

This commit is contained in:
4bb4 2021-01-31 12:40:13 +01:00
parent 2c56bd9803
commit 21aa28591c
7 changed files with 113 additions and 10 deletions

5
.gitignore vendored
View file

@ -1,6 +1,9 @@
# Generated by Cargo # Generated by Cargo
# will have compiled files and executables # will have compiled files and executables
/target/ **/target/
# Editor temporary files
**/*.swp
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html

View file

@ -83,7 +83,7 @@ created for 64-bit floats.
- [x] Styling variables - [x] Styling variables
- [x] Colormaps - [x] Colormaps
- [x] Legend locations - [x] Legend locations
- [ ] Plot querying - [x] Plot querying
- [x] is hovered - [x] is hovered
- [x] mouse position in plot - [x] mouse position in plot
- [x] plot limits - [x] plot limits
@ -91,7 +91,7 @@ created for 64-bit floats.
- [x] get plot query - [x] get plot query
- [x] are axes hovered - [x] are axes hovered
- [x] Choice of y axis - [x] Choice of y axis
- [ ] Are legend entries hovered - [x] Are legend entries hovered
- [ ] Utils - [ ] Utils
- [x] Plot limit setting - [x] Plot limit setting
- [x] imgui-rs style safe push/pop stacks - [x] imgui-rs style safe push/pop stacks

View file

@ -3,6 +3,7 @@ pub mod heatmaps;
pub mod line_plots; pub mod line_plots;
pub mod scatter_plots; pub mod scatter_plots;
pub mod stairs_plots; pub mod stairs_plots;
mod stem_plots;
pub mod text_plots; pub mod text_plots;
use imgui::{im_str, Condition, Ui, Window}; use imgui::{im_str, Condition, Ui, Window};
@ -43,5 +44,9 @@ pub fn show_demos(ui: &Ui, plot_ui: &PlotUi) {
ui.separator(); ui.separator();
ui.text(im_str!("Heatmaps:")); ui.text(im_str!("Heatmaps:"));
heatmaps::show_demo_headers(ui, plot_ui); heatmaps::show_demo_headers(ui, plot_ui);
ui.separator();
ui.text(im_str!("Stem plots:"));
stem_plots::show_demo_headers(ui, plot_ui);
}); });
} }

View file

@ -3,12 +3,12 @@
use imgui::{im_str, CollapsingHeader, Condition, Ui}; use imgui::{im_str, CollapsingHeader, Condition, Ui};
use implot::{ use implot::{
get_plot_limits, get_plot_mouse_position, get_plot_query, is_plot_hovered, is_plot_queried, get_plot_limits, get_plot_mouse_position, get_plot_query, is_legend_entry_hovered,
pixels_to_plot_vec2, plot_to_pixels_vec2, push_style_color, push_style_var_f32, is_plot_hovered, is_plot_queried, pixels_to_plot_vec2, plot_to_pixels_vec2, push_style_color,
push_style_var_i32, set_colormap_from_preset, set_colormap_from_vec, set_plot_y_axis, push_style_var_f32, push_style_var_i32, set_colormap_from_preset, set_colormap_from_vec,
AxisFlags, Colormap, ImPlotLimits, ImPlotPoint, ImPlotRange, ImVec2, ImVec4, Marker, Plot, set_plot_y_axis, AxisFlags, Colormap, ImPlotLimits, ImPlotPoint, ImPlotRange, ImVec2, ImVec4,
PlotColorElement, PlotFlags, PlotLine, PlotLocation, PlotOrientation, PlotUi, StyleVar, Marker, Plot, PlotColorElement, PlotFlags, PlotLine, PlotLocation, PlotOrientation, PlotUi,
YAxisChoice, StyleVar, YAxisChoice,
}; };
pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) { pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
@ -156,6 +156,8 @@ pub fn show_query_features_plot(ui: &Ui, plot_ui: &PlotUi) {
let mut hover_pos_from_pixels: Option<ImPlotPoint> = None; let mut hover_pos_from_pixels: Option<ImPlotPoint> = None;
let mut plot_limits: Option<ImPlotLimits> = None; let mut plot_limits: Option<ImPlotLimits> = None;
let mut query_limits: Option<ImPlotLimits> = None; let mut query_limits: Option<ImPlotLimits> = None;
let mut legend1_hovered = false;
let mut legend2_hovered = false;
// Draw a plot // Draw a plot
Plot::new("Plot querying") Plot::new("Plot querying")
@ -183,6 +185,12 @@ pub fn show_query_features_plot(ui: &Ui, plot_ui: &PlotUi) {
None, None,
)); ));
// Plot a line so we have a legend entry
PlotLine::new("Legend1").plot(&vec![2.0, 2.0], &vec![2.0, 1.0]);
PlotLine::new("Legend2").plot(&vec![0.0, 0.0], &vec![1.0, 1.0]);
legend1_hovered = is_legend_entry_hovered("Legend1");
legend2_hovered = is_legend_entry_hovered("Legend2");
if is_plot_queried() { if is_plot_queried() {
query_limits = Some(get_plot_query(None)); query_limits = Some(get_plot_query(None));
} }
@ -214,6 +222,11 @@ pub fn show_query_features_plot(ui: &Ui, plot_ui: &PlotUi) {
if let Some(query) = query_limits { if let Some(query) = query_limits {
ui.text(im_str!("Query limits are {:#?}", query)); ui.text(im_str!("Query limits are {:#?}", query));
} }
ui.text(im_str!(
"Legend hovering - 1: {}, 2: {}",
legend1_hovered,
legend2_hovered
));
// Try out converting pixel position to plot position // Try out converting pixel position to plot position
if let Some(pos) = hover_pos_from_pixels { if let Some(pos) = hover_pos_from_pixels {

View file

@ -0,0 +1,28 @@
//! This example demonstrates how stem plots are to be used. For more general
//! features of the libray, see the line_plots example.
use imgui::{im_str, CollapsingHeader, Ui};
use implot::{Plot, PlotStems, PlotUi};
pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
ui.text(im_str!("This header shows a simple stem plot."));
let content_width = ui.window_content_region_width();
Plot::new("Stem plot")
// The size call could also be omitted, though the defaults don't consider window
// width, which is why we're not doing so here.
.size(content_width, 300.0)
.build(plot_ui, || {
// If this is called outside a plot build callback, the program will panic.
let axis_positions = vec![0.2, 0.4, 0.6, 0.8, 0.9, 0.93];
let values = vec![0.1, 0.2, 0.3, 0.4, 0.3, 0.8];
PlotStems::new("legend label")
.with_reference_y(0.1)
.plot(&axis_positions, &values);
});
}
pub fn show_demo_headers(ui: &Ui, plot_ui: &PlotUi) {
if CollapsingHeader::new(im_str!("Stem plots")).build(&ui) {
show_basic_plot(&ui, &plot_ui);
}
}

View file

@ -20,6 +20,7 @@ use implot_sys as sys;
// TODO(4bb4) facade-wrap these? // TODO(4bb4) facade-wrap these?
pub use self::{context::*, plot::*, plot_elements::*}; pub use self::{context::*, plot::*, plot_elements::*};
use imgui::im_str;
pub use sys::{ImPlotLimits, ImPlotPoint, ImPlotRange, ImVec2, ImVec4}; pub use sys::{ImPlotLimits, ImPlotPoint, ImPlotRange, ImVec2, ImVec4};
mod context; mod context;
@ -572,6 +573,11 @@ pub fn is_plot_y_axis_hovered(y_axis_choice: Option<YAxisChoice>) -> bool {
unsafe { sys::ImPlot_IsPlotYAxisHovered(y_axis_choice_i32) } unsafe { sys::ImPlot_IsPlotYAxisHovered(y_axis_choice_i32) }
} }
/// Returns true if the given item in the legend of the current plot is hovered.
pub fn is_legend_entry_hovered(legend_entry: &str) -> bool {
unsafe { sys::ImPlot_IsLegendEntryHovered(im_str!("{}", legend_entry).as_ptr() as *const i8) }
}
// --- Demo window ------------------------------------------------------------------------------- // --- Demo window -------------------------------------------------------------------------------
/// Show the demo window for poking around what functionality implot has to /// Show the demo window for poking around what functionality implot has to
/// offer. Note that not all of this is necessarily implemented in implot-rs /// offer. Note that not all of this is necessarily implemented in implot-rs

View file

@ -147,7 +147,7 @@ impl PlotBars {
/// Draw a previously-created bar plot. Use this in closures passed to /// Draw a previously-created bar plot. Use this in closures passed to
/// [`Plot::build()`](struct.Plot.html#method.build). The `axis_positions` /// [`Plot::build()`](struct.Plot.html#method.build). The `axis_positions`
/// specify where on the corersponding axis (X for vertical mode, Y for horizontal mode) the /// specify where on the corresponding axis (X for vertical mode, Y for horizontal mode) the
/// bar is drawn, and the `bar_values` specify what values the bars have. /// bar is drawn, and the `bar_values` specify what values the bars have.
pub fn plot(&self, axis_positions: &[f64], bar_values: &[f64]) { pub fn plot(&self, axis_positions: &[f64], bar_values: &[f64]) {
let number_of_points = axis_positions.len().min(bar_values.len()); let number_of_points = axis_positions.len().min(bar_values.len());
@ -332,3 +332,51 @@ impl PlotHeatmap {
} }
} }
} }
/// Struct to provide stem plotting functionality.
pub struct PlotStems {
/// Label to show in the legend for this line
label: String,
/// Reference value for the y value, which the stems are "with respect to"
reference_y: f64,
}
impl PlotStems {
/// Create a new stem plot to be shown. Does not draw anything by itself, call
/// [`PlotStems::plot`] on the struct for that.
pub fn new(label: &str) -> Self {
Self {
label: label.to_owned(),
reference_y: 0.0, // Default value taken from C++ implot
}
}
/// Set the reference y value for the stems
pub fn with_reference_y(mut self, reference_y: f64) -> Self {
self.reference_y = reference_y;
self
}
/// Draw a previously-created stem plot. Use this in closures passed to
/// [`Plot::build()`](struct.Plot.html#method.build). The `axis_positions` specify where on the
/// X axis the stems are drawn, and the `stem_values` specify what values the stems have.
pub fn plot(&self, axis_positions: &[f64], stem_values: &[f64]) {
let number_of_points = axis_positions.len().min(stem_values.len());
// If there is no data to plot, we stop here
if number_of_points == 0 {
return;
}
unsafe {
sys::ImPlot_PlotStemsdoublePtrdoublePtr(
im_str!("{}", self.label).as_ptr() as *const i8,
axis_positions.as_ptr(),
stem_values.as_ptr(),
number_of_points as i32, // "as" casts saturate as of Rust 1.45. This is safe here.
self.reference_y,
0, // No offset
std::mem::size_of::<f64>() as i32, // Stride, set to one f64 for the standard use case
);
}
}
}