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 unsafe fn with_data_layout(mut self, layout: PlotDataLayout) -> Self {
68 self.layout = layout;
69 self
70 }
71
72 pub fn with_offset(mut self, offset: PlotDataOffset) -> Self {
74 self.layout = self.layout.with_offset(offset);
75 self
76 }
77
78 pub unsafe fn with_stride(mut self, stride: PlotDataStride) -> Self {
85 self.layout = self.layout.with_stride(stride);
86 self
87 }
88
89 pub fn validate(&self) -> Result<(), PlotError> {
91 validate_data_lengths(self.x_data, self.y_data)?;
92
93 Ok(())
96 }
97
98 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
100 let Ok(count) = i32::try_from(self.x_data.len()) else {
101 return;
102 };
103 plot_ui.with_bound_context(|| {
104 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
105 let spec = plot_spec_with_style(
106 self.style,
107 self.flags.bits() | self.item_flags.bits(),
108 self.layout,
109 );
110 sys::ImPlot_PlotDigital_doublePtr(
111 label_ptr,
112 self.x_data.as_ptr(),
113 self.y_data.as_ptr(),
114 count,
115 spec,
116 );
117 })
118 })
119 }
120}
121
122impl<'a> PlotData for DigitalPlot<'a> {
123 fn label(&self) -> &str {
124 self.label
125 }
126
127 fn data_len(&self) -> usize {
128 self.x_data.len().min(self.y_data.len())
129 }
130}
131
132pub struct DigitalPlotF32<'a> {
134 label: &'a str,
135 x_data: &'a [f32],
136 y_data: &'a [f32],
137 style: PlotItemStyle,
138 flags: DigitalFlags,
139 item_flags: ItemFlags,
140}
141
142impl<'a> super::PlotItemStyled for DigitalPlotF32<'a> {
143 fn style_mut(&mut self) -> &mut PlotItemStyle {
144 &mut self.style
145 }
146}
147
148impl<'a> DigitalPlotF32<'a> {
149 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
151 Self {
152 label,
153 x_data,
154 y_data,
155 style: PlotItemStyle::default(),
156 flags: DigitalFlags::NONE,
157 item_flags: ItemFlags::NONE,
158 }
159 }
160
161 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
163 self.style = style;
164 self
165 }
166
167 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
169 self.flags = flags;
170 self
171 }
172
173 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
175 self.item_flags = flags;
176 self
177 }
178
179 pub fn validate(&self) -> Result<(), PlotError> {
181 if self.x_data.len() != self.y_data.len() {
182 return Err(PlotError::DataLengthMismatch {
183 x_len: self.x_data.len(),
184 y_len: self.y_data.len(),
185 });
186 }
187 if self.x_data.is_empty() {
188 return Err(PlotError::EmptyData);
189 }
190 Ok(())
191 }
192
193 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
195 let Ok(count) = i32::try_from(self.x_data.len()) else {
196 return;
197 };
198 plot_ui.with_bound_context(|| {
199 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
200 let spec = plot_spec_with_style(
201 self.style,
202 self.flags.bits() | self.item_flags.bits(),
203 PlotDataLayout::DEFAULT,
204 );
205 sys::ImPlot_PlotDigital_FloatPtr(
206 label_ptr,
207 self.x_data.as_ptr(),
208 self.y_data.as_ptr(),
209 count,
210 spec,
211 );
212 })
213 })
214 }
215}
216
217impl<'a> PlotData for DigitalPlotF32<'a> {
218 fn label(&self) -> &str {
219 self.label
220 }
221
222 fn data_len(&self) -> usize {
223 self.x_data.len().min(self.y_data.len())
224 }
225}
226
227pub struct SimpleDigitalPlot<'a> {
229 label: &'a str,
230 y_data: &'a [f64],
231 style: PlotItemStyle,
232 flags: DigitalFlags,
233 item_flags: ItemFlags,
234 x_scale: f64,
235 x_start: f64,
236}
237
238impl<'a> super::PlotItemStyled for SimpleDigitalPlot<'a> {
239 fn style_mut(&mut self) -> &mut PlotItemStyle {
240 &mut self.style
241 }
242}
243
244impl<'a> SimpleDigitalPlot<'a> {
245 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
247 Self {
248 label,
249 y_data,
250 style: PlotItemStyle::default(),
251 flags: DigitalFlags::NONE,
252 item_flags: ItemFlags::NONE,
253 x_scale: 1.0,
254 x_start: 0.0,
255 }
256 }
257
258 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
260 self.x_scale = x_scale;
261 self
262 }
263
264 pub fn with_x_start(mut self, x_start: f64) -> Self {
266 self.x_start = x_start;
267 self
268 }
269
270 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
272 self.flags = flags;
273 self
274 }
275
276 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
278 self.style = style;
279 self
280 }
281
282 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
284 self.item_flags = flags;
285 self
286 }
287
288 pub fn validate(&self) -> Result<(), PlotError> {
290 if self.y_data.is_empty() {
291 return Err(PlotError::EmptyData);
292 }
293 Ok(())
294 }
295
296 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
298 let Ok(count) = i32::try_from(self.y_data.len()) else {
299 return;
300 };
301 let x_data: Vec<f64> = (0..self.y_data.len())
303 .map(|i| self.x_start + i as f64 * self.x_scale)
304 .collect();
305
306 plot_ui.with_bound_context(|| {
307 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
308 let spec = plot_spec_with_style(
309 self.style,
310 self.flags.bits() | self.item_flags.bits(),
311 PlotDataLayout::DEFAULT,
312 );
313 sys::ImPlot_PlotDigital_doublePtr(
314 label_ptr,
315 x_data.as_ptr(),
316 self.y_data.as_ptr(),
317 count,
318 spec,
319 );
320 })
321 })
322 }
323}
324
325impl<'a> PlotData for SimpleDigitalPlot<'a> {
326 fn label(&self) -> &str {
327 self.label
328 }
329
330 fn data_len(&self) -> usize {
331 self.y_data.len()
332 }
333}
334
335pub struct BooleanDigitalPlot<'a> {
337 label: &'a str,
338 x_data: &'a [f64],
339 y_data: &'a [bool],
340 style: PlotItemStyle,
341 flags: DigitalFlags,
342 item_flags: ItemFlags,
343}
344
345impl<'a> super::PlotItemStyled for BooleanDigitalPlot<'a> {
346 fn style_mut(&mut self) -> &mut PlotItemStyle {
347 &mut self.style
348 }
349}
350
351impl<'a> BooleanDigitalPlot<'a> {
352 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [bool]) -> Self {
354 Self {
355 label,
356 x_data,
357 y_data,
358 style: PlotItemStyle::default(),
359 flags: DigitalFlags::NONE,
360 item_flags: ItemFlags::NONE,
361 }
362 }
363
364 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
366 self.style = style;
367 self
368 }
369
370 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
372 self.flags = flags;
373 self
374 }
375
376 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
378 self.item_flags = flags;
379 self
380 }
381
382 pub fn validate(&self) -> Result<(), PlotError> {
384 if self.x_data.len() != self.y_data.len() {
385 return Err(PlotError::DataLengthMismatch {
386 x_len: self.x_data.len(),
387 y_len: self.y_data.len(),
388 });
389 }
390 if self.x_data.is_empty() {
391 return Err(PlotError::EmptyData);
392 }
393 Ok(())
394 }
395
396 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
398 let Ok(count) = i32::try_from(self.x_data.len()) else {
399 return;
400 };
401 let y_data_f64: Vec<f64> = self
403 .y_data
404 .iter()
405 .map(|&b| if b { 1.0 } else { 0.0 })
406 .collect();
407
408 plot_ui.with_bound_context(|| {
409 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
410 let spec = plot_spec_with_style(
411 self.style,
412 self.flags.bits() | self.item_flags.bits(),
413 PlotDataLayout::DEFAULT,
414 );
415 sys::ImPlot_PlotDigital_doublePtr(
416 label_ptr,
417 self.x_data.as_ptr(),
418 y_data_f64.as_ptr(),
419 count,
420 spec,
421 );
422 })
423 })
424 }
425}
426
427impl<'a> PlotData for BooleanDigitalPlot<'a> {
428 fn label(&self) -> &str {
429 self.label
430 }
431
432 fn data_len(&self) -> usize {
433 self.x_data.len().min(self.y_data.len())
434 }
435}