use super::{
PlotData, PlotError, PlotItemStyle, plot_spec_with_style, validate_data_lengths,
with_plot_str_or_empty,
};
use crate::{DigitalFlags, ItemFlags, sys};
pub struct DigitalPlot<'a> {
label: &'a str,
x_data: &'a [f64],
y_data: &'a [f64],
style: PlotItemStyle,
flags: DigitalFlags,
item_flags: ItemFlags,
offset: i32,
stride: i32,
}
impl<'a> super::PlotItemStyled for DigitalPlot<'a> {
fn style_mut(&mut self) -> &mut PlotItemStyle {
&mut self.style
}
}
impl<'a> DigitalPlot<'a> {
pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [f64]) -> Self {
Self {
label,
x_data,
y_data,
style: PlotItemStyle::default(),
flags: DigitalFlags::NONE,
item_flags: ItemFlags::NONE,
offset: 0,
stride: std::mem::size_of::<f64>() as i32,
}
}
pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
self.flags = flags;
self
}
pub fn with_style(mut self, style: PlotItemStyle) -> Self {
self.style = style;
self
}
pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
self.item_flags = flags;
self
}
pub fn with_offset(mut self, offset: i32) -> Self {
self.offset = offset;
self
}
pub fn with_stride(mut self, stride: i32) -> Self {
self.stride = stride;
self
}
pub fn validate(&self) -> Result<(), PlotError> {
validate_data_lengths(self.x_data, self.y_data)?;
Ok(())
}
pub fn plot(self) {
let Ok(count) = i32::try_from(self.x_data.len()) else {
return;
};
with_plot_str_or_empty(self.label, |label_ptr| unsafe {
let spec = plot_spec_with_style(
self.style,
self.flags.bits() | self.item_flags.bits(),
self.offset,
self.stride,
);
sys::ImPlot_PlotDigital_doublePtr(
label_ptr,
self.x_data.as_ptr(),
self.y_data.as_ptr(),
count,
spec,
);
})
}
}
impl<'a> PlotData for DigitalPlot<'a> {
fn label(&self) -> &str {
self.label
}
fn data_len(&self) -> usize {
self.x_data.len().min(self.y_data.len())
}
}
pub struct DigitalPlotF32<'a> {
label: &'a str,
x_data: &'a [f32],
y_data: &'a [f32],
style: PlotItemStyle,
flags: DigitalFlags,
item_flags: ItemFlags,
}
impl<'a> super::PlotItemStyled for DigitalPlotF32<'a> {
fn style_mut(&mut self) -> &mut PlotItemStyle {
&mut self.style
}
}
impl<'a> DigitalPlotF32<'a> {
pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
Self {
label,
x_data,
y_data,
style: PlotItemStyle::default(),
flags: DigitalFlags::NONE,
item_flags: ItemFlags::NONE,
}
}
pub fn with_style(mut self, style: PlotItemStyle) -> Self {
self.style = style;
self
}
pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
self.flags = flags;
self
}
pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
self.item_flags = flags;
self
}
pub fn validate(&self) -> Result<(), PlotError> {
if self.x_data.len() != self.y_data.len() {
return Err(PlotError::DataLengthMismatch {
x_len: self.x_data.len(),
y_len: self.y_data.len(),
});
}
if self.x_data.is_empty() {
return Err(PlotError::EmptyData);
}
Ok(())
}
pub fn plot(self) {
let Ok(count) = i32::try_from(self.x_data.len()) else {
return;
};
with_plot_str_or_empty(self.label, |label_ptr| unsafe {
let spec = plot_spec_with_style(
self.style,
self.flags.bits() | self.item_flags.bits(),
0,
std::mem::size_of::<f32>() as i32,
);
sys::ImPlot_PlotDigital_FloatPtr(
label_ptr,
self.x_data.as_ptr(),
self.y_data.as_ptr(),
count,
spec,
);
})
}
}
impl<'a> PlotData for DigitalPlotF32<'a> {
fn label(&self) -> &str {
self.label
}
fn data_len(&self) -> usize {
self.x_data.len().min(self.y_data.len())
}
}
pub struct SimpleDigitalPlot<'a> {
label: &'a str,
y_data: &'a [f64],
style: PlotItemStyle,
flags: DigitalFlags,
item_flags: ItemFlags,
x_scale: f64,
x_start: f64,
}
impl<'a> super::PlotItemStyled for SimpleDigitalPlot<'a> {
fn style_mut(&mut self) -> &mut PlotItemStyle {
&mut self.style
}
}
impl<'a> SimpleDigitalPlot<'a> {
pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
Self {
label,
y_data,
style: PlotItemStyle::default(),
flags: DigitalFlags::NONE,
item_flags: ItemFlags::NONE,
x_scale: 1.0,
x_start: 0.0,
}
}
pub fn with_x_scale(mut self, x_scale: f64) -> Self {
self.x_scale = x_scale;
self
}
pub fn with_x_start(mut self, x_start: f64) -> Self {
self.x_start = x_start;
self
}
pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
self.flags = flags;
self
}
pub fn with_style(mut self, style: PlotItemStyle) -> Self {
self.style = style;
self
}
pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
self.item_flags = flags;
self
}
pub fn validate(&self) -> Result<(), PlotError> {
if self.y_data.is_empty() {
return Err(PlotError::EmptyData);
}
Ok(())
}
pub fn plot(self) {
let Ok(count) = i32::try_from(self.y_data.len()) else {
return;
};
let x_data: Vec<f64> = (0..self.y_data.len())
.map(|i| self.x_start + i as f64 * self.x_scale)
.collect();
with_plot_str_or_empty(self.label, |label_ptr| unsafe {
let spec = plot_spec_with_style(
self.style,
self.flags.bits() | self.item_flags.bits(),
0,
std::mem::size_of::<f64>() as i32,
);
sys::ImPlot_PlotDigital_doublePtr(
label_ptr,
x_data.as_ptr(),
self.y_data.as_ptr(),
count,
spec,
);
})
}
}
impl<'a> PlotData for SimpleDigitalPlot<'a> {
fn label(&self) -> &str {
self.label
}
fn data_len(&self) -> usize {
self.y_data.len()
}
}
pub struct BooleanDigitalPlot<'a> {
label: &'a str,
x_data: &'a [f64],
y_data: &'a [bool],
style: PlotItemStyle,
flags: DigitalFlags,
item_flags: ItemFlags,
}
impl<'a> super::PlotItemStyled for BooleanDigitalPlot<'a> {
fn style_mut(&mut self) -> &mut PlotItemStyle {
&mut self.style
}
}
impl<'a> BooleanDigitalPlot<'a> {
pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [bool]) -> Self {
Self {
label,
x_data,
y_data,
style: PlotItemStyle::default(),
flags: DigitalFlags::NONE,
item_flags: ItemFlags::NONE,
}
}
pub fn with_style(mut self, style: PlotItemStyle) -> Self {
self.style = style;
self
}
pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
self.flags = flags;
self
}
pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
self.item_flags = flags;
self
}
pub fn validate(&self) -> Result<(), PlotError> {
if self.x_data.len() != self.y_data.len() {
return Err(PlotError::DataLengthMismatch {
x_len: self.x_data.len(),
y_len: self.y_data.len(),
});
}
if self.x_data.is_empty() {
return Err(PlotError::EmptyData);
}
Ok(())
}
pub fn plot(self) {
let Ok(count) = i32::try_from(self.x_data.len()) else {
return;
};
let y_data_f64: Vec<f64> = self
.y_data
.iter()
.map(|&b| if b { 1.0 } else { 0.0 })
.collect();
with_plot_str_or_empty(self.label, |label_ptr| unsafe {
let spec = plot_spec_with_style(
self.style,
self.flags.bits() | self.item_flags.bits(),
0,
std::mem::size_of::<f64>() as i32,
);
sys::ImPlot_PlotDigital_doublePtr(
label_ptr,
self.x_data.as_ptr(),
y_data_f64.as_ptr(),
count,
spec,
);
})
}
}
impl<'a> PlotData for BooleanDigitalPlot<'a> {
fn label(&self) -> &str {
self.label
}
fn data_len(&self) -> usize {
self.x_data.len().min(self.y_data.len())
}
}