1use super::{PlotData, PlotError, plot_spec_from, validate_data_lengths, with_plot_str_or_empty};
4use crate::{DigitalFlags, ItemFlags, sys};
5
6pub struct DigitalPlot<'a> {
11 label: &'a str,
12 x_data: &'a [f64],
13 y_data: &'a [f64],
14 flags: DigitalFlags,
15 item_flags: ItemFlags,
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 item_flags: ItemFlags::NONE,
29 offset: 0,
30 stride: std::mem::size_of::<f64>() as i32,
31 }
32 }
33
34 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
36 self.flags = flags;
37 self
38 }
39
40 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
42 self.item_flags = flags;
43 self
44 }
45
46 pub fn with_offset(mut self, offset: i32) -> Self {
48 self.offset = offset;
49 self
50 }
51
52 pub fn with_stride(mut self, stride: i32) -> Self {
54 self.stride = stride;
55 self
56 }
57
58 pub fn validate(&self) -> Result<(), PlotError> {
60 validate_data_lengths(self.x_data, self.y_data)?;
61
62 Ok(())
65 }
66
67 pub fn plot(self) {
69 let Ok(count) = i32::try_from(self.x_data.len()) else {
70 return;
71 };
72 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
73 let spec = plot_spec_from(
74 self.flags.bits() | self.item_flags.bits(),
75 self.offset,
76 self.stride,
77 );
78 sys::ImPlot_PlotDigital_doublePtr(
79 label_ptr,
80 self.x_data.as_ptr(),
81 self.y_data.as_ptr(),
82 count,
83 spec,
84 );
85 })
86 }
87}
88
89impl<'a> PlotData for DigitalPlot<'a> {
90 fn label(&self) -> &str {
91 self.label
92 }
93
94 fn data_len(&self) -> usize {
95 self.x_data.len().min(self.y_data.len())
96 }
97}
98
99pub struct DigitalPlotF32<'a> {
101 label: &'a str,
102 x_data: &'a [f32],
103 y_data: &'a [f32],
104 flags: DigitalFlags,
105 item_flags: ItemFlags,
106}
107
108impl<'a> DigitalPlotF32<'a> {
109 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
111 Self {
112 label,
113 x_data,
114 y_data,
115 flags: DigitalFlags::NONE,
116 item_flags: ItemFlags::NONE,
117 }
118 }
119
120 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
122 self.flags = flags;
123 self
124 }
125
126 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
128 self.item_flags = flags;
129 self
130 }
131
132 pub fn validate(&self) -> Result<(), PlotError> {
134 if self.x_data.len() != self.y_data.len() {
135 return Err(PlotError::DataLengthMismatch {
136 x_len: self.x_data.len(),
137 y_len: self.y_data.len(),
138 });
139 }
140 if self.x_data.is_empty() {
141 return Err(PlotError::EmptyData);
142 }
143 Ok(())
144 }
145
146 pub fn plot(self) {
148 let Ok(count) = i32::try_from(self.x_data.len()) else {
149 return;
150 };
151 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
152 let spec = plot_spec_from(
153 self.flags.bits() | self.item_flags.bits(),
154 0,
155 std::mem::size_of::<f32>() as i32,
156 );
157 sys::ImPlot_PlotDigital_FloatPtr(
158 label_ptr,
159 self.x_data.as_ptr(),
160 self.y_data.as_ptr(),
161 count,
162 spec,
163 );
164 })
165 }
166}
167
168impl<'a> PlotData for DigitalPlotF32<'a> {
169 fn label(&self) -> &str {
170 self.label
171 }
172
173 fn data_len(&self) -> usize {
174 self.x_data.len().min(self.y_data.len())
175 }
176}
177
178pub struct SimpleDigitalPlot<'a> {
180 label: &'a str,
181 y_data: &'a [f64],
182 flags: DigitalFlags,
183 item_flags: ItemFlags,
184 x_scale: f64,
185 x_start: f64,
186}
187
188impl<'a> SimpleDigitalPlot<'a> {
189 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
191 Self {
192 label,
193 y_data,
194 flags: DigitalFlags::NONE,
195 item_flags: ItemFlags::NONE,
196 x_scale: 1.0,
197 x_start: 0.0,
198 }
199 }
200
201 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
203 self.x_scale = x_scale;
204 self
205 }
206
207 pub fn with_x_start(mut self, x_start: f64) -> Self {
209 self.x_start = x_start;
210 self
211 }
212
213 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
215 self.flags = flags;
216 self
217 }
218
219 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
221 self.item_flags = flags;
222 self
223 }
224
225 pub fn validate(&self) -> Result<(), PlotError> {
227 if self.y_data.is_empty() {
228 return Err(PlotError::EmptyData);
229 }
230 Ok(())
231 }
232
233 pub fn plot(self) {
235 let Ok(count) = i32::try_from(self.y_data.len()) else {
236 return;
237 };
238 let x_data: Vec<f64> = (0..self.y_data.len())
240 .map(|i| self.x_start + i as f64 * self.x_scale)
241 .collect();
242
243 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
244 let spec = plot_spec_from(
245 self.flags.bits() | self.item_flags.bits(),
246 0,
247 std::mem::size_of::<f64>() as i32,
248 );
249 sys::ImPlot_PlotDigital_doublePtr(
250 label_ptr,
251 x_data.as_ptr(),
252 self.y_data.as_ptr(),
253 count,
254 spec,
255 );
256 })
257 }
258}
259
260impl<'a> PlotData for SimpleDigitalPlot<'a> {
261 fn label(&self) -> &str {
262 self.label
263 }
264
265 fn data_len(&self) -> usize {
266 self.y_data.len()
267 }
268}
269
270pub struct BooleanDigitalPlot<'a> {
272 label: &'a str,
273 x_data: &'a [f64],
274 y_data: &'a [bool],
275 flags: DigitalFlags,
276 item_flags: ItemFlags,
277}
278
279impl<'a> BooleanDigitalPlot<'a> {
280 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [bool]) -> Self {
282 Self {
283 label,
284 x_data,
285 y_data,
286 flags: DigitalFlags::NONE,
287 item_flags: ItemFlags::NONE,
288 }
289 }
290
291 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
293 self.flags = flags;
294 self
295 }
296
297 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
299 self.item_flags = flags;
300 self
301 }
302
303 pub fn validate(&self) -> Result<(), PlotError> {
305 if self.x_data.len() != self.y_data.len() {
306 return Err(PlotError::DataLengthMismatch {
307 x_len: self.x_data.len(),
308 y_len: self.y_data.len(),
309 });
310 }
311 if self.x_data.is_empty() {
312 return Err(PlotError::EmptyData);
313 }
314 Ok(())
315 }
316
317 pub fn plot(self) {
319 let Ok(count) = i32::try_from(self.x_data.len()) else {
320 return;
321 };
322 let y_data_f64: Vec<f64> = self
324 .y_data
325 .iter()
326 .map(|&b| if b { 1.0 } else { 0.0 })
327 .collect();
328
329 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
330 let spec = plot_spec_from(
331 self.flags.bits() | self.item_flags.bits(),
332 0,
333 std::mem::size_of::<f64>() as i32,
334 );
335 sys::ImPlot_PlotDigital_doublePtr(
336 label_ptr,
337 self.x_data.as_ptr(),
338 y_data_f64.as_ptr(),
339 count,
340 spec,
341 );
342 })
343 }
344}
345
346impl<'a> PlotData for BooleanDigitalPlot<'a> {
347 fn label(&self) -> &str {
348 self.label
349 }
350
351 fn data_len(&self) -> usize {
352 self.x_data.len().min(self.y_data.len())
353 }
354}