From 4f9a83860b7416c37c325fe2a75ca724b80b4f01 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sun, 20 Mar 2022 01:12:10 +0100 Subject: [PATCH] Replace Binding with two display properties --- Cargo.lock | 8 +- nih_plug_vizia/src/widgets/param_slider.rs | 211 ++++++++++----------- 2 files changed, 105 insertions(+), 114 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 243bb2b4..d55c4d59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3605,7 +3605,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vizia" version = "0.1.0" -source = "git+https://github.com/robbert-vdh/vizia.git?branch=feature/baseview-modifiers#dd14c83c4f70b19d00ae397dcc902cadd5464907" +source = "git+https://github.com/robbert-vdh/vizia.git?branch=feature/baseview-modifiers#8247518a4d74d741ad27334fc48ba961f43134ff" dependencies = [ "vizia_baseview", "vizia_core", @@ -3614,7 +3614,7 @@ dependencies = [ [[package]] name = "vizia_baseview" version = "0.1.0" -source = "git+https://github.com/robbert-vdh/vizia.git?branch=feature/baseview-modifiers#dd14c83c4f70b19d00ae397dcc902cadd5464907" +source = "git+https://github.com/robbert-vdh/vizia.git?branch=feature/baseview-modifiers#8247518a4d74d741ad27334fc48ba961f43134ff" dependencies = [ "baseview", "femtovg", @@ -3626,7 +3626,7 @@ dependencies = [ [[package]] name = "vizia_core" version = "0.1.0" -source = "git+https://github.com/robbert-vdh/vizia.git?branch=feature/baseview-modifiers#dd14c83c4f70b19d00ae397dcc902cadd5464907" +source = "git+https://github.com/robbert-vdh/vizia.git?branch=feature/baseview-modifiers#8247518a4d74d741ad27334fc48ba961f43134ff" dependencies = [ "bitflags", "copypasta", @@ -3649,7 +3649,7 @@ dependencies = [ [[package]] name = "vizia_derive" version = "0.1.0" -source = "git+https://github.com/robbert-vdh/vizia.git?branch=feature/baseview-modifiers#dd14c83c4f70b19d00ae397dcc902cadd5464907" +source = "git+https://github.com/robbert-vdh/vizia.git?branch=feature/baseview-modifiers#8247518a4d74d741ad27334fc48ba961f43134ff" dependencies = [ "proc-macro2", "quote", diff --git a/nih_plug_vizia/src/widgets/param_slider.rs b/nih_plug_vizia/src/widgets/param_slider.rs index e7a856e7..239fb45d 100644 --- a/nih_plug_vizia/src/widgets/param_slider.rs +++ b/nih_plug_vizia/src/widgets/param_slider.rs @@ -146,122 +146,113 @@ impl ParamSlider { && step_count.is_none() && (0.45..=0.55).contains(&default_value); - Binding::new( - cx, - ParamSliderInternal::text_input_active, - move |cx, text_input_active| { - let param_display_value_lens = - params.map(move |params| params_to_param(params).to_string()); - let param_preview_display_value_lens = |normalized_value| { - params.map(move |params| { - params_to_param(params) - .normalized_value_to_string(normalized_value, true) - }) - }; - let normalized_param_value_lens = - params.map(move |params| params_to_param(params).normalized_value()); + let param_display_value_lens = + params.map(move |params| params_to_param(params).to_string()); + let param_preview_display_value_lens = |normalized_value| { + params.map(move |params| { + params_to_param(params).normalized_value_to_string(normalized_value, true) + }) + }; + let normalized_param_value_lens = + params.map(move |params| params_to_param(params).normalized_value()); - // Only draw the text input widget when it gets focussed. Otherwise, overlay the - // label with the slider. - if *text_input_active.get(cx) { - Textbox::new(cx, param_display_value_lens) - .class("value-entry") - .on_submit(|cx, string| { - cx.emit(ParamSliderEvent::TextInput(string)) - }) - .on_focus_out(|cx| cx.emit(ParamSliderEvent::CancelTextInput)) - .child_space(Stretch(1.0)) - .height(Stretch(1.0)) - .width(Stretch(1.0)); - } else { - ZStack::new(cx, move |cx| { - // The filled bar portion. This can be visualized in a couple different - // ways depending on the current style property. See - // [`ParamSliderStyle`]. - Element::new(cx) - .class("fill") + // Only draw the text input widget when it gets focussed. Otherwise, overlay the + // label with the slider. We need to always include the text input widget in the + // tree because using a `Binding` here would cause the text box to get recreated + // whenever `ParamSliderInternal::text_input_active` changes. + Textbox::new(cx, param_display_value_lens.clone()) + .class("value-entry") + .on_submit(|cx, string| cx.emit(ParamSliderEvent::TextInput(string))) + .on_focus_out(|cx| cx.emit(ParamSliderEvent::CancelTextInput)) + .display(ParamSliderInternal::text_input_active) + .child_space(Stretch(1.0)) + .height(Stretch(1.0)) + .width(Stretch(1.0)); + + // This only gets shown when the text box isn't active + ZStack::new(cx, move |cx| { + // The filled bar portion. This can be visualized in a couple different + // ways depending on the current style property. See + // [`ParamSliderStyle`]. + Element::new(cx) + .class("fill") + .height(Stretch(1.0)) + .bind(normalized_param_value_lens, move |handle, value| { + let current_value = *value.get(handle.cx); + let (start_t, delta) = match style { + ParamSliderStyle::Centered if draw_fill_from_default => { + let delta = (default_value - current_value).abs(); + ( + default_value.min(current_value), + // Don't draw the filled portion at all if it could have been a + // rounding error since those slivers just look weird + if delta >= 1e-3 { delta } else { 0.0 }, + ) + } + ParamSliderStyle::Centered | ParamSliderStyle::FromLeft => { + (0.0, current_value) + } + ParamSliderStyle::CurrentStep + | ParamSliderStyle::CurrentStepLabeled => { + let previous_step = unsafe { + param_ptr.previous_normalized_step(current_value) + }; + let next_step = + unsafe { param_ptr.next_normalized_step(current_value) }; + ( + (previous_step + current_value) / 2.0, + (next_step + current_value) / 2.0, + ) + } + }; + + handle + .left(Percentage(start_t * 100.0)) + .width(Percentage(delta * 100.0)); + }) + // Hovering is handled on the param slider as a whole, this should + // not affect that + .hoverable(false); + + // Either display the current value, or display all values over the + // parameter's steps + // TODO: Do the same thing as in the iced widget where we draw the + // text overlapping the fill area slightly differently. We can + // set the cip region directly in vizia. + match (style, step_count) { + (ParamSliderStyle::CurrentStepLabeled, Some(step_count)) => { + HStack::new(cx, |cx| { + // There are step_count + 1 possible values for a + // discrete parameter + for value in 0..step_count + 1 { + let normalized_value = value as f32 / step_count as f32; + Label::new( + cx, + param_preview_display_value_lens(normalized_value), + ) + .class("value") + .class("value--multiple") .height(Stretch(1.0)) - .bind(normalized_param_value_lens, move |handle, value| { - let current_value = *value.get(handle.cx); - let (start_t, delta) = match style { - ParamSliderStyle::Centered - if draw_fill_from_default => - { - let delta = (default_value - current_value).abs(); - ( - default_value.min(current_value), - // Don't draw the filled portion at all if it could have been a - // rounding error since those slivers just look weird - if delta >= 1e-3 { delta } else { 0.0 }, - ) - } - ParamSliderStyle::Centered - | ParamSliderStyle::FromLeft => (0.0, current_value), - ParamSliderStyle::CurrentStep - | ParamSliderStyle::CurrentStepLabeled => { - let previous_step = unsafe { - param_ptr - .previous_normalized_step(current_value) - }; - let next_step = unsafe { - param_ptr.next_normalized_step(current_value) - }; - ( - (previous_step + current_value) / 2.0, - (next_step + current_value) / 2.0, - ) - } - }; - - handle - .left(Percentage(start_t * 100.0)) - .width(Percentage(delta * 100.0)); - }) - // Hovering is handled on the param slider as a whole, this should - // not affect that + .width(Stretch(1.0)) .hoverable(false); - - // Either display the current value, or display all values over the - // parameter's steps - match (style, step_count) { - (ParamSliderStyle::CurrentStepLabeled, Some(step_count)) => { - HStack::new(cx, |cx| { - // There are step_count + 1 possible values for a - // discrete parameter - for value in 0..step_count + 1 { - let normalized_value = - value as f32 / step_count as f32; - Label::new( - cx, - param_preview_display_value_lens( - normalized_value, - ), - ) - .class("value") - .class("value--multiple") - .height(Stretch(1.0)) - .width(Stretch(1.0)) - .hoverable(false); - } - }) - .height(Stretch(1.0)) - .width(Stretch(1.0)) - .hoverable(false); - } - _ => { - Label::new(cx, param_display_value_lens) - .class("value") - .class("value--single") - .height(Stretch(1.0)) - .width(Stretch(1.0)) - .hoverable(false); - } - }; + } }) + .height(Stretch(1.0)) + .width(Stretch(1.0)) .hoverable(false); } - }, - ); + _ => { + Label::new(cx, param_display_value_lens) + .class("value") + .class("value--single") + .height(Stretch(1.0)) + .width(Stretch(1.0)) + .hoverable(false); + } + }; + }) + .display(ParamSliderInternal::text_input_active.map(|active| !active)) + .hoverable(false); }); }) }