1#![allow(
7 clippy::cast_possible_truncation,
8 clippy::cast_sign_loss,
9 clippy::as_conversions
10)]
11use crate::internal::plot_value_count_i32;
12use crate::sys;
13use crate::ui::Ui;
14use std::borrow::Cow;
15
16impl Ui {
18 #[doc(alias = "PlotLines")]
20 pub fn plot_lines(&self, label: impl AsRef<str>, values: &[f32]) {
21 self.plot_lines_config(label.as_ref(), values).build()
22 }
23
24 #[doc(alias = "PlotHistogram")]
26 pub fn plot_histogram(&self, label: impl AsRef<str>, values: &[f32]) {
27 self.plot_histogram_config(label.as_ref(), values).build()
28 }
29
30 pub fn plot_lines_config<'ui, 'p>(
32 &'ui self,
33 label: impl Into<Cow<'ui, str>>,
34 values: &'p [f32],
35 ) -> PlotLines<'ui, 'p> {
36 PlotLines::new(self, label, values)
37 }
38
39 pub fn plot_histogram_config<'ui, 'p>(
41 &'ui self,
42 label: impl Into<Cow<'ui, str>>,
43 values: &'p [f32],
44 ) -> PlotHistogram<'ui, 'p> {
45 PlotHistogram::new(self, label, values)
46 }
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
51pub struct PlotValueOffset(usize);
52
53impl PlotValueOffset {
54 pub const ZERO: Self = Self(0);
56
57 #[inline]
59 pub const fn new(offset: usize) -> Self {
60 Self(offset)
61 }
62
63 #[inline]
64 pub(crate) fn into_i32(self, caller: &str, value_count: i32) -> i32 {
65 let offset = i32::try_from(self.0).unwrap_or_else(|_| {
66 panic!("{caller} values_offset supports at most i32::MAX");
67 });
68 assert!(
69 value_count == 0 || offset < value_count,
70 "{caller} values_offset must be less than values.len()"
71 );
72 offset
73 }
74}
75
76impl From<usize> for PlotValueOffset {
77 fn from(offset: usize) -> Self {
78 Self::new(offset)
79 }
80}
81
82#[derive(Debug)]
84#[must_use]
85pub struct PlotLines<'ui, 'p> {
86 ui: &'ui Ui,
87 label: Cow<'ui, str>,
88 values: &'p [f32],
89 values_offset: PlotValueOffset,
90 overlay_text: Option<Cow<'ui, str>>,
91 scale_min: f32,
92 scale_max: f32,
93 graph_size: [f32; 2],
94}
95
96impl<'ui, 'p> PlotLines<'ui, 'p> {
97 pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, values: &'p [f32]) -> Self {
99 Self {
100 ui,
101 label: label.into(),
102 values,
103 values_offset: PlotValueOffset::ZERO,
104 overlay_text: None,
105 scale_min: f32::MAX,
106 scale_max: f32::MAX,
107 graph_size: [0.0, 0.0],
108 }
109 }
110
111 pub fn values_offset(mut self, offset: impl Into<PlotValueOffset>) -> Self {
113 self.values_offset = offset.into();
114 self
115 }
116
117 pub fn overlay_text(mut self, text: impl Into<Cow<'ui, str>>) -> Self {
119 self.overlay_text = Some(text.into());
120 self
121 }
122
123 pub fn scale_min(mut self, scale_min: f32) -> Self {
125 self.scale_min = scale_min;
126 self
127 }
128
129 pub fn scale_max(mut self, scale_max: f32) -> Self {
131 self.scale_max = scale_max;
132 self
133 }
134
135 pub fn graph_size(mut self, size: [f32; 2]) -> Self {
137 self.graph_size = size;
138 self
139 }
140
141 pub fn build(self) {
143 let count = plot_value_count_i32("PlotLines::build()", self.values.len());
144 let values_offset = self.values_offset.into_i32("PlotLines::build()", count);
145 let (label_ptr, overlay_ptr) = self
146 .ui
147 .scratch_txt_with_opt(self.label.as_ref(), self.overlay_text.as_deref());
148 let graph_size_vec: sys::ImVec2 = self.graph_size.into();
149
150 unsafe {
151 sys::igPlotLines_FloatPtr(
152 label_ptr,
153 self.values.as_ptr(),
154 count,
155 values_offset,
156 overlay_ptr,
157 self.scale_min,
158 self.scale_max,
159 graph_size_vec,
160 std::mem::size_of::<f32>() as i32,
161 );
162 }
163 }
164}
165
166#[derive(Debug)]
168#[must_use]
169pub struct PlotHistogram<'ui, 'p> {
170 ui: &'ui Ui,
171 label: Cow<'ui, str>,
172 values: &'p [f32],
173 values_offset: PlotValueOffset,
174 overlay_text: Option<Cow<'ui, str>>,
175 scale_min: f32,
176 scale_max: f32,
177 graph_size: [f32; 2],
178}
179
180impl<'ui, 'p> PlotHistogram<'ui, 'p> {
181 pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, values: &'p [f32]) -> Self {
183 Self {
184 ui,
185 label: label.into(),
186 values,
187 values_offset: PlotValueOffset::ZERO,
188 overlay_text: None,
189 scale_min: f32::MAX,
190 scale_max: f32::MAX,
191 graph_size: [0.0, 0.0],
192 }
193 }
194
195 pub fn values_offset(mut self, offset: impl Into<PlotValueOffset>) -> Self {
197 self.values_offset = offset.into();
198 self
199 }
200
201 pub fn overlay_text(mut self, text: impl Into<Cow<'ui, str>>) -> Self {
203 self.overlay_text = Some(text.into());
204 self
205 }
206
207 pub fn scale_min(mut self, scale_min: f32) -> Self {
209 self.scale_min = scale_min;
210 self
211 }
212
213 pub fn scale_max(mut self, scale_max: f32) -> Self {
215 self.scale_max = scale_max;
216 self
217 }
218
219 pub fn graph_size(mut self, size: [f32; 2]) -> Self {
221 self.graph_size = size;
222 self
223 }
224
225 pub fn build(self) {
227 let count = plot_value_count_i32("PlotHistogram::build()", self.values.len());
228 let values_offset = self.values_offset.into_i32("PlotHistogram::build()", count);
229 let (label_ptr, overlay_ptr) = self
230 .ui
231 .scratch_txt_with_opt(self.label.as_ref(), self.overlay_text.as_deref());
232 let graph_size_vec: sys::ImVec2 = self.graph_size.into();
233
234 unsafe {
235 sys::igPlotHistogram_FloatPtr(
236 label_ptr,
237 self.values.as_ptr(),
238 count,
239 values_offset,
240 overlay_ptr,
241 self.scale_min,
242 self.scale_max,
243 graph_size_vec,
244 std::mem::size_of::<f32>() as i32,
245 );
246 }
247 }
248}