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 fn with_data_layout(mut self, layout: PlotDataLayout) -> Self {
66 self.layout = layout;
67 self
68 }
69
70 pub fn with_offset(mut self, offset: PlotDataOffset) -> Self {
72 self.layout = self.layout.with_offset(offset);
73 self
74 }
75
76 pub fn with_stride(mut self, stride: PlotDataStride) -> Self {
78 self.layout = self.layout.with_stride(stride);
79 self
80 }
81
82 pub fn validate(&self) -> Result<(), PlotError> {
84 validate_data_lengths(self.x_data, self.y_data)
85 }
86
87 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
89 let Ok(count) = i32::try_from(self.x_data.len()) else {
90 return;
91 };
92 let _guard = plot_ui.bind();
93 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
94 let spec = plot_spec_with_style(
95 self.style,
96 self.flags.bits() | self.item_flags.bits(),
97 self.layout,
98 );
99 sys::ImPlot_PlotStairs_doublePtrdoublePtr(
100 label_ptr,
101 self.x_data.as_ptr(),
102 self.y_data.as_ptr(),
103 count,
104 spec,
105 );
106 })
107 }
108}
109
110impl<'a> PlotData for StairsPlot<'a> {
111 fn label(&self) -> &str {
112 self.label
113 }
114
115 fn data_len(&self) -> usize {
116 self.x_data.len().min(self.y_data.len())
117 }
118}
119
120pub struct StairsPlotF32<'a> {
122 label: &'a str,
123 x_data: &'a [f32],
124 y_data: &'a [f32],
125 style: PlotItemStyle,
126 flags: StairsFlags,
127 item_flags: ItemFlags,
128}
129
130impl<'a> super::PlotItemStyled for StairsPlotF32<'a> {
131 fn style_mut(&mut self) -> &mut PlotItemStyle {
132 &mut self.style
133 }
134}
135
136impl<'a> StairsPlotF32<'a> {
137 pub fn new(label: &'a str, x_data: &'a [f32], y_data: &'a [f32]) -> Self {
139 Self {
140 label,
141 x_data,
142 y_data,
143 style: PlotItemStyle::default(),
144 flags: StairsFlags::NONE,
145 item_flags: ItemFlags::NONE,
146 }
147 }
148
149 pub fn with_flags(mut self, flags: StairsFlags) -> Self {
151 self.flags = flags;
152 self
153 }
154
155 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
157 self.item_flags = flags;
158 self
159 }
160
161 pub fn pre_step(mut self) -> Self {
163 self.flags |= StairsFlags::PRE_STEP;
164 self
165 }
166
167 pub fn shaded(mut self) -> Self {
169 self.flags |= StairsFlags::SHADED;
170 self
171 }
172
173 pub fn validate(&self) -> Result<(), PlotError> {
175 if self.x_data.len() != self.y_data.len() {
176 return Err(PlotError::DataLengthMismatch {
177 x_len: self.x_data.len(),
178 y_len: self.y_data.len(),
179 });
180 }
181 if self.x_data.is_empty() {
182 return Err(PlotError::EmptyData);
183 }
184 Ok(())
185 }
186
187 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
189 let Ok(count) = i32::try_from(self.x_data.len()) else {
190 return;
191 };
192 let _guard = plot_ui.bind();
193 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
194 let spec = plot_spec_with_style(
195 self.style,
196 self.flags.bits() | self.item_flags.bits(),
197 PlotDataLayout::DEFAULT,
198 );
199 sys::ImPlot_PlotStairs_FloatPtrFloatPtr(
200 label_ptr,
201 self.x_data.as_ptr(),
202 self.y_data.as_ptr(),
203 count,
204 spec,
205 );
206 })
207 }
208}
209
210impl<'a> PlotData for StairsPlotF32<'a> {
211 fn label(&self) -> &str {
212 self.label
213 }
214
215 fn data_len(&self) -> usize {
216 self.x_data.len().min(self.y_data.len())
217 }
218}
219
220pub struct SimpleStairsPlot<'a> {
222 label: &'a str,
223 y_data: &'a [f64],
224 style: PlotItemStyle,
225 flags: StairsFlags,
226 item_flags: ItemFlags,
227 x_scale: f64,
228 x_start: f64,
229}
230
231impl<'a> super::PlotItemStyled for SimpleStairsPlot<'a> {
232 fn style_mut(&mut self) -> &mut PlotItemStyle {
233 &mut self.style
234 }
235}
236
237impl<'a> SimpleStairsPlot<'a> {
238 pub fn new(label: &'a str, y_data: &'a [f64]) -> Self {
240 Self {
241 label,
242 y_data,
243 style: PlotItemStyle::default(),
244 flags: StairsFlags::NONE,
245 item_flags: ItemFlags::NONE,
246 x_scale: 1.0,
247 x_start: 0.0,
248 }
249 }
250
251 pub fn with_x_scale(mut self, x_scale: f64) -> Self {
253 self.x_scale = x_scale;
254 self
255 }
256
257 pub fn with_x_start(mut self, x_start: f64) -> Self {
259 self.x_start = x_start;
260 self
261 }
262
263 pub fn with_flags(mut self, flags: StairsFlags) -> Self {
265 self.flags = flags;
266 self
267 }
268
269 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
271 self.item_flags = flags;
272 self
273 }
274
275 pub fn pre_step(mut self) -> Self {
277 self.flags |= StairsFlags::PRE_STEP;
278 self
279 }
280
281 pub fn shaded(mut self) -> Self {
283 self.flags |= StairsFlags::SHADED;
284 self
285 }
286
287 pub fn validate(&self) -> Result<(), PlotError> {
289 if self.y_data.is_empty() {
290 return Err(PlotError::EmptyData);
291 }
292 Ok(())
293 }
294
295 pub fn plot(self, plot_ui: &crate::PlotUi<'_>) {
297 let Ok(count) = i32::try_from(self.y_data.len()) else {
298 return;
299 };
300 let _guard = plot_ui.bind();
301 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
302 let spec = plot_spec_with_style(
303 self.style,
304 self.flags.bits() | self.item_flags.bits(),
305 PlotDataLayout::DEFAULT,
306 );
307 sys::ImPlot_PlotStairs_doublePtrInt(
308 label_ptr,
309 self.y_data.as_ptr(),
310 count,
311 self.x_scale,
312 self.x_start,
313 spec,
314 );
315 })
316 }
317}
318
319impl<'a> PlotData for SimpleStairsPlot<'a> {
320 fn label(&self) -> &str {
321 self.label
322 }
323
324 fn data_len(&self) -> usize {
325 self.y_data.len()
326 }
327}