dear_implot/plots/
dummy.rs1use super::{PlotData, PlotError, PlotItemStyle, plot_spec_with_style, with_plot_str_or_empty};
4use crate::{DummyFlags, ItemFlags, sys};
5
6pub struct DummyPlot<'a> {
11 label: &'a str,
12 style: PlotItemStyle,
13 flags: DummyFlags,
14 item_flags: ItemFlags,
15}
16
17impl<'a> super::PlotItemStyled for DummyPlot<'a> {
18 fn style_mut(&mut self) -> &mut PlotItemStyle {
19 &mut self.style
20 }
21}
22
23impl<'a> DummyPlot<'a> {
24 pub fn new(label: &'a str) -> Self {
26 Self {
27 label,
28 style: PlotItemStyle::default(),
29 flags: DummyFlags::NONE,
30 item_flags: ItemFlags::NONE,
31 }
32 }
33
34 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
36 self.style = style;
37 self
38 }
39
40 pub fn with_flags(mut self, flags: DummyFlags) -> 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 validate(&self) -> Result<(), PlotError> {
54 if self.label.is_empty() {
55 return Err(PlotError::InvalidData("Label cannot be empty".to_string()));
56 }
57 Ok(())
58 }
59
60 pub fn plot(self) {
62 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
63 let spec = plot_spec_with_style(
64 self.style,
65 self.flags.bits() | self.item_flags.bits(),
66 0,
67 crate::IMPLOT_AUTO,
68 );
69 sys::ImPlot_PlotDummy(label_ptr, spec);
70 })
71 }
72}
73
74impl<'a> PlotData for DummyPlot<'a> {
75 fn label(&self) -> &str {
76 self.label
77 }
78
79 fn data_len(&self) -> usize {
80 0 }
82}
83
84pub struct MultiDummyPlot<'a> {
86 labels: Vec<&'a str>,
87 style: PlotItemStyle,
88 flags: DummyFlags,
89 item_flags: ItemFlags,
90}
91
92impl<'a> super::PlotItemStyled for MultiDummyPlot<'a> {
93 fn style_mut(&mut self) -> &mut PlotItemStyle {
94 &mut self.style
95 }
96}
97
98impl<'a> MultiDummyPlot<'a> {
99 pub fn new(labels: Vec<&'a str>) -> Self {
101 Self {
102 labels,
103 style: PlotItemStyle::default(),
104 flags: DummyFlags::NONE,
105 item_flags: ItemFlags::NONE,
106 }
107 }
108
109 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
111 self.style = style;
112 self
113 }
114
115 pub fn with_flags(mut self, flags: DummyFlags) -> Self {
117 self.flags = flags;
118 self
119 }
120
121 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
123 self.item_flags = flags;
124 self
125 }
126
127 pub fn validate(&self) -> Result<(), PlotError> {
129 if self.labels.is_empty() {
130 return Err(PlotError::EmptyData);
131 }
132
133 for (i, &label) in self.labels.iter().enumerate() {
134 if label.is_empty() {
135 return Err(PlotError::InvalidData(format!(
136 "Label at index {} cannot be empty",
137 i
138 )));
139 }
140 }
141
142 Ok(())
143 }
144
145 pub fn plot(self) {
147 for &label in &self.labels {
148 let dummy_plot = DummyPlot::new(label)
149 .with_style(self.style)
150 .with_flags(self.flags)
151 .with_item_flags(self.item_flags);
152 dummy_plot.plot();
153 }
154 }
155}
156
157impl<'a> PlotData for MultiDummyPlot<'a> {
158 fn label(&self) -> &str {
159 "MultiDummy"
160 }
161
162 fn data_len(&self) -> usize {
163 self.labels.len()
164 }
165}
166
167pub struct LegendSeparator<'a> {
169 label: &'a str,
170 style: PlotItemStyle,
171}
172
173impl<'a> super::PlotItemStyled for LegendSeparator<'a> {
174 fn style_mut(&mut self) -> &mut PlotItemStyle {
175 &mut self.style
176 }
177}
178
179impl<'a> LegendSeparator<'a> {
180 pub fn new(label: &'a str) -> Self {
182 Self {
183 label,
184 style: PlotItemStyle::default(),
185 }
186 }
187
188 pub fn empty() -> Self {
190 Self {
191 label: "---",
192 style: PlotItemStyle::default(),
193 }
194 }
195
196 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
198 self.style = style;
199 self
200 }
201
202 pub fn plot(self) {
204 let dummy_plot = DummyPlot::new(self.label).with_style(self.style);
205 dummy_plot.plot();
206 }
207}
208
209pub struct LegendHeader<'a> {
211 title: &'a str,
212 style: PlotItemStyle,
213}
214
215impl<'a> super::PlotItemStyled for LegendHeader<'a> {
216 fn style_mut(&mut self) -> &mut PlotItemStyle {
217 &mut self.style
218 }
219}
220
221impl<'a> LegendHeader<'a> {
222 pub fn new(title: &'a str) -> Self {
224 Self {
225 title,
226 style: PlotItemStyle::default(),
227 }
228 }
229
230 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
232 self.style = style;
233 self
234 }
235
236 pub fn plot(self) {
238 let dummy_plot = DummyPlot::new(self.title).with_style(self.style);
239 dummy_plot.plot();
240 }
241}
242
243pub struct CustomLegendEntry<'a> {
245 label: &'a str,
246 style: PlotItemStyle,
247 flags: DummyFlags,
248 item_flags: ItemFlags,
249}
250
251impl<'a> super::PlotItemStyled for CustomLegendEntry<'a> {
252 fn style_mut(&mut self) -> &mut PlotItemStyle {
253 &mut self.style
254 }
255}
256
257impl<'a> CustomLegendEntry<'a> {
258 pub fn new(label: &'a str) -> Self {
260 Self {
261 label,
262 style: PlotItemStyle::default(),
263 flags: DummyFlags::NONE,
264 item_flags: ItemFlags::NONE,
265 }
266 }
267
268 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
270 self.style = style;
271 self
272 }
273
274 pub fn with_flags(mut self, flags: DummyFlags) -> Self {
276 self.flags = flags;
277 self
278 }
279
280 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
282 self.item_flags = flags;
283 self
284 }
285
286 pub fn plot(self) {
288 let dummy_plot = DummyPlot::new(self.label)
289 .with_style(self.style)
290 .with_flags(self.flags)
291 .with_item_flags(self.item_flags);
292 dummy_plot.plot();
293 }
294}
295
296pub struct LegendGroup<'a> {
298 title: &'a str,
299 entries: Vec<&'a str>,
300 style: PlotItemStyle,
301 add_separator: bool,
302}
303
304impl<'a> super::PlotItemStyled for LegendGroup<'a> {
305 fn style_mut(&mut self) -> &mut PlotItemStyle {
306 &mut self.style
307 }
308}
309
310impl<'a> LegendGroup<'a> {
311 pub fn new(title: &'a str, entries: Vec<&'a str>) -> Self {
313 Self {
314 title,
315 entries,
316 style: PlotItemStyle::default(),
317 add_separator: true,
318 }
319 }
320
321 pub fn with_style(mut self, style: PlotItemStyle) -> Self {
323 self.style = style;
324 self
325 }
326
327 pub fn no_separator(mut self) -> Self {
329 self.add_separator = false;
330 self
331 }
332
333 pub fn plot(self) {
335 LegendHeader::new(self.title).with_style(self.style).plot();
337
338 for &entry in &self.entries {
340 DummyPlot::new(entry).with_style(self.style).plot();
341 }
342
343 if self.add_separator && !self.entries.is_empty() {
345 LegendSeparator::empty().with_style(self.style).plot();
346 }
347 }
348}
349
350impl<'a> DummyPlot<'a> {
352 pub fn separator() -> DummyPlot<'static> {
354 DummyPlot::new("---")
355 }
356
357 pub fn spacer() -> DummyPlot<'static> {
359 DummyPlot::new(" ")
360 }
361
362 pub fn header(title: &'a str) -> DummyPlot<'a> {
364 DummyPlot::new(title)
365 }
366}
367
368#[macro_export]
370macro_rules! dummy_plots {
371 ($($label:expr),* $(,)?) => {
372 {
373 let labels = vec![$($label),*];
374 $crate::plots::dummy::MultiDummyPlot::new(labels)
375 }
376 };
377}
378
379#[macro_export]
381macro_rules! legend_group {
382 ($title:expr, $($entry:expr),* $(,)?) => {
383 {
384 let entries = vec![$($entry),*];
385 $crate::plots::dummy::LegendGroup::new($title, entries)
386 }
387 };
388}