Move BoolParam to its own module
This commit is contained in:
parent
287576d064
commit
5a26756765
165
src/param.rs
165
src/param.rs
|
@ -3,17 +3,18 @@
|
|||
//! example.
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::sync::Arc;
|
||||
|
||||
use self::range::Range;
|
||||
|
||||
// Parameter types
|
||||
mod boolean;
|
||||
mod plain;
|
||||
|
||||
pub mod internals;
|
||||
pub mod range;
|
||||
pub mod smoothing;
|
||||
|
||||
pub use boolean::BoolParam;
|
||||
pub use plain::{FloatParam, IntParam};
|
||||
|
||||
// Re-export for the [EnumParam]
|
||||
|
@ -75,28 +76,6 @@ pub trait Param: Display {
|
|||
fn as_ptr(&self) -> internals::ParamPtr;
|
||||
}
|
||||
|
||||
/// A simple boolean parmaeter.
|
||||
#[repr(C, align(4))]
|
||||
pub struct BoolParam {
|
||||
/// The field's current, normalized value. Should be initialized with the default value.
|
||||
pub value: bool,
|
||||
|
||||
/// Optional callback for listening to value changes. The argument passed to this function is
|
||||
/// the parameter's new value. This should not do anything expensive as it may be called
|
||||
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
||||
/// thread.
|
||||
pub value_changed: Option<Arc<dyn Fn(bool) + Send + Sync>>,
|
||||
|
||||
/// The parameter's human readable display name.
|
||||
pub name: &'static str,
|
||||
/// Optional custom conversion function from a boolean value to a string.
|
||||
pub value_to_string: Option<Arc<dyn Fn(bool) -> String + Send + Sync>>,
|
||||
/// Optional custom conversion function from a string to a boolean value. If the string cannot
|
||||
/// be parsed, then this should return a `None`. If this happens while the parameter is being
|
||||
/// updated then the update will be canceled.
|
||||
pub string_to_value: Option<Arc<dyn Fn(&str) -> Option<bool> + Send + Sync>>,
|
||||
}
|
||||
|
||||
/// An [IntParam]-backed categorical parameter that allows convenient conversion to and from a
|
||||
/// simple enum. This enum must derive the re-exported [EnumIter] and [EnumMessage] and [Display]
|
||||
/// traits. You can use the `#[strum(message = "Foo Bar")]` to override the name of the variant.
|
||||
|
@ -112,19 +91,6 @@ pub struct EnumParam<T: EnumIter + EnumMessage + Eq + Copy + Display> {
|
|||
variants: Vec<(T, String)>,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for BoolParam {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
value: false,
|
||||
value_changed: None,
|
||||
name: "",
|
||||
value_to_string: None,
|
||||
string_to_value: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EnumIter + EnumMessage + Eq + Copy + Display + Default> Default for EnumParam<T> {
|
||||
fn default() -> Self {
|
||||
let variants: Vec<_> = Self::build_variants();
|
||||
|
@ -147,82 +113,6 @@ impl<T: EnumIter + EnumMessage + Eq + Copy + Display + Default> Default for Enum
|
|||
}
|
||||
}
|
||||
|
||||
impl Param for BoolParam {
|
||||
type Plain = bool;
|
||||
|
||||
fn update_smoother(&mut self, _sample_rate: f32, _init: bool) {
|
||||
// Can't really smooth a binary parameter now can you
|
||||
}
|
||||
|
||||
fn set_from_string(&mut self, string: &str) -> bool {
|
||||
let value = match &self.string_to_value {
|
||||
Some(f) => f(string),
|
||||
None => Some(string.eq_ignore_ascii_case("true") || string.eq_ignore_ascii_case("on")),
|
||||
};
|
||||
|
||||
match value {
|
||||
Some(plain) => {
|
||||
self.set_plain_value(plain);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn plain_value(&self) -> Self::Plain {
|
||||
self.value
|
||||
}
|
||||
|
||||
fn set_plain_value(&mut self, plain: Self::Plain) {
|
||||
self.value = plain;
|
||||
if let Some(f) = &self.value_changed {
|
||||
f(plain);
|
||||
}
|
||||
}
|
||||
|
||||
fn normalized_value(&self) -> f32 {
|
||||
self.preview_normalized(self.value)
|
||||
}
|
||||
|
||||
fn set_normalized_value(&mut self, normalized: f32) {
|
||||
self.set_plain_value(self.preview_plain(normalized));
|
||||
}
|
||||
|
||||
fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {
|
||||
let value = self.preview_plain(normalized);
|
||||
match (value, &self.value_to_string) {
|
||||
(v, Some(f)) => f(v),
|
||||
(true, None) => String::from("On"),
|
||||
(false, None) => String::from("Off"),
|
||||
}
|
||||
}
|
||||
|
||||
fn string_to_normalized_value(&self, string: &str) -> Option<f32> {
|
||||
let value = match &self.string_to_value {
|
||||
Some(f) => f(string),
|
||||
None => Some(string.eq_ignore_ascii_case("true") || string.eq_ignore_ascii_case("on")),
|
||||
}?;
|
||||
|
||||
Some(self.preview_normalized(value))
|
||||
}
|
||||
|
||||
fn preview_normalized(&self, plain: Self::Plain) -> f32 {
|
||||
if plain {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
fn preview_plain(&self, normalized: f32) -> Self::Plain {
|
||||
normalized > 0.5
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> internals::ParamPtr {
|
||||
internals::ParamPtr::BoolParam(self as *const BoolParam as *mut BoolParam)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> Param for EnumParam<T> {
|
||||
type Plain = T;
|
||||
|
||||
|
@ -287,63 +177,12 @@ impl<T: EnumIter + EnumMessage + Eq + Copy + Display> Param for EnumParam<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for BoolParam {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match (self.value, &self.value_to_string) {
|
||||
(v, Some(func)) => write!(f, "{}", func(v)),
|
||||
(true, None) => write!(f, "On"),
|
||||
(false, None) => write!(f, "Off"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> Display for EnumParam<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.variants[self.inner.plain_value() as usize].1)
|
||||
}
|
||||
}
|
||||
|
||||
impl BoolParam {
|
||||
/// Build a new [Self]. Use the other associated functions to modify the behavior of the
|
||||
/// parameter.
|
||||
pub fn new(name: &'static str, default: bool) -> Self {
|
||||
Self {
|
||||
value: default,
|
||||
name,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a callback whenever this parameter's value changes. The argument passed to this function
|
||||
/// is the parameter's new value. This should not do anything expensive as it may be called
|
||||
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
||||
/// thread.
|
||||
pub fn with_callback(mut self, callback: Arc<dyn Fn(bool) + Send + Sync>) -> Self {
|
||||
self.value_changed = Some(callback);
|
||||
self
|
||||
}
|
||||
|
||||
/// Use a custom conversion function to convert the boolean value to a string.
|
||||
pub fn with_value_to_string(
|
||||
mut self,
|
||||
callback: Arc<dyn Fn(bool) -> String + Send + Sync>,
|
||||
) -> Self {
|
||||
self.value_to_string = Some(callback);
|
||||
self
|
||||
}
|
||||
|
||||
/// Use a custom conversion function to convert from a string to a boolean value. If the string
|
||||
/// cannot be parsed, then this should return a `None`. If this happens while the parameter is
|
||||
/// being updated then the update will be canceled.
|
||||
pub fn with_string_to_value(
|
||||
mut self,
|
||||
callback: Arc<dyn Fn(&str) -> Option<bool> + Send + Sync>,
|
||||
) -> Self {
|
||||
self.string_to_value = Some(callback);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> EnumParam<T> {
|
||||
/// Build a new [Self]. Use the other associated functions to modify the behavior of the
|
||||
/// parameter.
|
||||
|
|
169
src/param/boolean.rs
Normal file
169
src/param/boolean.rs
Normal file
|
@ -0,0 +1,169 @@
|
|||
//! Simple boolean parameters.
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::internals::ParamPtr;
|
||||
use super::Param;
|
||||
|
||||
/// A simple boolean parmaeter.
|
||||
#[repr(C, align(4))]
|
||||
pub struct BoolParam {
|
||||
/// The field's current, normalized value. Should be initialized with the default value.
|
||||
pub value: bool,
|
||||
|
||||
/// Optional callback for listening to value changes. The argument passed to this function is
|
||||
/// the parameter's new value. This should not do anything expensive as it may be called
|
||||
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
||||
/// thread.
|
||||
pub value_changed: Option<Arc<dyn Fn(bool) + Send + Sync>>,
|
||||
|
||||
/// The parameter's human readable display name.
|
||||
pub name: &'static str,
|
||||
/// Optional custom conversion function from a boolean value to a string.
|
||||
pub value_to_string: Option<Arc<dyn Fn(bool) -> String + Send + Sync>>,
|
||||
/// Optional custom conversion function from a string to a boolean value. If the string cannot
|
||||
/// be parsed, then this should return a `None`. If this happens while the parameter is being
|
||||
/// updated then the update will be canceled.
|
||||
pub string_to_value: Option<Arc<dyn Fn(&str) -> Option<bool> + Send + Sync>>,
|
||||
}
|
||||
|
||||
#[allow(clippy::derivable_impls)]
|
||||
impl Default for BoolParam {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
value: false,
|
||||
value_changed: None,
|
||||
name: "",
|
||||
value_to_string: None,
|
||||
string_to_value: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BoolParam {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match (self.value, &self.value_to_string) {
|
||||
(v, Some(func)) => write!(f, "{}", func(v)),
|
||||
(true, None) => write!(f, "On"),
|
||||
(false, None) => write!(f, "Off"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Param for BoolParam {
|
||||
type Plain = bool;
|
||||
|
||||
fn update_smoother(&mut self, _sample_rate: f32, _init: bool) {
|
||||
// Can't really smooth a binary parameter now can you
|
||||
}
|
||||
|
||||
fn set_from_string(&mut self, string: &str) -> bool {
|
||||
let value = match &self.string_to_value {
|
||||
Some(f) => f(string),
|
||||
None => Some(string.eq_ignore_ascii_case("true") || string.eq_ignore_ascii_case("on")),
|
||||
};
|
||||
|
||||
match value {
|
||||
Some(plain) => {
|
||||
self.set_plain_value(plain);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn plain_value(&self) -> Self::Plain {
|
||||
self.value
|
||||
}
|
||||
|
||||
fn set_plain_value(&mut self, plain: Self::Plain) {
|
||||
self.value = plain;
|
||||
if let Some(f) = &self.value_changed {
|
||||
f(plain);
|
||||
}
|
||||
}
|
||||
|
||||
fn normalized_value(&self) -> f32 {
|
||||
self.preview_normalized(self.value)
|
||||
}
|
||||
|
||||
fn set_normalized_value(&mut self, normalized: f32) {
|
||||
self.set_plain_value(self.preview_plain(normalized));
|
||||
}
|
||||
|
||||
fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {
|
||||
let value = self.preview_plain(normalized);
|
||||
match (value, &self.value_to_string) {
|
||||
(v, Some(f)) => f(v),
|
||||
(true, None) => String::from("On"),
|
||||
(false, None) => String::from("Off"),
|
||||
}
|
||||
}
|
||||
|
||||
fn string_to_normalized_value(&self, string: &str) -> Option<f32> {
|
||||
let value = match &self.string_to_value {
|
||||
Some(f) => f(string),
|
||||
None => Some(string.eq_ignore_ascii_case("true") || string.eq_ignore_ascii_case("on")),
|
||||
}?;
|
||||
|
||||
Some(self.preview_normalized(value))
|
||||
}
|
||||
|
||||
fn preview_normalized(&self, plain: Self::Plain) -> f32 {
|
||||
if plain {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
fn preview_plain(&self, normalized: f32) -> Self::Plain {
|
||||
normalized > 0.5
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> ParamPtr {
|
||||
ParamPtr::BoolParam(self as *const BoolParam as *mut BoolParam)
|
||||
}
|
||||
}
|
||||
|
||||
impl BoolParam {
|
||||
/// Build a new [Self]. Use the other associated functions to modify the behavior of the
|
||||
/// parameter.
|
||||
pub fn new(name: &'static str, default: bool) -> Self {
|
||||
Self {
|
||||
value: default,
|
||||
name,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a callback whenever this parameter's value changes. The argument passed to this function
|
||||
/// is the parameter's new value. This should not do anything expensive as it may be called
|
||||
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
||||
/// thread.
|
||||
pub fn with_callback(mut self, callback: Arc<dyn Fn(bool) + Send + Sync>) -> Self {
|
||||
self.value_changed = Some(callback);
|
||||
self
|
||||
}
|
||||
|
||||
/// Use a custom conversion function to convert the boolean value to a string.
|
||||
pub fn with_value_to_string(
|
||||
mut self,
|
||||
callback: Arc<dyn Fn(bool) -> String + Send + Sync>,
|
||||
) -> Self {
|
||||
self.value_to_string = Some(callback);
|
||||
self
|
||||
}
|
||||
|
||||
/// Use a custom conversion function to convert from a string to a boolean value. If the string
|
||||
/// cannot be parsed, then this should return a `None`. If this happens while the parameter is
|
||||
/// being updated then the update will be canceled.
|
||||
pub fn with_string_to_value(
|
||||
mut self,
|
||||
callback: Arc<dyn Fn(&str) -> Option<bool> + Send + Sync>,
|
||||
) -> Self {
|
||||
self.string_to_value = Some(callback);
|
||||
self
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue