dear_implot/plots/
dummy.rs1use super::{PlotData, PlotError, plot_spec_from, with_plot_str_or_empty};
4use crate::{DummyFlags, ItemFlags, sys};
5
6pub struct DummyPlot<'a> {
11 label: &'a str,
12 flags: DummyFlags,
13 item_flags: ItemFlags,
14}
15
16impl<'a> DummyPlot<'a> {
17 pub fn new(label: &'a str) -> Self {
19 Self {
20 label,
21 flags: DummyFlags::NONE,
22 item_flags: ItemFlags::NONE,
23 }
24 }
25
26 pub fn with_flags(mut self, flags: DummyFlags) -> Self {
28 self.flags = flags;
29 self
30 }
31
32 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
34 self.item_flags = flags;
35 self
36 }
37
38 pub fn validate(&self) -> Result<(), PlotError> {
40 if self.label.is_empty() {
41 return Err(PlotError::InvalidData("Label cannot be empty".to_string()));
42 }
43 Ok(())
44 }
45
46 pub fn plot(self) {
48 with_plot_str_or_empty(self.label, |label_ptr| unsafe {
49 let spec = plot_spec_from(
50 self.flags.bits() | self.item_flags.bits(),
51 0,
52 crate::IMPLOT_AUTO,
53 );
54 sys::ImPlot_PlotDummy(label_ptr, spec);
55 })
56 }
57}
58
59impl<'a> PlotData for DummyPlot<'a> {
60 fn label(&self) -> &str {
61 self.label
62 }
63
64 fn data_len(&self) -> usize {
65 0 }
67}
68
69pub struct MultiDummyPlot<'a> {
71 labels: Vec<&'a str>,
72 flags: DummyFlags,
73 item_flags: ItemFlags,
74}
75
76impl<'a> MultiDummyPlot<'a> {
77 pub fn new(labels: Vec<&'a str>) -> Self {
79 Self {
80 labels,
81 flags: DummyFlags::NONE,
82 item_flags: ItemFlags::NONE,
83 }
84 }
85
86 pub fn with_flags(mut self, flags: DummyFlags) -> Self {
88 self.flags = flags;
89 self
90 }
91
92 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
94 self.item_flags = flags;
95 self
96 }
97
98 pub fn validate(&self) -> Result<(), PlotError> {
100 if self.labels.is_empty() {
101 return Err(PlotError::EmptyData);
102 }
103
104 for (i, &label) in self.labels.iter().enumerate() {
105 if label.is_empty() {
106 return Err(PlotError::InvalidData(format!(
107 "Label at index {} cannot be empty",
108 i
109 )));
110 }
111 }
112
113 Ok(())
114 }
115
116 pub fn plot(self) {
118 for &label in &self.labels {
119 let dummy_plot = DummyPlot::new(label)
120 .with_flags(self.flags)
121 .with_item_flags(self.item_flags);
122 dummy_plot.plot();
123 }
124 }
125}
126
127impl<'a> PlotData for MultiDummyPlot<'a> {
128 fn label(&self) -> &str {
129 "MultiDummy"
130 }
131
132 fn data_len(&self) -> usize {
133 self.labels.len()
134 }
135}
136
137pub struct LegendSeparator<'a> {
139 label: &'a str,
140}
141
142impl<'a> LegendSeparator<'a> {
143 pub fn new(label: &'a str) -> Self {
145 Self { label }
146 }
147
148 pub fn empty() -> Self {
150 Self { label: "---" }
151 }
152
153 pub fn plot(self) {
155 let dummy_plot = DummyPlot::new(self.label);
156 dummy_plot.plot();
157 }
158}
159
160pub struct LegendHeader<'a> {
162 title: &'a str,
163}
164
165impl<'a> LegendHeader<'a> {
166 pub fn new(title: &'a str) -> Self {
168 Self { title }
169 }
170
171 pub fn plot(self) {
173 let dummy_plot = DummyPlot::new(self.title);
174 dummy_plot.plot();
175 }
176}
177
178pub struct CustomLegendEntry<'a> {
180 label: &'a str,
181 flags: DummyFlags,
182 item_flags: ItemFlags,
183}
184
185impl<'a> CustomLegendEntry<'a> {
186 pub fn new(label: &'a str) -> Self {
188 Self {
189 label,
190 flags: DummyFlags::NONE,
191 item_flags: ItemFlags::NONE,
192 }
193 }
194
195 pub fn with_flags(mut self, flags: DummyFlags) -> Self {
197 self.flags = flags;
198 self
199 }
200
201 pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
203 self.item_flags = flags;
204 self
205 }
206
207 pub fn plot(self) {
209 let dummy_plot = DummyPlot::new(self.label)
210 .with_flags(self.flags)
211 .with_item_flags(self.item_flags);
212 dummy_plot.plot();
213 }
214}
215
216pub struct LegendGroup<'a> {
218 title: &'a str,
219 entries: Vec<&'a str>,
220 add_separator: bool,
221}
222
223impl<'a> LegendGroup<'a> {
224 pub fn new(title: &'a str, entries: Vec<&'a str>) -> Self {
226 Self {
227 title,
228 entries,
229 add_separator: true,
230 }
231 }
232
233 pub fn no_separator(mut self) -> Self {
235 self.add_separator = false;
236 self
237 }
238
239 pub fn plot(self) {
241 LegendHeader::new(self.title).plot();
243
244 for &entry in &self.entries {
246 DummyPlot::new(entry).plot();
247 }
248
249 if self.add_separator && !self.entries.is_empty() {
251 LegendSeparator::empty().plot();
252 }
253 }
254}
255
256impl<'a> DummyPlot<'a> {
258 pub fn separator() -> DummyPlot<'static> {
260 DummyPlot::new("---")
261 }
262
263 pub fn spacer() -> DummyPlot<'static> {
265 DummyPlot::new(" ")
266 }
267
268 pub fn header(title: &'a str) -> DummyPlot<'a> {
270 DummyPlot::new(title)
271 }
272}
273
274#[macro_export]
276macro_rules! dummy_plots {
277 ($($label:expr),* $(,)?) => {
278 {
279 let labels = vec![$($label),*];
280 $crate::plots::dummy::MultiDummyPlot::new(labels)
281 }
282 };
283}
284
285#[macro_export]
287macro_rules! legend_group {
288 ($title:expr, $($entry:expr),* $(,)?) => {
289 {
290 let entries = vec![$($entry),*];
291 $crate::plots::dummy::LegendGroup::new($title, entries)
292 }
293 };
294}