1use super::ui::PlotUi;
2use super::validation::{
3 assert_axis_constraint_range, assert_axis_limit_range, assert_axis_zoom_range,
4 assert_finite_f64_slice, axis_tick_count_to_i32,
5};
6use crate::{Axis, AxisFlags, PlotCond, XAxis, YAxis, sys};
7use dear_imgui_rs::{with_scratch_txt, with_scratch_txt_slice, with_scratch_txt_two};
8use std::os::raw::c_char;
9
10impl<'ui> PlotUi<'ui> {
11 pub fn setup_x_axis(&self, axis: XAxis, label: Option<&str>, flags: AxisFlags) {
13 let _guard = self.bind();
14 let label = label.filter(|s| !s.contains('\0'));
15 match label {
16 Some(label) => with_scratch_txt(label, |ptr| unsafe {
17 sys::ImPlot_SetupAxis(
18 axis as sys::ImAxis,
19 ptr,
20 flags.bits() as sys::ImPlotAxisFlags,
21 )
22 }),
23 None => unsafe {
24 sys::ImPlot_SetupAxis(
25 axis as sys::ImAxis,
26 std::ptr::null(),
27 flags.bits() as sys::ImPlotAxisFlags,
28 )
29 },
30 }
31 }
32
33 pub fn setup_y_axis(&self, axis: YAxis, label: Option<&str>, flags: AxisFlags) {
35 let _guard = self.bind();
36 let label = label.filter(|s| !s.contains('\0'));
37 match label {
38 Some(label) => with_scratch_txt(label, |ptr| unsafe {
39 sys::ImPlot_SetupAxis(
40 axis as sys::ImAxis,
41 ptr,
42 flags.bits() as sys::ImPlotAxisFlags,
43 )
44 }),
45 None => unsafe {
46 sys::ImPlot_SetupAxis(
47 axis as sys::ImAxis,
48 std::ptr::null(),
49 flags.bits() as sys::ImPlotAxisFlags,
50 )
51 },
52 }
53 }
54
55 pub fn setup_x_axis_limits(&self, axis: XAxis, min: f64, max: f64, cond: PlotCond) {
57 assert_axis_limit_range("PlotUi::setup_x_axis_limits()", min, max);
58 let _guard = self.bind();
59 unsafe {
60 sys::ImPlot_SetupAxisLimits(axis as sys::ImAxis, min, max, cond as sys::ImPlotCond)
61 }
62 }
63
64 pub fn setup_y_axis_limits(&self, axis: YAxis, min: f64, max: f64, cond: PlotCond) {
66 assert_axis_limit_range("PlotUi::setup_y_axis_limits()", min, max);
67 let _guard = self.bind();
68 unsafe {
69 sys::ImPlot_SetupAxisLimits(axis as sys::ImAxis, min, max, cond as sys::ImPlotCond)
70 }
71 }
72
73 pub fn setup_axis_links(
75 &self,
76 axis: Axis,
77 link_min: Option<&mut f64>,
78 link_max: Option<&mut f64>,
79 ) {
80 let pmin = link_min.map_or(std::ptr::null_mut(), |r| r as *mut f64);
81 let pmax = link_max.map_or(std::ptr::null_mut(), |r| r as *mut f64);
82 let _guard = self.bind();
83 unsafe { sys::ImPlot_SetupAxisLinks(axis.to_sys(), pmin, pmax) }
84 }
85
86 pub unsafe fn setup_axis_links_unchecked(
93 &self,
94 axis: sys::ImAxis,
95 link_min: Option<&mut f64>,
96 link_max: Option<&mut f64>,
97 ) {
98 let pmin = link_min.map_or(std::ptr::null_mut(), |r| r as *mut f64);
99 let pmax = link_max.map_or(std::ptr::null_mut(), |r| r as *mut f64);
100 let _guard = self.bind();
101 unsafe { sys::ImPlot_SetupAxisLinks(axis, pmin, pmax) }
102 }
103
104 pub fn setup_axes(
106 &self,
107 x_label: Option<&str>,
108 y_label: Option<&str>,
109 x_flags: AxisFlags,
110 y_flags: AxisFlags,
111 ) {
112 let _guard = self.bind();
113 let x_label = x_label.filter(|s| !s.contains('\0'));
114 let y_label = y_label.filter(|s| !s.contains('\0'));
115
116 match (x_label, y_label) {
117 (Some(x_label), Some(y_label)) => {
118 with_scratch_txt_two(x_label, y_label, |xp, yp| unsafe {
119 sys::ImPlot_SetupAxes(
120 xp,
121 yp,
122 x_flags.bits() as sys::ImPlotAxisFlags,
123 y_flags.bits() as sys::ImPlotAxisFlags,
124 )
125 })
126 }
127 (Some(x_label), None) => with_scratch_txt(x_label, |xp| unsafe {
128 sys::ImPlot_SetupAxes(
129 xp,
130 std::ptr::null(),
131 x_flags.bits() as sys::ImPlotAxisFlags,
132 y_flags.bits() as sys::ImPlotAxisFlags,
133 )
134 }),
135 (None, Some(y_label)) => with_scratch_txt(y_label, |yp| unsafe {
136 sys::ImPlot_SetupAxes(
137 std::ptr::null(),
138 yp,
139 x_flags.bits() as sys::ImPlotAxisFlags,
140 y_flags.bits() as sys::ImPlotAxisFlags,
141 )
142 }),
143 (None, None) => unsafe {
144 sys::ImPlot_SetupAxes(
145 std::ptr::null(),
146 std::ptr::null(),
147 x_flags.bits() as sys::ImPlotAxisFlags,
148 y_flags.bits() as sys::ImPlotAxisFlags,
149 )
150 },
151 }
152 }
153
154 pub fn setup_axes_limits(
156 &self,
157 x_min: f64,
158 x_max: f64,
159 y_min: f64,
160 y_max: f64,
161 cond: PlotCond,
162 ) {
163 assert_axis_limit_range("PlotUi::setup_axes_limits() x axis", x_min, x_max);
164 assert_axis_limit_range("PlotUi::setup_axes_limits() y axis", y_min, y_max);
165 let _guard = self.bind();
166 unsafe { sys::ImPlot_SetupAxesLimits(x_min, x_max, y_min, y_max, cond as sys::ImPlotCond) }
167 }
168
169 pub fn setup_finish(&self) {
171 let _guard = self.bind();
172 unsafe { sys::ImPlot_SetupFinish() }
173 }
174
175 pub fn set_next_x_axis_limits(&self, axis: XAxis, min: f64, max: f64, cond: PlotCond) {
177 assert_axis_limit_range("PlotUi::set_next_x_axis_limits()", min, max);
178 let _guard = self.bind();
179 unsafe {
180 sys::ImPlot_SetNextAxisLimits(axis as sys::ImAxis, min, max, cond as sys::ImPlotCond)
181 }
182 }
183
184 pub fn set_next_y_axis_limits(&self, axis: YAxis, min: f64, max: f64, cond: PlotCond) {
186 assert_axis_limit_range("PlotUi::set_next_y_axis_limits()", min, max);
187 let _guard = self.bind();
188 unsafe {
189 sys::ImPlot_SetNextAxisLimits(axis as sys::ImAxis, min, max, cond as sys::ImPlotCond)
190 }
191 }
192
193 pub fn set_next_axis_links(
195 &self,
196 axis: Axis,
197 link_min: Option<&mut f64>,
198 link_max: Option<&mut f64>,
199 ) {
200 let pmin = link_min.map_or(std::ptr::null_mut(), |r| r as *mut f64);
201 let pmax = link_max.map_or(std::ptr::null_mut(), |r| r as *mut f64);
202 let _guard = self.bind();
203 unsafe { sys::ImPlot_SetNextAxisLinks(axis.to_sys(), pmin, pmax) }
204 }
205
206 pub unsafe fn set_next_axis_links_unchecked(
213 &self,
214 axis: sys::ImAxis,
215 link_min: Option<&mut f64>,
216 link_max: Option<&mut f64>,
217 ) {
218 let pmin = link_min.map_or(std::ptr::null_mut(), |r| r as *mut f64);
219 let pmax = link_max.map_or(std::ptr::null_mut(), |r| r as *mut f64);
220 let _guard = self.bind();
221 unsafe { sys::ImPlot_SetNextAxisLinks(axis, pmin, pmax) }
222 }
223
224 pub fn set_next_axes_limits(
226 &self,
227 x_min: f64,
228 x_max: f64,
229 y_min: f64,
230 y_max: f64,
231 cond: PlotCond,
232 ) {
233 assert_axis_limit_range("PlotUi::set_next_axes_limits() x axis", x_min, x_max);
234 assert_axis_limit_range("PlotUi::set_next_axes_limits() y axis", y_min, y_max);
235 let _guard = self.bind();
236 unsafe {
237 sys::ImPlot_SetNextAxesLimits(x_min, x_max, y_min, y_max, cond as sys::ImPlotCond)
238 }
239 }
240
241 pub fn set_next_axes_to_fit(&self) {
243 let _guard = self.bind();
244 unsafe { sys::ImPlot_SetNextAxesToFit() }
245 }
246
247 pub fn set_next_axis_to_fit(&self, axis: Axis) {
249 let _guard = self.bind();
250 unsafe { sys::ImPlot_SetNextAxisToFit(axis.to_sys()) }
251 }
252
253 pub unsafe fn set_next_axis_to_fit_unchecked(&self, axis: sys::ImAxis) {
260 let _guard = self.bind();
261 unsafe { sys::ImPlot_SetNextAxisToFit(axis) }
262 }
263
264 pub fn set_next_x_axis_to_fit(&self, axis: XAxis) {
266 let _guard = self.bind();
267 unsafe { sys::ImPlot_SetNextAxisToFit(axis as sys::ImAxis) }
268 }
269
270 pub fn set_next_y_axis_to_fit(&self, axis: YAxis) {
272 let _guard = self.bind();
273 unsafe { sys::ImPlot_SetNextAxisToFit(axis as sys::ImAxis) }
274 }
275
276 pub fn setup_x_axis_ticks_positions(
280 &self,
281 axis: XAxis,
282 values: &[f64],
283 labels: Option<&[&str]>,
284 keep_default: bool,
285 ) {
286 assert_finite_f64_slice("PlotUi::setup_x_axis_ticks_positions()", "values", values);
287 let _guard = self.bind();
288 let count = match i32::try_from(values.len()) {
289 Ok(v) => v,
290 Err(_) => return,
291 };
292 if let Some(labels) = labels {
293 if labels.len() != values.len() {
294 return;
295 }
296 let cleaned: Vec<&str> = labels
297 .iter()
298 .map(|&s| if s.contains('\0') { "" } else { s })
299 .collect();
300 with_scratch_txt_slice(&cleaned, |ptrs| unsafe {
301 sys::ImPlot_SetupAxisTicks_doublePtr(
302 axis as sys::ImAxis,
303 values.as_ptr(),
304 count,
305 ptrs.as_ptr() as *const *const c_char,
306 keep_default,
307 )
308 })
309 } else {
310 unsafe {
311 sys::ImPlot_SetupAxisTicks_doublePtr(
312 axis as sys::ImAxis,
313 values.as_ptr(),
314 count,
315 std::ptr::null(),
316 keep_default,
317 )
318 }
319 }
320 }
321
322 pub fn setup_y_axis_ticks_positions(
326 &self,
327 axis: YAxis,
328 values: &[f64],
329 labels: Option<&[&str]>,
330 keep_default: bool,
331 ) {
332 assert_finite_f64_slice("PlotUi::setup_y_axis_ticks_positions()", "values", values);
333 let _guard = self.bind();
334 let count = match i32::try_from(values.len()) {
335 Ok(v) => v,
336 Err(_) => return,
337 };
338 if let Some(labels) = labels {
339 if labels.len() != values.len() {
340 return;
341 }
342 let cleaned: Vec<&str> = labels
343 .iter()
344 .map(|&s| if s.contains('\0') { "" } else { s })
345 .collect();
346 with_scratch_txt_slice(&cleaned, |ptrs| unsafe {
347 sys::ImPlot_SetupAxisTicks_doublePtr(
348 axis as sys::ImAxis,
349 values.as_ptr(),
350 count,
351 ptrs.as_ptr() as *const *const c_char,
352 keep_default,
353 )
354 })
355 } else {
356 unsafe {
357 sys::ImPlot_SetupAxisTicks_doublePtr(
358 axis as sys::ImAxis,
359 values.as_ptr(),
360 count,
361 std::ptr::null(),
362 keep_default,
363 )
364 }
365 }
366 }
367
368 pub fn setup_x_axis_ticks_range(
372 &self,
373 axis: XAxis,
374 v_min: f64,
375 v_max: f64,
376 n_ticks: usize,
377 labels: Option<&[&str]>,
378 keep_default: bool,
379 ) {
380 assert_axis_limit_range("PlotUi::setup_x_axis_ticks_range()", v_min, v_max);
381 let n_ticks_i32 = axis_tick_count_to_i32("PlotUi::setup_x_axis_ticks_range()", n_ticks);
382 let _guard = self.bind();
383 if let Some(labels) = labels {
384 if labels.len() != n_ticks {
385 return;
386 }
387 let cleaned: Vec<&str> = labels
388 .iter()
389 .map(|&s| if s.contains('\0') { "" } else { s })
390 .collect();
391 with_scratch_txt_slice(&cleaned, |ptrs| unsafe {
392 sys::ImPlot_SetupAxisTicks_double(
393 axis as sys::ImAxis,
394 v_min,
395 v_max,
396 n_ticks_i32,
397 ptrs.as_ptr() as *const *const c_char,
398 keep_default,
399 )
400 })
401 } else {
402 unsafe {
403 sys::ImPlot_SetupAxisTicks_double(
404 axis as sys::ImAxis,
405 v_min,
406 v_max,
407 n_ticks_i32,
408 std::ptr::null(),
409 keep_default,
410 )
411 }
412 }
413 }
414
415 pub fn setup_y_axis_ticks_range(
419 &self,
420 axis: YAxis,
421 v_min: f64,
422 v_max: f64,
423 n_ticks: usize,
424 labels: Option<&[&str]>,
425 keep_default: bool,
426 ) {
427 assert_axis_limit_range("PlotUi::setup_y_axis_ticks_range()", v_min, v_max);
428 let n_ticks_i32 = axis_tick_count_to_i32("PlotUi::setup_y_axis_ticks_range()", n_ticks);
429 let _guard = self.bind();
430 if let Some(labels) = labels {
431 if labels.len() != n_ticks {
432 return;
433 }
434 let cleaned: Vec<&str> = labels
435 .iter()
436 .map(|&s| if s.contains('\0') { "" } else { s })
437 .collect();
438 with_scratch_txt_slice(&cleaned, |ptrs| unsafe {
439 sys::ImPlot_SetupAxisTicks_double(
440 axis as sys::ImAxis,
441 v_min,
442 v_max,
443 n_ticks_i32,
444 ptrs.as_ptr() as *const *const c_char,
445 keep_default,
446 )
447 })
448 } else {
449 unsafe {
450 sys::ImPlot_SetupAxisTicks_double(
451 axis as sys::ImAxis,
452 v_min,
453 v_max,
454 n_ticks_i32,
455 std::ptr::null(),
456 keep_default,
457 )
458 }
459 }
460 }
461
462 pub fn setup_x_axis_format(&self, axis: XAxis, fmt: &str) {
464 if fmt.contains('\0') {
465 return;
466 }
467 let _guard = self.bind();
468 with_scratch_txt(fmt, |ptr| unsafe {
469 sys::ImPlot_SetupAxisFormat_Str(axis as sys::ImAxis, ptr)
470 })
471 }
472
473 pub fn setup_y_axis_format(&self, axis: YAxis, fmt: &str) {
475 if fmt.contains('\0') {
476 return;
477 }
478 let _guard = self.bind();
479 with_scratch_txt(fmt, |ptr| unsafe {
480 sys::ImPlot_SetupAxisFormat_Str(axis as sys::ImAxis, ptr)
481 })
482 }
483
484 pub fn setup_x_axis_scale(&self, axis: XAxis, scale: sys::ImPlotScale) {
486 let _guard = self.bind();
487 unsafe { sys::ImPlot_SetupAxisScale_PlotScale(axis as sys::ImAxis, scale) }
488 }
489
490 pub fn setup_y_axis_scale(&self, axis: YAxis, scale: sys::ImPlotScale) {
492 let _guard = self.bind();
493 unsafe { sys::ImPlot_SetupAxisScale_PlotScale(axis as sys::ImAxis, scale) }
494 }
495
496 pub fn setup_axis_limits_constraints(&self, axis: Axis, v_min: f64, v_max: f64) {
498 assert_axis_constraint_range("PlotUi::setup_axis_limits_constraints()", v_min, v_max);
499 let _guard = self.bind();
500 unsafe { sys::ImPlot_SetupAxisLimitsConstraints(axis.to_sys(), v_min, v_max) }
501 }
502
503 pub unsafe fn setup_axis_limits_constraints_unchecked(
510 &self,
511 axis: sys::ImAxis,
512 v_min: f64,
513 v_max: f64,
514 ) {
515 assert_axis_constraint_range(
516 "PlotUi::setup_axis_limits_constraints_unchecked()",
517 v_min,
518 v_max,
519 );
520 let _guard = self.bind();
521 unsafe { sys::ImPlot_SetupAxisLimitsConstraints(axis, v_min, v_max) }
522 }
523
524 pub fn setup_axis_zoom_constraints(&self, axis: Axis, z_min: f64, z_max: f64) {
526 assert_axis_zoom_range("PlotUi::setup_axis_zoom_constraints()", z_min, z_max);
527 let _guard = self.bind();
528 unsafe { sys::ImPlot_SetupAxisZoomConstraints(axis.to_sys(), z_min, z_max) }
529 }
530
531 pub unsafe fn setup_axis_zoom_constraints_unchecked(
538 &self,
539 axis: sys::ImAxis,
540 z_min: f64,
541 z_max: f64,
542 ) {
543 assert_axis_zoom_range(
544 "PlotUi::setup_axis_zoom_constraints_unchecked()",
545 z_min,
546 z_max,
547 );
548 let _guard = self.bind();
549 unsafe { sys::ImPlot_SetupAxisZoomConstraints(axis, z_min, z_max) }
550 }
551}