1use super::{PlotData, PlotError, safe_cstring, validate_data_lengths};
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 label_cstring = safe_cstring(self.label);
63
64 unsafe {
65 sys::ImPlot_PlotDigital_doublePtr(
66 label_cstring.as_ptr(),
67 self.x_data.as_ptr(),
68 self.y_data.as_ptr(),
69 self.x_data.len() as i32,
70 self.flags.bits() as i32,
71 self.offset,
72 self.stride,
73 );
74 }
75 }
76}
77
78impl<'a> PlotData for DigitalPlot<'a> {
79 fn label(&self) -> &str {
80 self.label
81 }
82
83 fn data_len(&self) -> usize {
84 self.x_data.len().min(self.y_data.len())
85 }
86}
87
88pub struct DigitalPlotF32<'a> {
90 label: &'a str,
91 x_data: &'a [f32],
92 y_data: &'a [f32],
93 flags: DigitalFlags,
94}
95
96impl<'a> DigitalPlotF32<'a> {
97 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
99 Self {
100 label,
101 x_data,
102 y_data,
103 flags: DigitalFlags::NONE,
104 }
105 }
106
107 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
109 self.flags = flags;
110 self
111 }
112
113 pub fn validate(&self) -> Result<(), PlotError> {
115 if self.x_data.len() != self.y_data.len() {
116 return Err(PlotError::DataLengthMismatch {
117 x_len: self.x_data.len(),
118 y_len: self.y_data.len(),
119 });
120 }
121 if self.x_data.is_empty() {
122 return Err(PlotError::EmptyData);
123 }
124 Ok(())
125 }
126
127 pub fn plot(self) {
129 let label_cstring = safe_cstring(self.label);
130
131 unsafe {
132 sys::ImPlot_PlotDigital_FloatPtr(
133 label_cstring.as_ptr(),
134 self.x_data.as_ptr(),
135 self.y_data.as_ptr(),
136 self.x_data.len() as i32,
137 self.flags.bits() as i32,
138 0,
139 std::mem::size_of::<f32>() as i32,
140 );
141 }
142 }
143}
144
145impl<'a> PlotData for DigitalPlotF32<'a> {
146 fn label(&self) -> &str {
147 self.label
148 }
149
150 fn data_len(&self) -> usize {
151 self.x_data.len().min(self.y_data.len())
152 }
153}
154
155pub struct SimpleDigitalPlot<'a> {
157 label: &'a str,
158 y_data: &'a [f64],
159 flags: DigitalFlags,
160 x_scale: f64,
161 x_start: f64,
162}
163
164impl<'a> SimpleDigitalPlot<'a> {
165 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
167 Self {
168 label,
169 y_data,
170 flags: DigitalFlags::NONE,
171 x_scale: 1.0,
172 x_start: 0.0,
173 }
174 }
175
176 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
178 self.x_scale = x_scale;
179 self
180 }
181
182 pub fn with_x_start(mut self, x_start: f64) -> Self {
184 self.x_start = x_start;
185 self
186 }
187
188 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
190 self.flags = flags;
191 self
192 }
193
194 pub fn validate(&self) -> Result<(), PlotError> {
196 if self.y_data.is_empty() {
197 return Err(PlotError::EmptyData);
198 }
199 Ok(())
200 }
201
202 pub fn plot(self) {
204 let x_data: Vec<f64> = (0..self.y_data.len())
206 .map(|i| self.x_start + i as f64 * self.x_scale)
207 .collect();
208
209 let label_cstring = safe_cstring(self.label);
210
211 unsafe {
212 sys::ImPlot_PlotDigital_doublePtr(
213 label_cstring.as_ptr(),
214 x_data.as_ptr(),
215 self.y_data.as_ptr(),
216 self.y_data.len() as i32,
217 self.flags.bits() as i32,
218 0,
219 std::mem::size_of::<f64>() as i32,
220 );
221 }
222 }
223}
224
225impl<'a> PlotData for SimpleDigitalPlot<'a> {
226 fn label(&self) -> &str {
227 self.label
228 }
229
230 fn data_len(&self) -> usize {
231 self.y_data.len()
232 }
233}
234
235pub struct BooleanDigitalPlot<'a> {
237 label: &'a str,
238 x_data: &'a [f64],
239 y_data: &'a [bool],
240 flags: DigitalFlags,
241}
242
243impl<'a> BooleanDigitalPlot<'a> {
244 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [bool]) -> Self {
246 Self {
247 label,
248 x_data,
249 y_data,
250 flags: DigitalFlags::NONE,
251 }
252 }
253
254 pub fn with_flags(mut self, flags: DigitalFlags) -> Self {
256 self.flags = flags;
257 self
258 }
259
260 pub fn validate(&self) -> Result<(), PlotError> {
262 if self.x_data.len() != self.y_data.len() {
263 return Err(PlotError::DataLengthMismatch {
264 x_len: self.x_data.len(),
265 y_len: self.y_data.len(),
266 });
267 }
268 if self.x_data.is_empty() {
269 return Err(PlotError::EmptyData);
270 }
271 Ok(())
272 }
273
274 pub fn plot(self) {
276 let y_data_f64: Vec<f64> = self
278 .y_data
279 .iter()
280 .map(|&b| if b { 1.0 } else { 0.0 })
281 .collect();
282
283 let label_cstring = safe_cstring(self.label);
284
285 unsafe {
286 sys::ImPlot_PlotDigital_doublePtr(
287 label_cstring.as_ptr(),
288 self.x_data.as_ptr(),
289 y_data_f64.as_ptr(),
290 self.x_data.len() as i32,
291 self.flags.bits() as i32,
292 0,
293 std::mem::size_of::<f64>() as i32,
294 );
295 }
296 }
297}
298
299impl<'a> PlotData for BooleanDigitalPlot<'a> {
300 fn label(&self) -> &str {
301 self.label
302 }
303
304 fn data_len(&self) -> usize {
305 self.x_data.len().min(self.y_data.len())
306 }
307}