1use super::{
4 PlotData, PlotError, PlotItemStyle, plot_spec_with_style, validate_data_lengths,
5 with_plot_str_or_empty,
6};
7use crate::{DigitalFlags, ItemFlags, sys};
8
9pub struct DigitalPlot<'a> {
14 label: &'a str,
15 x_data: &'a [f64],
16 y_data: &'a [f64],
17 style: PlotItemStyle,
18 flags: DigitalFlags,
19 item_flags: ItemFlags,
20 offset: i32,
21 stride: i32,
22}
23
24impl<'a> super::PlotItemStyled for DigitalPlot<'a> {
25 fn style_mut(&mut self) -> &mut PlotItemStyle {
26 &mut self.style
27 }
28}
29
30impl<'a> DigitalPlot<'a> {
31 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [f64]) -> Self {
33 Self {
34 label,
35 x_data,
36 y_data,
37 style: PlotItemStyle::default(),
38 flags: DigitalFlags::NONE,
39 item_flags: ItemFlags::NONE,
40 offset: 0,
41 stride: std::mem::size_of::<f64>() as i32,
42 }
43 }
44
45 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
47 self.flags = flags;
48 self
49 }
50
51 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
53 self.style = style;
54 self
55 }
56
57 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
59 self.item_flags = flags;
60 self
61 }
62
63 pub fn with_offset(mut self, offset: i32) -> Self {
65 self.offset = offset;
66 self
67 }
68
69 pub fn with_stride(mut self, stride: i32) -> Self {
71 self.stride = stride;
72 self
73 }
74
75 pub fn validate(&self) -> Result<(), PlotError> {
77 validate_data_lengths(self.x_data, self.y_data)?;
78
79 Ok(())
82 }
83
84 pub fn plot(self) {
86 let Ok(count) = i32::try_from(self.x_data.len()) else {
87 return;
88 };
89 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
90 let spec = plot_spec_with_style(
91 self.style,
92 self.flags.bits() | self.item_flags.bits(),
93 self.offset,
94 self.stride,
95 );
96 sys::ImPlot_PlotDigital_doublePtr(
97 label_ptr,
98 self.x_data.as_ptr(),
99 self.y_data.as_ptr(),
100 count,
101 spec,
102 );
103 })
104 }
105}
106
107impl<'a> PlotData for DigitalPlot<'a> {
108 fn label(&self) -> &str {
109 self.label
110 }
111
112 fn data_len(&self) -> usize {
113 self.x_data.len().min(self.y_data.len())
114 }
115}
116
117pub struct DigitalPlotF32<'a> {
119 label: &'a str,
120 x_data: &'a [f32],
121 y_data: &'a [f32],
122 style: PlotItemStyle,
123 flags: DigitalFlags,
124 item_flags: ItemFlags,
125}
126
127impl<'a> super::PlotItemStyled for DigitalPlotF32<'a> {
128 fn style_mut(&mut self) -> &mut PlotItemStyle {
129 &mut self.style
130 }
131}
132
133impl<'a> DigitalPlotF32<'a> {
134 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
136 Self {
137 label,
138 x_data,
139 y_data,
140 style: PlotItemStyle::default(),
141 flags: DigitalFlags::NONE,
142 item_flags: ItemFlags::NONE,
143 }
144 }
145
146 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
148 self.style = style;
149 self
150 }
151
152 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
154 self.flags = flags;
155 self
156 }
157
158 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
160 self.item_flags = flags;
161 self
162 }
163
164 pub fn validate(&self) -> Result<(), PlotError> {
166 if self.x_data.len() != self.y_data.len() {
167 return Err(PlotError::DataLengthMismatch {
168 x_len: self.x_data.len(),
169 y_len: self.y_data.len(),
170 });
171 }
172 if self.x_data.is_empty() {
173 return Err(PlotError::EmptyData);
174 }
175 Ok(())
176 }
177
178 pub fn plot(self) {
180 let Ok(count) = i32::try_from(self.x_data.len()) else {
181 return;
182 };
183 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
184 let spec = plot_spec_with_style(
185 self.style,
186 self.flags.bits() | self.item_flags.bits(),
187 0,
188 std::mem::size_of::<f32>() as i32,
189 );
190 sys::ImPlot_PlotDigital_FloatPtr(
191 label_ptr,
192 self.x_data.as_ptr(),
193 self.y_data.as_ptr(),
194 count,
195 spec,
196 );
197 })
198 }
199}
200
201impl<'a> PlotData for DigitalPlotF32<'a> {
202 fn label(&self) -> &str {
203 self.label
204 }
205
206 fn data_len(&self) -> usize {
207 self.x_data.len().min(self.y_data.len())
208 }
209}
210
211pub struct SimpleDigitalPlot<'a> {
213 label: &'a str,
214 y_data: &'a [f64],
215 style: PlotItemStyle,
216 flags: DigitalFlags,
217 item_flags: ItemFlags,
218 x_scale: f64,
219 x_start: f64,
220}
221
222impl<'a> super::PlotItemStyled for SimpleDigitalPlot<'a> {
223 fn style_mut(&mut self) -> &mut PlotItemStyle {
224 &mut self.style
225 }
226}
227
228impl<'a> SimpleDigitalPlot<'a> {
229 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
231 Self {
232 label,
233 y_data,
234 style: PlotItemStyle::default(),
235 flags: DigitalFlags::NONE,
236 item_flags: ItemFlags::NONE,
237 x_scale: 1.0,
238 x_start: 0.0,
239 }
240 }
241
242 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
244 self.x_scale = x_scale;
245 self
246 }
247
248 pub fn with_x_start(mut self, x_start: f64) -> Self {
250 self.x_start = x_start;
251 self
252 }
253
254 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
256 self.flags = flags;
257 self
258 }
259
260 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
262 self.style = style;
263 self
264 }
265
266 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
268 self.item_flags = flags;
269 self
270 }
271
272 pub fn validate(&self) -> Result<(), PlotError> {
274 if self.y_data.is_empty() {
275 return Err(PlotError::EmptyData);
276 }
277 Ok(())
278 }
279
280 pub fn plot(self) {
282 let Ok(count) = i32::try_from(self.y_data.len()) else {
283 return;
284 };
285 let x_data: Vec<f64> = (0..self.y_data.len())
287 .map(|i| self.x_start + i as f64 * self.x_scale)
288 .collect();
289
290 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
291 let spec = plot_spec_with_style(
292 self.style,
293 self.flags.bits() | self.item_flags.bits(),
294 0,
295 std::mem::size_of::<f64>() as i32,
296 );
297 sys::ImPlot_PlotDigital_doublePtr(
298 label_ptr,
299 x_data.as_ptr(),
300 self.y_data.as_ptr(),
301 count,
302 spec,
303 );
304 })
305 }
306}
307
308impl<'a> PlotData for SimpleDigitalPlot<'a> {
309 fn label(&self) -> &str {
310 self.label
311 }
312
313 fn data_len(&self) -> usize {
314 self.y_data.len()
315 }
316}
317
318pub struct BooleanDigitalPlot<'a> {
320 label: &'a str,
321 x_data: &'a [f64],
322 y_data: &'a [bool],
323 style: PlotItemStyle,
324 flags: DigitalFlags,
325 item_flags: ItemFlags,
326}
327
328impl<'a> super::PlotItemStyled for BooleanDigitalPlot<'a> {
329 fn style_mut(&mut self) -> &mut PlotItemStyle {
330 &mut self.style
331 }
332}
333
334impl<'a> BooleanDigitalPlot<'a> {
335 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [bool]) -> Self {
337 Self {
338 label,
339 x_data,
340 y_data,
341 style: PlotItemStyle::default(),
342 flags: DigitalFlags::NONE,
343 item_flags: ItemFlags::NONE,
344 }
345 }
346
347 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
349 self.style = style;
350 self
351 }
352
353 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
355 self.flags = flags;
356 self
357 }
358
359 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
361 self.item_flags = flags;
362 self
363 }
364
365 pub fn validate(&self) -> Result<(), PlotError> {
367 if self.x_data.len() != self.y_data.len() {
368 return Err(PlotError::DataLengthMismatch {
369 x_len: self.x_data.len(),
370 y_len: self.y_data.len(),
371 });
372 }
373 if self.x_data.is_empty() {
374 return Err(PlotError::EmptyData);
375 }
376 Ok(())
377 }
378
379 pub fn plot(self) {
381 let Ok(count) = i32::try_from(self.x_data.len()) else {
382 return;
383 };
384 let y_data_f64: Vec<f64> = self
386 .y_data
387 .iter()
388 .map(|&b| if b { 1.0 } else { 0.0 })
389 .collect();
390
391 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
392 let spec = plot_spec_with_style(
393 self.style,
394 self.flags.bits() | self.item_flags.bits(),
395 0,
396 std::mem::size_of::<f64>() as i32,
397 );
398 sys::ImPlot_PlotDigital_doublePtr(
399 label_ptr,
400 self.x_data.as_ptr(),
401 y_data_f64.as_ptr(),
402 count,
403 spec,
404 );
405 })
406 }
407}
408
409impl<'a> PlotData for BooleanDigitalPlot<'a> {
410 fn label(&self) -> &str {
411 self.label
412 }
413
414 fn data_len(&self) -> usize {
415 self.x_data.len().min(self.y_data.len())
416 }
417}