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