dear_implot/context/
ui.rs1use super::core::PlotContext;
2use super::token::PlotToken;
3use super::validation::assert_finite_vec2;
4use crate::{XAxis, YAxis, sys};
5use dear_imgui_rs::{Ui, with_scratch_txt};
6
7pub struct PlotUi<'ui> {
12 #[allow(dead_code)]
13 pub(crate) context: &'ui PlotContext,
14 #[allow(dead_code)]
15 pub(crate) ui: &'ui Ui,
16}
17
18impl<'ui> PlotUi<'ui> {
19 #[inline]
20 pub(crate) fn bind(&self) {
21 self.context.assert_imgui_alive();
22 self.context.binding().bind("dear-implot: PlotUi");
23 }
24
25 pub fn begin_plot(&self, title: &str) -> Option<PlotToken<'_>> {
30 let size = sys::ImVec2_c { x: -1.0, y: 0.0 };
31 if title.contains('\0') {
32 return None;
33 }
34 self.bind();
35 let started = with_scratch_txt(title, |ptr| unsafe { sys::ImPlot_BeginPlot(ptr, size, 0) });
36
37 if started {
38 Some(PlotToken::new(
39 self.context.binding(),
40 self.context.imgui_alive_token(),
41 ))
42 } else {
43 None
44 }
45 }
46
47 pub fn begin_plot_with_size(&self, title: &str, size: [f32; 2]) -> Option<PlotToken<'_>> {
49 assert_finite_vec2("PlotUi::begin_plot_with_size()", "size", size);
50 let plot_size = sys::ImVec2_c {
51 x: size[0],
52 y: size[1],
53 };
54 if title.contains('\0') {
55 return None;
56 }
57 self.bind();
58 let started = with_scratch_txt(title, |ptr| unsafe {
59 sys::ImPlot_BeginPlot(ptr, plot_size, 0)
60 });
61
62 if started {
63 Some(PlotToken::new(
64 self.context.binding(),
65 self.context.imgui_alive_token(),
66 ))
67 } else {
68 None
69 }
70 }
71
72 pub fn plot_line(&self, label: &str, x_data: &[f64], y_data: &[f64]) {
76 if x_data.len() != y_data.len() {
77 return; }
79 let count = match i32::try_from(x_data.len()) {
80 Ok(v) => v,
81 Err(_) => return,
82 };
83
84 let label = if label.contains('\0') { "" } else { label };
85 self.bind();
86 with_scratch_txt(label, |ptr| unsafe {
87 let spec = crate::plots::plot_spec_from(0, crate::plots::PlotDataLayout::DEFAULT);
88 sys::ImPlot_PlotLine_doublePtrdoublePtr(
89 ptr,
90 x_data.as_ptr(),
91 y_data.as_ptr(),
92 count,
93 spec,
94 );
95 })
96 }
97
98 pub fn plot_scatter(&self, label: &str, x_data: &[f64], y_data: &[f64]) {
100 if x_data.len() != y_data.len() {
101 return; }
103 let count = match i32::try_from(x_data.len()) {
104 Ok(v) => v,
105 Err(_) => return,
106 };
107
108 let label = if label.contains('\0') { "" } else { label };
109 self.bind();
110 with_scratch_txt(label, |ptr| unsafe {
111 let spec = crate::plots::plot_spec_from(0, crate::plots::PlotDataLayout::DEFAULT);
112 sys::ImPlot_PlotScatter_doublePtrdoublePtr(
113 ptr,
114 x_data.as_ptr(),
115 y_data.as_ptr(),
116 count,
117 spec,
118 );
119 })
120 }
121
122 pub fn plot_polygon(&self, label: &str, x_data: &[f64], y_data: &[f64]) {
124 if x_data.len() != y_data.len() {
125 return;
126 }
127 let count = match i32::try_from(x_data.len()) {
128 Ok(v) => v,
129 Err(_) => return,
130 };
131
132 let label = if label.contains('\0') { "" } else { label };
133 self.bind();
134 with_scratch_txt(label, |ptr| unsafe {
135 let spec = crate::plots::plot_spec_from(0, crate::plots::PlotDataLayout::DEFAULT);
136 sys::ImPlot_PlotPolygon_doublePtr(ptr, x_data.as_ptr(), y_data.as_ptr(), count, spec);
137 })
138 }
139
140 pub fn is_plot_hovered(&self) -> bool {
142 self.bind();
143 unsafe { sys::ImPlot_IsPlotHovered() }
144 }
145
146 pub fn get_plot_mouse_pos(&self, y_axis: Option<crate::YAxisChoice>) -> sys::ImPlotPoint {
148 let y_axis_i32 = crate::y_axis_choice_option_to_i32(y_axis);
149 let y_axis = match y_axis_i32 {
150 0 => 3,
151 1 => 4,
152 2 => 5,
153 _ => 3,
154 };
155 self.bind();
156 unsafe { sys::ImPlot_GetPlotMousePos(0, y_axis) }
157 }
158
159 pub fn get_plot_mouse_pos_axes(&self, x_axis: XAxis, y_axis: YAxis) -> sys::ImPlotPoint {
161 self.bind();
162 unsafe { sys::ImPlot_GetPlotMousePos(x_axis as i32, y_axis as i32) }
163 }
164
165 pub fn set_axes(&self, x_axis: XAxis, y_axis: YAxis) {
167 self.bind();
168 unsafe { sys::ImPlot_SetAxes(x_axis as i32, y_axis as i32) }
169 }
170}