egui_probe/
num.rs

1use core::ops::{RangeFrom, RangeFull, RangeInclusive, RangeToInclusive};
2
3use egui::emath::Numeric;
4
5use crate::{EguiProbe, Style, option::option_probe_with};
6
7/// Marker type to indicate that the step for range is not set.
8pub struct StepUnset;
9
10/// Bundles value and a range to show probbing UI to edit the value in that range.
11pub struct EguiProbeRange<'a, T, R, S = StepUnset> {
12    pub value: &'a mut T,
13    pub range: R,
14    pub step: S,
15}
16
17pub fn non_negative<N: Numeric>(value: &mut N) -> EguiProbeRange<'_, N, RangeFrom<N>> {
18    EguiProbeRange {
19        value,
20        range: N::from_f64(0.0)..,
21        step: StepUnset,
22    }
23}
24
25// pub fn non_negative_with_step<N: Numeric, S>(
26//     value: &mut N,
27//     step: S,
28// ) -> EguiProbeRange<'_, N, RangeFrom<N>, S> {
29//     EguiProbeRange {
30//         value,
31//         range: N::from_f64(0.0)..,
32//         step,
33//     }
34// }
35
36// pub fn range_from<'a, T>(value: &'a mut T, from: T) -> EguiProbeRange<'a, T, RangeFrom<T>> {
37//     EguiProbeRange {
38//         value,
39//         range: from..,
40//     }
41// }
42
43// pub fn range_to<'a, T>(value: &'a mut T, to: T) -> EguiProbeRange<'a, T, RangeToInclusive<T>> {
44//     EguiProbeRange {
45//         value,
46//         range: ..=to,
47//     }
48// }
49
50// pub fn range<'a, T>(
51//     value: &'a mut T,
52//     range: RangeInclusive<T>,
53// ) -> EguiProbeRange<'a, T, RangeInclusive<T>> {
54//     EguiProbeRange { value, range }
55// }
56
57macro_rules! impl_for_num_types {
58    ($num_type:ident) => {
59        impl EguiProbe for $num_type {
60            #[inline(always)]
61            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
62                ui.add(egui::DragValue::new(self))
63            }
64        }
65
66        impl EguiProbe for EguiProbeRange<'_, $num_type, RangeFull> {
67            #[inline(always)]
68            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
69                let range = $num_type::MIN..=$num_type::MAX;
70                ui.add(egui::DragValue::new(self.value).range(range))
71            }
72        }
73
74        impl EguiProbe for EguiProbeRange<'_, $num_type, RangeFrom<$num_type>> {
75            #[inline(always)]
76            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
77                let range = self.range.start..=$num_type::MAX;
78                let mut changed = false;
79                let mut r = ui.horizontal(|ui| {
80                    changed |= ui.add(egui::DragValue::new(self.value).range(range)).changed();
81                    ui.weak(format!("{}..", self.range.start));
82                }).response;
83
84                if changed {
85                    r.mark_changed();
86                }
87
88                r
89            }
90        }
91
92        impl EguiProbe for EguiProbeRange<'_, $num_type, RangeToInclusive<$num_type>> {
93            #[inline(always)]
94            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
95                let range = $num_type::MIN..=self.range.end;
96                let mut changed = false;
97                let mut r = ui.horizontal(|ui| {
98                    changed |= ui.add(egui::DragValue::new(self.value).range(range)).changed();
99                    ui.weak(format!("..={}", self.range.end));
100                }).response;
101
102                if changed {
103                    r.mark_changed();
104                }
105
106                r
107            }
108        }
109
110        impl EguiProbe for EguiProbeRange<'_, $num_type, RangeInclusive<$num_type>> {
111            #[inline(always)]
112            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
113                let range = self.range.clone();
114                let mut changed = false;
115                let mut r = ui.horizontal(|ui| {
116                    changed |= ui.add(egui::DragValue::new(self.value).range(range)).changed();
117                    ui.weak(format!("{}..={}", self.range.start(), self.range.end()));
118                }).response;
119
120                if changed {
121                    r.mark_changed();
122                }
123
124                r
125            }
126        }
127
128        impl EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeFull> {
129            #[inline(always)]
130            fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
131                let range = $num_type::MIN..=$num_type::MAX;
132                option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
133                    ui.add(egui::DragValue::new(value).range(range))
134                })
135            }
136        }
137
138        impl EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeFrom<$num_type>> {
139            #[inline(always)]
140            fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
141                let range = self.range.start..=$num_type::MAX;
142                option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
143                    let r = ui.add(egui::DragValue::new(value).range(range));
144                    ui.weak(format!("{}..", self.range.start));
145                    r
146                })
147            }
148        }
149
150        impl EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeToInclusive<$num_type>> {
151            #[inline(always)]
152            fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
153                let range = $num_type::MIN..=self.range.end;
154                option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
155                    let r = ui.add(egui::DragValue::new(value).range(range));
156                    ui.weak(format!("..={}", self.range.end));
157                    r
158                })
159            }
160        }
161
162        impl EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeInclusive<$num_type>> {
163            #[inline(always)]
164            fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
165                let range = self.range.clone();
166                option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
167                    let r = ui.add(egui::DragValue::new(value).range(range));
168                    ui.weak(format!("{}..={}", self.range.start(), self.range.end()));
169                    r
170                })
171            }
172        }
173
174
175
176
177
178
179
180        impl<S> EguiProbe for EguiProbeRange<'_, $num_type, RangeFull, S> where S: Copy + Into<f64> {
181            #[inline(always)]
182            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
183                let range = $num_type::MIN..=$num_type::MAX;
184                ui.add(egui::DragValue::new(self.value).range(range).speed(self.step.into()))
185            }
186        }
187
188        impl<S> EguiProbe for EguiProbeRange<'_, $num_type, RangeFrom<$num_type>, S> where S: Copy + Into<f64> {
189            #[inline(always)]
190            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
191                let range = self.range.start..=$num_type::MAX;
192                let mut changed = false;
193                let mut r = ui.horizontal(|ui| {
194                    changed |= ui.add(egui::DragValue::new(self.value).range(range).speed(self.step.into())).changed();
195                    ui.weak(format!("{}..", self.range.start));
196                }).response;
197
198                if changed {
199                    r.mark_changed();
200                }
201
202                r
203            }
204        }
205
206        impl<S> EguiProbe for EguiProbeRange<'_, $num_type, RangeToInclusive<$num_type>, S> where S: Copy + Into<f64> {
207            #[inline(always)]
208            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
209                let range = $num_type::MIN..=self.range.end;
210                let mut changed = false;
211                let mut r = ui.horizontal(|ui| {
212                    changed |= ui.add(egui::DragValue::new(self.value).range(range).speed(self.step.into())).changed();
213                    ui.weak(format!("..={}", self.range.end));
214                }).response;
215
216                if changed {
217                    r.mark_changed();
218                }
219
220                r
221            }
222        }
223
224        impl<S> EguiProbe for EguiProbeRange<'_, $num_type, RangeInclusive<$num_type>, S> where S: Copy + Into<f64> {
225            #[inline(always)]
226            fn probe(&mut self, ui: &mut egui::Ui, _: &Style) -> egui::Response {
227                let range = self.range.clone();
228                let mut changed = false;
229                let mut r = ui.horizontal(|ui| {
230                    changed |= ui.add(egui::DragValue::new(self.value).range(range).speed(self.step.into())).changed();
231                    ui.weak(format!("{}..={}", self.range.start(), self.range.end()));
232                }).response;
233
234                if changed {
235                    r.mark_changed();
236                }
237
238                r
239            }
240        }
241
242        impl<S> EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeFull, S> where S: Copy + Into<f64> {
243            #[inline(always)]
244            fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
245                let range = $num_type::MIN..=$num_type::MAX;
246                option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
247                    ui.add(egui::DragValue::new(value).range(range).speed(self.step.into()))
248                })
249            }
250        }
251
252        impl<S> EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeFrom<$num_type>, S> where S: Copy + Into<f64> {
253            #[inline(always)]
254            fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
255                let range = self.range.start..=$num_type::MAX;
256                option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
257                    let r = ui.add(egui::DragValue::new(value).range(range).speed(self.step.into()));
258                    ui.weak(format!("{}..", self.range.start));
259                    r
260                })
261            }
262        }
263
264        impl<S> EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeToInclusive<$num_type>, S> where S: Copy + Into<f64> {
265            #[inline(always)]
266            fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
267                let range = $num_type::MIN..=self.range.end;
268                option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
269                    let r = ui.add(egui::DragValue::new(value).range(range).speed(self.step.into()));
270                    ui.weak(format!("..={}", self.range.end));
271                    r
272                })
273            }
274        }
275
276        impl<S> EguiProbe for EguiProbeRange<'_, Option<$num_type>, RangeInclusive<$num_type>, S> where S: Copy + Into<f64> {
277            #[inline(always)]
278            fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
279                let range = self.range.clone();
280                option_probe_with(self.value, ui, style, $num_type::default, |value, ui, _| {
281                    let r = ui.add(egui::DragValue::new(value).range(range).speed(self.step.into()));
282                    ui.weak(format!("{}..={}", self.range.start(), self.range.end()));
283                    r
284                })
285            }
286        }
287    };
288
289    ($($num_type:ident),*) => {
290        $(impl_for_num_types!($num_type);)*
291    };
292}
293
294impl_for_num_types!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64);