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::{ItemFlags, StairsFlags, sys};
8
9pub struct StairsPlot<'a> {
11 label: &'a str,
12 x_data: &'a [f64],
13 y_data: &'a [f64],
14 style: PlotItemStyle,
15 flags: StairsFlags,
16 item_flags: ItemFlags,
17 layout: PlotDataLayout,
18}
19
20impl<'a> super::PlotItemStyled for StairsPlot<'a> {
21 fn style_mut(&mut self) -> &mut PlotItemStyle {
22 &mut self.style
23 }
24}
25
26impl<'a> StairsPlot<'a> {
27 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [f64]) -> Self {
29 Self {
30 label,
31 x_data,
32 y_data,
33 style: PlotItemStyle::default(),
34 flags: StairsFlags::NONE,
35 item_flags: ItemFlags::NONE,
36 layout: PlotDataLayout::DEFAULT,
37 }
38 }
39
40 pub fn with_flags(mut self, flags: StairsFlags) -> Self {
42 self.flags = flags;
43 self
44 }
45
46 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
48 self.item_flags = flags;
49 self
50 }
51
52 pub fn pre_step(mut self) -> Self {
54 self.flags |= StairsFlags::PRE_STEP;
55 self
56 }
57
58 pub fn shaded(mut self) -> Self {
60 self.flags |= StairsFlags::SHADED;
61 self
62 }
63
64 pub unsafe fn with_data_layout(mut self, layout: PlotDataLayout) -> Self {
71 self.layout = layout;
72 self
73 }
74
75 pub fn with_offset(mut self, offset: PlotDataOffset) -> Self {
77 self.layout = self.layout.with_offset(offset);
78 self
79 }
80
81 pub unsafe fn with_stride(mut self, stride: PlotDataStride) -> Self {
88 self.layout = self.layout.with_stride(stride);
89 self
90 }
91
92 pub fn validate(&self) -> Result<(), PlotError> {
94 validate_data_lengths(self.x_data, self.y_data)
95 }
96
97 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
99 let Ok(count) = i32::try_from(self.x_data.len()) else {
100 return;
101 };
102 plot_ui.with_bound_context(|| {
103 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
104 let spec = plot_spec_with_style(
105 self.style,
106 self.flags.bits() | self.item_flags.bits(),
107 self.layout,
108 );
109 sys::ImPlot_PlotStairs_doublePtrdoublePtr(
110 label_ptr,
111 self.x_data.as_ptr(),
112 self.y_data.as_ptr(),
113 count,
114 spec,
115 );
116 })
117 })
118 }
119}
120
121impl<'a> PlotData for StairsPlot<'a> {
122 fn label(&self) -> &str {
123 self.label
124 }
125
126 fn data_len(&self) -> usize {
127 self.x_data.len().min(self.y_data.len())
128 }
129}
130
131pub struct StairsPlotF32<'a> {
133 label: &'a str,
134 x_data: &'a [f32],
135 y_data: &'a [f32],
136 style: PlotItemStyle,
137 flags: StairsFlags,
138 item_flags: ItemFlags,
139}
140
141impl<'a> super::PlotItemStyled for StairsPlotF32<'a> {
142 fn style_mut(&mut self) -> &mut PlotItemStyle {
143 &mut self.style
144 }
145}
146
147impl<'a> StairsPlotF32<'a> {
148 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
150 Self {
151 label,
152 x_data,
153 y_data,
154 style: PlotItemStyle::default(),
155 flags: StairsFlags::NONE,
156 item_flags: ItemFlags::NONE,
157 }
158 }
159
160 pub fn with_flags(mut self, flags: StairsFlags) -> Self {
162 self.flags = flags;
163 self
164 }
165
166 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
168 self.item_flags = flags;
169 self
170 }
171
172 pub fn pre_step(mut self) -> Self {
174 self.flags |= StairsFlags::PRE_STEP;
175 self
176 }
177
178 pub fn shaded(mut self) -> Self {
180 self.flags |= StairsFlags::SHADED;
181 self
182 }
183
184 pub fn validate(&self) -> Result<(), PlotError> {
186 if self.x_data.len() != self.y_data.len() {
187 return Err(PlotError::DataLengthMismatch {
188 x_len: self.x_data.len(),
189 y_len: self.y_data.len(),
190 });
191 }
192 if self.x_data.is_empty() {
193 return Err(PlotError::EmptyData);
194 }
195 Ok(())
196 }
197
198 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
200 let Ok(count) = i32::try_from(self.x_data.len()) else {
201 return;
202 };
203 plot_ui.with_bound_context(|| {
204 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
205 let spec = plot_spec_with_style(
206 self.style,
207 self.flags.bits() | self.item_flags.bits(),
208 PlotDataLayout::DEFAULT,
209 );
210 sys::ImPlot_PlotStairs_FloatPtrFloatPtr(
211 label_ptr,
212 self.x_data.as_ptr(),
213 self.y_data.as_ptr(),
214 count,
215 spec,
216 );
217 })
218 })
219 }
220}
221
222impl<'a> PlotData for StairsPlotF32<'a> {
223 fn label(&self) -> &str {
224 self.label
225 }
226
227 fn data_len(&self) -> usize {
228 self.x_data.len().min(self.y_data.len())
229 }
230}
231
232pub struct SimpleStairsPlot<'a> {
234 label: &'a str,
235 y_data: &'a [f64],
236 style: PlotItemStyle,
237 flags: StairsFlags,
238 item_flags: ItemFlags,
239 x_scale: f64,
240 x_start: f64,
241}
242
243impl<'a> super::PlotItemStyled for SimpleStairsPlot<'a> {
244 fn style_mut(&mut self) -> &mut PlotItemStyle {
245 &mut self.style
246 }
247}
248
249impl<'a> SimpleStairsPlot<'a> {
250 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
252 Self {
253 label,
254 y_data,
255 style: PlotItemStyle::default(),
256 flags: StairsFlags::NONE,
257 item_flags: ItemFlags::NONE,
258 x_scale: 1.0,
259 x_start: 0.0,
260 }
261 }
262
263 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
265 self.x_scale = x_scale;
266 self
267 }
268
269 pub fn with_x_start(mut self, x_start: f64) -> Self {
271 self.x_start = x_start;
272 self
273 }
274
275 pub fn with_flags(mut self, flags: StairsFlags) -> Self {
277 self.flags = flags;
278 self
279 }
280
281 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
283 self.item_flags = flags;
284 self
285 }
286
287 pub fn pre_step(mut self) -> Self {
289 self.flags |= StairsFlags::PRE_STEP;
290 self
291 }
292
293 pub fn shaded(mut self) -> Self {
295 self.flags |= StairsFlags::SHADED;
296 self
297 }
298
299 pub fn validate(&self) -> Result<(), PlotError> {
301 if self.y_data.is_empty() {
302 return Err(PlotError::EmptyData);
303 }
304 Ok(())
305 }
306
307 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
309 let Ok(count) = i32::try_from(self.y_data.len()) else {
310 return;
311 };
312 plot_ui.with_bound_context(|| {
313 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
314 let spec = plot_spec_with_style(
315 self.style,
316 self.flags.bits() | self.item_flags.bits(),
317 PlotDataLayout::DEFAULT,
318 );
319 sys::ImPlot_PlotStairs_doublePtrInt(
320 label_ptr,
321 self.y_data.as_ptr(),
322 count,
323 self.x_scale,
324 self.x_start,
325 spec,
326 );
327 })
328 })
329 }
330}
331
332impl<'a> PlotData for SimpleStairsPlot<'a> {
333 fn label(&self) -> &str {
334 self.label
335 }
336
337 fn data_len(&self) -> usize {
338 self.y_data.len()
339 }
340}