Add methods for custom number formatting in DragValue
and Slider
(#1851)
This commit is contained in:
parent
c02fbfe973
commit
36cdae98df
2 changed files with 68 additions and 8 deletions
|
@ -27,6 +27,10 @@ impl MonoState {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type NumFormatter<'a> = Box<dyn 'a + Fn(f64, RangeInclusive<usize>) -> String>;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Combined into one function (rather than two) to make it easier
|
||||
/// for the borrow checker.
|
||||
type GetSetValue<'a> = Box<dyn 'a + FnMut(Option<f64>) -> f64>;
|
||||
|
@ -56,6 +60,7 @@ pub struct DragValue<'a> {
|
|||
clamp_range: RangeInclusive<f64>,
|
||||
min_decimals: usize,
|
||||
max_decimals: Option<usize>,
|
||||
custom_formatter: Option<NumFormatter<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> DragValue<'a> {
|
||||
|
@ -85,6 +90,7 @@ impl<'a> DragValue<'a> {
|
|||
clamp_range: f64::NEG_INFINITY..=f64::INFINITY,
|
||||
min_decimals: 0,
|
||||
max_decimals: None,
|
||||
custom_formatter: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +151,25 @@ impl<'a> DragValue<'a> {
|
|||
self.max_decimals = Some(num_decimals);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set custom formatter defining how numbers are converted into text.
|
||||
///
|
||||
/// A custom formatter takes a `f64` for the numeric value and a `RangeInclusive<usize>` representing
|
||||
/// the decimal range i.e. minimum and maximum number of decimal places shown.
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// # let mut my_i64: i64 = 0;
|
||||
/// ui.add(egui::DragValue::new(&mut my_i64).custom_formatter(|n, _| format!("{:X}", n as i64)));
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn custom_formatter(
|
||||
mut self,
|
||||
formatter: impl 'a + Fn(f64, RangeInclusive<usize>) -> String,
|
||||
) -> Self {
|
||||
self.custom_formatter = Some(Box::new(formatter));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for DragValue<'a> {
|
||||
|
@ -157,6 +182,7 @@ impl<'a> Widget for DragValue<'a> {
|
|||
suffix,
|
||||
min_decimals,
|
||||
max_decimals,
|
||||
custom_formatter,
|
||||
} = self;
|
||||
|
||||
let shift = ui.input().modifiers.shift_only();
|
||||
|
@ -174,10 +200,15 @@ impl<'a> Widget for DragValue<'a> {
|
|||
|
||||
let max_decimals = max_decimals.unwrap_or(auto_decimals + 2);
|
||||
let auto_decimals = auto_decimals.clamp(min_decimals, max_decimals);
|
||||
let value_text = if value == 0.0 {
|
||||
let value_text = match custom_formatter {
|
||||
Some(custom_formatter) => custom_formatter(value, auto_decimals..=max_decimals),
|
||||
None => {
|
||||
if value == 0.0 {
|
||||
"0".to_owned()
|
||||
} else {
|
||||
emath::format_with_decimals_in_range(value, auto_decimals..=max_decimals)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let kb_edit_id = ui.next_auto_id();
|
||||
|
|
|
@ -6,6 +6,10 @@ use crate::*;
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
type NumFormatter<'a> = Box<dyn 'a + Fn(f64, RangeInclusive<usize>) -> String>;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Combined into one function (rather than two) to make it easier
|
||||
/// for the borrow checker.
|
||||
type GetSetValue<'a> = Box<dyn 'a + FnMut(Option<f64>) -> f64>;
|
||||
|
@ -75,6 +79,7 @@ pub struct Slider<'a> {
|
|||
step: Option<f64>,
|
||||
min_decimals: usize,
|
||||
max_decimals: Option<usize>,
|
||||
custom_formatter: Option<NumFormatter<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> Slider<'a> {
|
||||
|
@ -118,6 +123,7 @@ impl<'a> Slider<'a> {
|
|||
step: None,
|
||||
min_decimals: 0,
|
||||
max_decimals: None,
|
||||
custom_formatter: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,6 +247,25 @@ impl<'a> Slider<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Set custom formatter defining how numbers are converted into text.
|
||||
///
|
||||
/// A custom formatter takes a `f64` for the numeric value and a `RangeInclusive<usize>` representing
|
||||
/// the decimal range i.e. minimum and maximum number of decimal places shown.
|
||||
///
|
||||
/// ```
|
||||
/// # egui::__run_test_ui(|ui| {
|
||||
/// # let mut my_i64: i64 = 0;
|
||||
/// ui.add(egui::Slider::new(&mut my_i64, 0..=100).custom_formatter(|n, _| format!("{:X}", n as i64)));
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn custom_formatter(
|
||||
mut self,
|
||||
formatter: impl 'a + Fn(f64, RangeInclusive<usize>) -> String,
|
||||
) -> Self {
|
||||
self.custom_formatter = Some(Box::new(formatter));
|
||||
self
|
||||
}
|
||||
|
||||
/// Helper: equivalent to `self.precision(0).smallest_positive(1.0)`.
|
||||
/// If you use one of the integer constructors (e.g. `Slider::i32`) this is called for you,
|
||||
/// but if you want to have a slider for picking integer values in an `Slider::f64`, use this.
|
||||
|
@ -465,15 +490,19 @@ impl<'a> Slider<'a> {
|
|||
_ => self.current_gradient(&position_range),
|
||||
};
|
||||
let mut value = self.get_value();
|
||||
let response = ui.add(
|
||||
DragValue::new(&mut value)
|
||||
let response = ui.add({
|
||||
let dv = DragValue::new(&mut value)
|
||||
.speed(speed)
|
||||
.clamp_range(self.clamp_range())
|
||||
.min_decimals(self.min_decimals)
|
||||
.max_decimals_opt(self.max_decimals)
|
||||
.suffix(self.suffix.clone())
|
||||
.prefix(self.prefix.clone()),
|
||||
);
|
||||
.prefix(self.prefix.clone());
|
||||
match &self.custom_formatter {
|
||||
Some(fmt) => dv.custom_formatter(fmt),
|
||||
None => dv,
|
||||
}
|
||||
});
|
||||
if value != self.get_value() {
|
||||
self.set_value(value);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue