1use super::{PlotData, PlotError, validate_data_lengths, with_plot_str_or_empty};
4use crate::DigitalFlags;
5use crate::sys;
6
7pub struct DigitalPlot<'a> {
12 label: &'a str,
13 x_data: &'a [f64],
14 y_data: &'a [f64],
15 flags: DigitalFlags,
16 offset: i32,
17 stride: i32,
18}
19
20impl<'a> DigitalPlot<'a> {
21 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [f64]) -> Self {
23 Self {
24 label,
25 x_data,
26 y_data,
27 flags: DigitalFlags::NONE,
28 offset: 0,
29 stride: std::mem::size_of::<f64>() as i32,
30 }
31 }
32
33 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
35 self.flags = flags;
36 self
37 }
38
39 pub fn with_offset(mut self, offset: i32) -> Self {
41 self.offset = offset;
42 self
43 }
44
45 pub fn with_stride(mut self, stride: i32) -> Self {
47 self.stride = stride;
48 self
49 }
50
51 pub fn validate(&self) -> Result<(), PlotError> {
53 validate_data_lengths(self.x_data, self.y_data)?;
54
55 Ok(())
58 }
59
60 pub fn plot(self) {
62 let Ok(count) = i32::try_from(self.x_data.len()) else {
63 return;
64 };
65 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
66 sys::ImPlot_PlotDigital_doublePtr(
67 label_ptr,
68 self.x_data.as_ptr(),
69 self.y_data.as_ptr(),
70 count,
71 self.flags.bits() as i32,
72 self.offset,
73 self.stride,
74 );
75 })
76 }
77}
78
79impl<'a> PlotData for DigitalPlot<'a> {
80 fn label(&self) -> &str {
81 self.label
82 }
83
84 fn data_len(&self) -> usize {
85 self.x_data.len().min(self.y_data.len())
86 }
87}
88
89pub struct DigitalPlotF32<'a> {
91 label: &'a str,
92 x_data: &'a [f32],
93 y_data: &'a [f32],
94 flags: DigitalFlags,
95}
96
97impl<'a> DigitalPlotF32<'a> {
98 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
100 Self {
101 label,
102 x_data,
103 y_data,
104 flags: DigitalFlags::NONE,
105 }
106 }
107
108 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
110 self.flags = flags;
111 self
112 }
113
114 pub fn validate(&self) -> Result<(), PlotError> {
116 if self.x_data.len() != self.y_data.len() {
117 return Err(PlotError::DataLengthMismatch {
118 x_len: self.x_data.len(),
119 y_len: self.y_data.len(),
120 });
121 }
122 if self.x_data.is_empty() {
123 return Err(PlotError::EmptyData);
124 }
125 Ok(())
126 }
127
128 pub fn plot(self) {
130 let Ok(count) = i32::try_from(self.x_data.len()) else {
131 return;
132 };
133 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
134 sys::ImPlot_PlotDigital_FloatPtr(
135 label_ptr,
136 self.x_data.as_ptr(),
137 self.y_data.as_ptr(),
138 count,
139 self.flags.bits() as i32,
140 0,
141 std::mem::size_of::<f32>() as i32,
142 );
143 })
144 }
145}
146
147impl<'a> PlotData for DigitalPlotF32<'a> {
148 fn label(&self) -> &str {
149 self.label
150 }
151
152 fn data_len(&self) -> usize {
153 self.x_data.len().min(self.y_data.len())
154 }
155}
156
157pub struct SimpleDigitalPlot<'a> {
159 label: &'a str,
160 y_data: &'a [f64],
161 flags: DigitalFlags,
162 x_scale: f64,
163 x_start: f64,
164}
165
166impl<'a> SimpleDigitalPlot<'a> {
167 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
169 Self {
170 label,
171 y_data,
172 flags: DigitalFlags::NONE,
173 x_scale: 1.0,
174 x_start: 0.0,
175 }
176 }
177
178 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
180 self.x_scale = x_scale;
181 self
182 }
183
184 pub fn with_x_start(mut self, x_start: f64) -> Self {
186 self.x_start = x_start;
187 self
188 }
189
190 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
192 self.flags = flags;
193 self
194 }
195
196 pub fn validate(&self) -> Result<(), PlotError> {
198 if self.y_data.is_empty() {
199 return Err(PlotError::EmptyData);
200 }
201 Ok(())
202 }
203
204 pub fn plot(self) {
206 let Ok(count) = i32::try_from(self.y_data.len()) else {
207 return;
208 };
209 let x_data: Vec<f64> = (0..self.y_data.len())
211 .map(|i| self.x_start + i as f64 * self.x_scale)
212 .collect();
213
214 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
215 sys::ImPlot_PlotDigital_doublePtr(
216 label_ptr,
217 x_data.as_ptr(),
218 self.y_data.as_ptr(),
219 count,
220 self.flags.bits() as i32,
221 0,
222 std::mem::size_of::<f64>() as i32,
223 );
224 })
225 }
226}
227
228impl<'a> PlotData for SimpleDigitalPlot<'a> {
229 fn label(&self) -> &str {
230 self.label
231 }
232
233 fn data_len(&self) -> usize {
234 self.y_data.len()
235 }
236}
237
238pub struct BooleanDigitalPlot<'a> {
240 label: &'a str,
241 x_data: &'a [f64],
242 y_data: &'a [bool],
243 flags: DigitalFlags,
244}
245
246impl<'a> BooleanDigitalPlot<'a> {
247 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [bool]) -> Self {
249 Self {
250 label,
251 x_data,
252 y_data,
253 flags: DigitalFlags::NONE,
254 }
255 }
256
257 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
259 self.flags = flags;
260 self
261 }
262
263 pub fn validate(&self) -> Result<(), PlotError> {
265 if self.x_data.len() != self.y_data.len() {
266 return Err(PlotError::DataLengthMismatch {
267 x_len: self.x_data.len(),
268 y_len: self.y_data.len(),
269 });
270 }
271 if self.x_data.is_empty() {
272 return Err(PlotError::EmptyData);
273 }
274 Ok(())
275 }
276
277 pub fn plot(self) {
279 let Ok(count) = i32::try_from(self.x_data.len()) else {
280 return;
281 };
282 let y_data_f64: Vec<f64> = self
284 .y_data
285 .iter()
286 .map(|&b| if b { 1.0 } else { 0.0 })
287 .collect();
288
289 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
290 sys::ImPlot_PlotDigital_doublePtr(
291 label_ptr,
292 self.x_data.as_ptr(),
293 y_data_f64.as_ptr(),
294 count,
295 self.flags.bits() as i32,
296 0,
297 std::mem::size_of::<f64>() as i32,
298 );
299 })
300 }
301}
302
303impl<'a> PlotData for BooleanDigitalPlot<'a> {
304 fn label(&self) -> &str {
305 self.label
306 }
307
308 fn data_len(&self) -> usize {
309 self.x_data.len().min(self.y_data.len())
310 }
311}