1use super::{PlotData, PlotError, plot_spec_from, validate_data_lengths, with_plot_str_or_empty};
4use crate::{ItemFlags, StairsFlags, sys};
5
6pub struct StairsPlot<'a> {
8 label: &'a str,
9 x_data: &'a [f64],
10 y_data: &'a [f64],
11 flags: StairsFlags,
12 item_flags: ItemFlags,
13 offset: i32,
14 stride: i32,
15}
16
17impl<'a> StairsPlot<'a> {
18 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [f64]) -> Self {
20 Self {
21 label,
22 x_data,
23 y_data,
24 flags: StairsFlags::NONE,
25 item_flags: ItemFlags::NONE,
26 offset: 0,
27 stride: std::mem::size_of::<f64>() as i32,
28 }
29 }
30
31 pub fn with_flags(mut self, flags: StairsFlags) -> Self {
33 self.flags = flags;
34 self
35 }
36
37 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
39 self.item_flags = flags;
40 self
41 }
42
43 pub fn pre_step(mut self) -> Self {
45 self.flags |= StairsFlags::PRE_STEP;
46 self
47 }
48
49 pub fn shaded(mut self) -> Self {
51 self.flags |= StairsFlags::SHADED;
52 self
53 }
54
55 pub fn with_offset(mut self, offset: i32) -> Self {
57 self.offset = offset;
58 self
59 }
60
61 pub fn with_stride(mut self, stride: i32) -> Self {
63 self.stride = stride;
64 self
65 }
66
67 pub fn validate(&self) -> Result<(), PlotError> {
69 validate_data_lengths(self.x_data, self.y_data)
70 }
71
72 pub fn plot(self) {
74 let Ok(count) = i32::try_from(self.x_data.len()) else {
75 return;
76 };
77 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
78 let spec = plot_spec_from(
79 self.flags.bits() | self.item_flags.bits(),
80 self.offset,
81 self.stride,
82 );
83 sys::ImPlot_PlotStairs_doublePtrdoublePtr(
84 label_ptr,
85 self.x_data.as_ptr(),
86 self.y_data.as_ptr(),
87 count,
88 spec,
89 );
90 })
91 }
92}
93
94impl<'a> PlotData for StairsPlot<'a> {
95 fn label(&self) -> &str {
96 self.label
97 }
98
99 fn data_len(&self) -> usize {
100 self.x_data.len().min(self.y_data.len())
101 }
102}
103
104pub struct StairsPlotF32<'a> {
106 label: &'a str,
107 x_data: &'a [f32],
108 y_data: &'a [f32],
109 flags: StairsFlags,
110 item_flags: ItemFlags,
111}
112
113impl<'a> StairsPlotF32<'a> {
114 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
116 Self {
117 label,
118 x_data,
119 y_data,
120 flags: StairsFlags::NONE,
121 item_flags: ItemFlags::NONE,
122 }
123 }
124
125 pub fn with_flags(mut self, flags: StairsFlags) -> Self {
127 self.flags = flags;
128 self
129 }
130
131 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
133 self.item_flags = flags;
134 self
135 }
136
137 pub fn pre_step(mut self) -> Self {
139 self.flags |= StairsFlags::PRE_STEP;
140 self
141 }
142
143 pub fn shaded(mut self) -> Self {
145 self.flags |= StairsFlags::SHADED;
146 self
147 }
148
149 pub fn validate(&self) -> Result<(), PlotError> {
151 if self.x_data.len() != self.y_data.len() {
152 return Err(PlotError::DataLengthMismatch {
153 x_len: self.x_data.len(),
154 y_len: self.y_data.len(),
155 });
156 }
157 if self.x_data.is_empty() {
158 return Err(PlotError::EmptyData);
159 }
160 Ok(())
161 }
162
163 pub fn plot(self) {
165 let Ok(count) = i32::try_from(self.x_data.len()) else {
166 return;
167 };
168 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
169 let spec = plot_spec_from(
170 self.flags.bits() | self.item_flags.bits(),
171 0,
172 std::mem::size_of::<f32>() as i32,
173 );
174 sys::ImPlot_PlotStairs_FloatPtrFloatPtr(
175 label_ptr,
176 self.x_data.as_ptr(),
177 self.y_data.as_ptr(),
178 count,
179 spec,
180 );
181 })
182 }
183}
184
185impl<'a> PlotData for StairsPlotF32<'a> {
186 fn label(&self) -> &str {
187 self.label
188 }
189
190 fn data_len(&self) -> usize {
191 self.x_data.len().min(self.y_data.len())
192 }
193}
194
195pub struct SimpleStairsPlot<'a> {
197 label: &'a str,
198 y_data: &'a [f64],
199 flags: StairsFlags,
200 item_flags: ItemFlags,
201 x_scale: f64,
202 x_start: f64,
203}
204
205impl<'a> SimpleStairsPlot<'a> {
206 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
208 Self {
209 label,
210 y_data,
211 flags: StairsFlags::NONE,
212 item_flags: ItemFlags::NONE,
213 x_scale: 1.0,
214 x_start: 0.0,
215 }
216 }
217
218 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
220 self.x_scale = x_scale;
221 self
222 }
223
224 pub fn with_x_start(mut self, x_start: f64) -> Self {
226 self.x_start = x_start;
227 self
228 }
229
230 pub fn with_flags(mut self, flags: StairsFlags) -> Self {
232 self.flags = flags;
233 self
234 }
235
236 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
238 self.item_flags = flags;
239 self
240 }
241
242 pub fn pre_step(mut self) -> Self {
244 self.flags |= StairsFlags::PRE_STEP;
245 self
246 }
247
248 pub fn shaded(mut self) -> Self {
250 self.flags |= StairsFlags::SHADED;
251 self
252 }
253
254 pub fn validate(&self) -> Result<(), PlotError> {
256 if self.y_data.is_empty() {
257 return Err(PlotError::EmptyData);
258 }
259 Ok(())
260 }
261
262 pub fn plot(self) {
264 let Ok(count) = i32::try_from(self.y_data.len()) else {
265 return;
266 };
267 let x_data: Vec<f64> = (0..self.y_data.len())
269 .map(|i| self.x_start + i as f64 * self.x_scale)
270 .collect();
271
272 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
273 let spec = plot_spec_from(
274 self.flags.bits() | self.item_flags.bits(),
275 0,
276 std::mem::size_of::<f64>() as i32,
277 );
278 sys::ImPlot_PlotStairs_doublePtrdoublePtr(
279 label_ptr,
280 x_data.as_ptr(),
281 self.y_data.as_ptr(),
282 count,
283 spec,
284 );
285 })
286 }
287}
288
289impl<'a> PlotData for SimpleStairsPlot<'a> {
290 fn label(&self) -> &str {
291 self.label
292 }
293
294 fn data_len(&self) -> usize {
295 self.y_data.len()
296 }
297}