1use super::{
4 PlotData, PlotDataLayout, PlotDataOffset, PlotDataStride, PlotError, PlotItemStyle,
5 plot_spec_with_style, validate_data_lengths, 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 layout: PlotDataLayout,
21}
22
23impl<'a> super::PlotItemStyled for DigitalPlot<'a> {
24 fn style_mut(&mut self) -> &mut PlotItemStyle {
25 &mut self.style
26 }
27}
28
29impl<'a> DigitalPlot<'a> {
30 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [f64]) -> Self {
32 Self {
33 label,
34 x_data,
35 y_data,
36 style: PlotItemStyle::default(),
37 flags: DigitalFlags::NONE,
38 item_flags: ItemFlags::NONE,
39 layout: PlotDataLayout::DEFAULT,
40 }
41 }
42
43 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
45 self.flags = flags;
46 self
47 }
48
49 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
51 self.style = style;
52 self
53 }
54
55 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
57 self.item_flags = flags;
58 self
59 }
60
61 pub fn with_data_layout(mut self, layout: PlotDataLayout) -> Self {
63 self.layout = layout;
64 self
65 }
66
67 pub fn with_offset(mut self, offset: PlotDataOffset) -> Self {
69 self.layout = self.layout.with_offset(offset);
70 self
71 }
72
73 pub fn with_stride(mut self, stride: PlotDataStride) -> Self {
75 self.layout = self.layout.with_stride(stride);
76 self
77 }
78
79 pub fn validate(&self) -> Result<(), PlotError> {
81 validate_data_lengths(self.x_data, self.y_data)?;
82
83 Ok(())
86 }
87
88 pub fn plot(self) {
90 let Ok(count) = i32::try_from(self.x_data.len()) else {
91 return;
92 };
93 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
94 let spec = plot_spec_with_style(
95 self.style,
96 self.flags.bits() | self.item_flags.bits(),
97 self.layout,
98 );
99 sys::ImPlot_PlotDigital_doublePtr(
100 label_ptr,
101 self.x_data.as_ptr(),
102 self.y_data.as_ptr(),
103 count,
104 spec,
105 );
106 })
107 }
108}
109
110impl<'a> PlotData for DigitalPlot<'a> {
111 fn label(&self) -> &str {
112 self.label
113 }
114
115 fn data_len(&self) -> usize {
116 self.x_data.len().min(self.y_data.len())
117 }
118}
119
120pub struct DigitalPlotF32<'a> {
122 label: &'a str,
123 x_data: &'a [f32],
124 y_data: &'a [f32],
125 style: PlotItemStyle,
126 flags: DigitalFlags,
127 item_flags: ItemFlags,
128}
129
130impl<'a> super::PlotItemStyled for DigitalPlotF32<'a> {
131 fn style_mut(&mut self) -> &mut PlotItemStyle {
132 &mut self.style
133 }
134}
135
136impl<'a> DigitalPlotF32<'a> {
137 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
139 Self {
140 label,
141 x_data,
142 y_data,
143 style: PlotItemStyle::default(),
144 flags: DigitalFlags::NONE,
145 item_flags: ItemFlags::NONE,
146 }
147 }
148
149 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
151 self.style = style;
152 self
153 }
154
155 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
157 self.flags = flags;
158 self
159 }
160
161 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
163 self.item_flags = flags;
164 self
165 }
166
167 pub fn validate(&self) -> Result<(), PlotError> {
169 if self.x_data.len() != self.y_data.len() {
170 return Err(PlotError::DataLengthMismatch {
171 x_len: self.x_data.len(),
172 y_len: self.y_data.len(),
173 });
174 }
175 if self.x_data.is_empty() {
176 return Err(PlotError::EmptyData);
177 }
178 Ok(())
179 }
180
181 pub fn plot(self) {
183 let Ok(count) = i32::try_from(self.x_data.len()) else {
184 return;
185 };
186 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
187 let spec = plot_spec_with_style(
188 self.style,
189 self.flags.bits() | self.item_flags.bits(),
190 PlotDataLayout::DEFAULT,
191 );
192 sys::ImPlot_PlotDigital_FloatPtr(
193 label_ptr,
194 self.x_data.as_ptr(),
195 self.y_data.as_ptr(),
196 count,
197 spec,
198 );
199 })
200 }
201}
202
203impl<'a> PlotData for DigitalPlotF32<'a> {
204 fn label(&self) -> &str {
205 self.label
206 }
207
208 fn data_len(&self) -> usize {
209 self.x_data.len().min(self.y_data.len())
210 }
211}
212
213pub struct SimpleDigitalPlot<'a> {
215 label: &'a str,
216 y_data: &'a [f64],
217 style: PlotItemStyle,
218 flags: DigitalFlags,
219 item_flags: ItemFlags,
220 x_scale: f64,
221 x_start: f64,
222}
223
224impl<'a> super::PlotItemStyled for SimpleDigitalPlot<'a> {
225 fn style_mut(&mut self) -> &mut PlotItemStyle {
226 &mut self.style
227 }
228}
229
230impl<'a> SimpleDigitalPlot<'a> {
231 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
233 Self {
234 label,
235 y_data,
236 style: PlotItemStyle::default(),
237 flags: DigitalFlags::NONE,
238 item_flags: ItemFlags::NONE,
239 x_scale: 1.0,
240 x_start: 0.0,
241 }
242 }
243
244 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
246 self.x_scale = x_scale;
247 self
248 }
249
250 pub fn with_x_start(mut self, x_start: f64) -> Self {
252 self.x_start = x_start;
253 self
254 }
255
256 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
258 self.flags = flags;
259 self
260 }
261
262 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
264 self.style = style;
265 self
266 }
267
268 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
270 self.item_flags = flags;
271 self
272 }
273
274 pub fn validate(&self) -> Result<(), PlotError> {
276 if self.y_data.is_empty() {
277 return Err(PlotError::EmptyData);
278 }
279 Ok(())
280 }
281
282 pub fn plot(self) {
284 let Ok(count) = i32::try_from(self.y_data.len()) else {
285 return;
286 };
287 let x_data: Vec<f64> = (0..self.y_data.len())
289 .map(|i| self.x_start + i as f64 * self.x_scale)
290 .collect();
291
292 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
293 let spec = plot_spec_with_style(
294 self.style,
295 self.flags.bits() | self.item_flags.bits(),
296 PlotDataLayout::DEFAULT,
297 );
298 sys::ImPlot_PlotDigital_doublePtr(
299 label_ptr,
300 x_data.as_ptr(),
301 self.y_data.as_ptr(),
302 count,
303 spec,
304 );
305 })
306 }
307}
308
309impl<'a> PlotData for SimpleDigitalPlot<'a> {
310 fn label(&self) -> &str {
311 self.label
312 }
313
314 fn data_len(&self) -> usize {
315 self.y_data.len()
316 }
317}
318
319pub struct BooleanDigitalPlot<'a> {
321 label: &'a str,
322 x_data: &'a [f64],
323 y_data: &'a [bool],
324 style: PlotItemStyle,
325 flags: DigitalFlags,
326 item_flags: ItemFlags,
327}
328
329impl<'a> super::PlotItemStyled for BooleanDigitalPlot<'a> {
330 fn style_mut(&mut self) -> &mut PlotItemStyle {
331 &mut self.style
332 }
333}
334
335impl<'a> BooleanDigitalPlot<'a> {
336 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [bool]) -> Self {
338 Self {
339 label,
340 x_data,
341 y_data,
342 style: PlotItemStyle::default(),
343 flags: DigitalFlags::NONE,
344 item_flags: ItemFlags::NONE,
345 }
346 }
347
348 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
350 self.style = style;
351 self
352 }
353
354 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
356 self.flags = flags;
357 self
358 }
359
360 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
362 self.item_flags = flags;
363 self
364 }
365
366 pub fn validate(&self) -> Result<(), PlotError> {
368 if self.x_data.len() != self.y_data.len() {
369 return Err(PlotError::DataLengthMismatch {
370 x_len: self.x_data.len(),
371 y_len: self.y_data.len(),
372 });
373 }
374 if self.x_data.is_empty() {
375 return Err(PlotError::EmptyData);
376 }
377 Ok(())
378 }
379
380 pub fn plot(self) {
382 let Ok(count) = i32::try_from(self.x_data.len()) else {
383 return;
384 };
385 let y_data_f64: Vec<f64> = self
387 .y_data
388 .iter()
389 .map(|&b| if b { 1.0 } else { 0.0 })
390 .collect();
391
392 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
393 let spec = plot_spec_with_style(
394 self.style,
395 self.flags.bits() | self.item_flags.bits(),
396 PlotDataLayout::DEFAULT,
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}