use crate::sys;
use imgui::{im_str, ImString};
use std::os::raw::c_char;
pub use crate::sys::ImPlotPoint;
pub struct PlotLine {
label: String,
}
impl PlotLine {
pub fn new(label: &str) -> Self {
Self {
label: label.to_owned(),
}
}
pub fn plot(&self, x: &[f64], y: &[f64]) {
if x.len().min(y.len()) == 0 {
return;
}
unsafe {
sys::ImPlot_PlotLinedoublePtrdoublePtr(
im_str!("{}", self.label).as_ptr() as *const c_char,
x.as_ptr(),
y.as_ptr(),
x.len().min(y.len()) as i32, 0, std::mem::size_of::<f64>() as i32, );
}
}
}
pub struct PlotStairs {
label: String,
}
impl PlotStairs {
pub fn new(label: &str) -> Self {
Self {
label: label.to_owned(),
}
}
pub fn plot(&self, x: &[f64], y: &[f64]) {
if x.len().min(y.len()) == 0 {
return;
}
unsafe {
sys::ImPlot_PlotStairsdoublePtrdoublePtr(
im_str!("{}", self.label).as_ptr() as *const c_char,
x.as_ptr(),
y.as_ptr(),
x.len().min(y.len()) as i32, 0, std::mem::size_of::<f64>() as i32, );
}
}
}
pub struct PlotScatter {
label: String,
}
impl PlotScatter {
pub fn new(label: &str) -> Self {
Self {
label: label.to_owned(),
}
}
pub fn plot(&self, x: &[f64], y: &[f64]) {
if x.len().min(y.len()) == 0 {
return;
}
unsafe {
sys::ImPlot_PlotScatterdoublePtrdoublePtr(
im_str!("{}", self.label).as_ptr() as *const c_char,
x.as_ptr(),
y.as_ptr(),
x.len().min(y.len()) as i32, 0, std::mem::size_of::<f64>() as i32, );
}
}
}
pub struct PlotBars {
label: String,
bar_width: f64,
horizontal_bars: bool,
}
impl PlotBars {
pub fn new(label: &str) -> Self {
Self {
label: label.to_owned(),
bar_width: 0.67, horizontal_bars: false,
}
}
pub fn with_bar_width(mut self, bar_width: f64) -> Self {
self.bar_width = bar_width;
self
}
pub fn with_horizontal_bars(mut self) -> Self {
self.horizontal_bars = true;
self
}
pub fn plot(&self, axis_positions: &[f64], bar_values: &[f64]) {
let number_of_points = axis_positions.len().min(bar_values.len());
if number_of_points == 0 {
return;
}
unsafe {
let (plot_function, x, y);
if self.horizontal_bars {
plot_function = sys::ImPlot_PlotBarsHdoublePtrdoublePtr
as unsafe extern "C" fn(*const c_char, *const f64, *const f64, i32, f64, i32, i32);
x = bar_values;
y = axis_positions;
} else {
plot_function = sys::ImPlot_PlotBarsdoublePtrdoublePtr
as unsafe extern "C" fn(*const c_char, *const f64, *const f64, i32, f64, i32, i32);
x = axis_positions;
y = bar_values;
};
plot_function(
im_str!("{}", self.label).as_ptr() as *const c_char,
x.as_ptr(),
y.as_ptr(),
number_of_points as i32, self.bar_width,
0, std::mem::size_of::<f64>() as i32, );
}
}
}
pub struct PlotText {
label: String,
pixel_offset_x: f32,
pixel_offset_y: f32,
}
impl PlotText {
pub fn new(label: &str) -> Self {
Self {
label: label.into(),
pixel_offset_x: 0.0,
pixel_offset_y: 0.0,
}
}
pub fn with_pixel_offset(mut self, offset_x: f32, offset_y: f32) -> Self {
self.pixel_offset_x = offset_x;
self.pixel_offset_y = offset_y;
self
}
pub fn plot(&self, x: f64, y: f64, vertical: bool) {
if self.label.is_empty() {
return;
}
unsafe {
sys::ImPlot_PlotText(
im_str!("{}", self.label).as_ptr() as *const c_char,
x,
y,
vertical,
sys::ImVec2 {
x: self.pixel_offset_x,
y: self.pixel_offset_y,
},
);
}
}
}
pub struct PlotHeatmap {
label: String,
scale_range: Option<(f64, f64)>,
label_format: Option<ImString>,
drawarea_lower_left: ImPlotPoint,
drawarea_upper_right: ImPlotPoint,
}
impl PlotHeatmap {
pub fn new(label: &str) -> Self {
Self {
label: label.to_owned(),
scale_range: None,
label_format: Some(im_str!("%.1f").to_owned()),
drawarea_lower_left: ImPlotPoint { x: 0.0, y: 0.0 },
drawarea_upper_right: ImPlotPoint { x: 1.0, y: 1.0 },
}
}
pub fn with_scale(mut self, scale_min: f64, scale_max: f64) -> Self {
self.scale_range = Some((scale_min, scale_max));
self
}
pub fn with_label_format(mut self, label_format: Option<&str>) -> Self {
self.label_format = label_format.map(|x| im_str!("{}", x));
self
}
pub fn with_drawing_area(mut self, lower_left: ImPlotPoint, upper_right: ImPlotPoint) -> Self {
self.drawarea_lower_left = lower_left;
self.drawarea_upper_right = upper_right;
self
}
pub fn plot(&self, values: &[f64], number_of_rows: u32, number_of_cols: u32) {
let scale_range = self.scale_range.unwrap_or_else(|| {
let mut min_seen = values[0];
let mut max_seen = values[0];
values.iter().for_each(|value| {
min_seen = min_seen.min(*value);
max_seen = max_seen.max(*value);
});
(min_seen, max_seen)
});
unsafe {
sys::ImPlot_PlotHeatmapdoublePtr(
im_str!("{}", self.label).as_ptr() as *const c_char,
values.as_ptr(),
number_of_rows as i32, number_of_cols as i32, scale_range.0,
scale_range.1,
if self.label_format.is_some() {
self.label_format.as_ref().unwrap().as_ptr() as *const c_char
} else {
std::ptr::null()
},
self.drawarea_lower_left,
self.drawarea_upper_right,
);
}
}
}
pub struct PlotStems {
label: String,
reference_y: f64,
}
impl PlotStems {
pub fn new(label: &str) -> Self {
Self {
label: label.to_owned(),
reference_y: 0.0, }
}
pub fn with_reference_y(mut self, reference_y: f64) -> Self {
self.reference_y = reference_y;
self
}
pub fn plot(&self, axis_positions: &[f64], stem_values: &[f64]) {
let number_of_points = axis_positions.len().min(stem_values.len());
if number_of_points == 0 {
return;
}
unsafe {
sys::ImPlot_PlotStemsdoublePtrdoublePtr(
im_str!("{}", self.label).as_ptr() as *const c_char,
axis_positions.as_ptr(),
stem_values.as_ptr(),
number_of_points as i32, self.reference_y,
0, std::mem::size_of::<f64>() as i32, );
}
}
}