Fix granular drag when clicking with shift held
This commit is contained in:
parent
986e93b8d0
commit
304b9bdfeb
|
@ -9,10 +9,13 @@ use nih_plug::prelude::{GuiContext, Param, ParamSetter};
|
|||
use super::util;
|
||||
use super::ParamMessage;
|
||||
|
||||
/// When shift+dragging a parameter, one pixel dragged corresponds to this much change in the
|
||||
/// noramlized parameter.
|
||||
const GRANULAR_DRAG_MULTIPLIER: f32 = 0.1;
|
||||
|
||||
/// A slider that integrates with NIH-plug's [`Param`] types.
|
||||
///
|
||||
/// TODO: There are currently no styling options at all
|
||||
/// TODO: Handle Shift+drag for granular drag
|
||||
/// TODO: Handle Alt+click for text entry
|
||||
pub struct ParamSlider<'a, P: Param, Renderer: text::Renderer> {
|
||||
state: &'a mut State,
|
||||
|
@ -31,8 +34,11 @@ pub struct ParamSlider<'a, P: Param, Renderer: text::Renderer> {
|
|||
/// State for a [`ParamSlider`].
|
||||
#[derive(Debug, Default)]
|
||||
pub struct State {
|
||||
drag_active: bool,
|
||||
keyboard_modifiers: keyboard::Modifiers,
|
||||
drag_active: bool,
|
||||
/// We keep track of the start coordinate holding down Shift while dragging for higher precision
|
||||
/// dragging. This is a `None` value when granular dragging is not active.
|
||||
granular_drag_start_x: Option<f32>,
|
||||
/// Track clicks for double clicks.
|
||||
last_click: Option<mouse::Click>,
|
||||
/// Will be set to `true` if we just reset the parameter since you could otherwise reset the
|
||||
|
@ -117,25 +123,35 @@ impl<'a, P: Param, Renderer: text::Renderer> Widget<ParamMessage, Renderer>
|
|||
| Event::Touch(touch::Event::FingerPressed { .. }) => {
|
||||
if bounds.contains(cursor_position) {
|
||||
shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr()));
|
||||
|
||||
self.state.drag_active = true;
|
||||
|
||||
// Immediately trigger a parameter update if the value would be different, or
|
||||
// reset the parameter if Ctrl is held or the parameter is being double clicked
|
||||
let click = mouse::Click::new(cursor_position, self.state.last_click);
|
||||
self.state.last_click = Some(click);
|
||||
if self.state.keyboard_modifiers.control()
|
||||
if self.state.keyboard_modifiers.command()
|
||||
|| matches!(click.kind(), mouse::click::Kind::Double)
|
||||
{
|
||||
// Immediately trigger a parameter update if the value would be different, or
|
||||
// reset the parameter if Ctrl is held or the parameter is being double clicked
|
||||
self.set_normalized_value(
|
||||
shell,
|
||||
self.setter.default_normalized_param_value(self.param),
|
||||
);
|
||||
self.state.ignore_changes = true;
|
||||
} else if self.state.keyboard_modifiers.shift() {
|
||||
// When holding down shift while clicking on a parameter we want to
|
||||
// granuarly edit the parameter without jumping to a new value
|
||||
self.state.granular_drag_start_x =
|
||||
Some(util::remap_rect_x_t(&bounds, self.param.normalized_value()));
|
||||
|
||||
self.state.ignore_changes = false;
|
||||
} else {
|
||||
self.set_normalized_value(
|
||||
shell,
|
||||
util::remap_rect_x_coordinate(&bounds, cursor_position.x),
|
||||
);
|
||||
self.state.granular_drag_start_x = None;
|
||||
|
||||
self.state.ignore_changes = false;
|
||||
}
|
||||
|
||||
|
@ -146,6 +162,7 @@ impl<'a, P: Param, Renderer: text::Renderer> Widget<ParamMessage, Renderer>
|
|||
| Event::Touch(touch::Event::FingerLifted { .. } | touch::Event::FingerLost { .. }) => {
|
||||
if bounds.contains(cursor_position) {
|
||||
shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr()));
|
||||
|
||||
self.state.drag_active = false;
|
||||
|
||||
return event::Status::Captured;
|
||||
|
@ -158,10 +175,30 @@ impl<'a, P: Param, Renderer: text::Renderer> Widget<ParamMessage, Renderer>
|
|||
&& self.state.drag_active
|
||||
&& bounds.contains(cursor_position)
|
||||
{
|
||||
// If shift is being held then the drag should be more granular instead of
|
||||
// absolute
|
||||
if self.state.keyboard_modifiers.shift() {
|
||||
let drag_start_x = *self
|
||||
.state
|
||||
.granular_drag_start_x
|
||||
.get_or_insert(cursor_position.x);
|
||||
|
||||
self.set_normalized_value(
|
||||
shell,
|
||||
util::remap_rect_x_coordinate(
|
||||
&bounds,
|
||||
drag_start_x
|
||||
+ (cursor_position.x - drag_start_x) * GRANULAR_DRAG_MULTIPLIER,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
self.state.granular_drag_start_x = None;
|
||||
|
||||
self.set_normalized_value(
|
||||
shell,
|
||||
util::remap_rect_x_coordinate(&bounds, cursor_position.x),
|
||||
);
|
||||
}
|
||||
|
||||
return event::Status::Captured;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue