1
0
Fork 0

Update the Diopser XY pad

The translation can now be done from the stylesheet, in percentages.
This commit is contained in:
Robbert van der Helm 2023-11-14 23:40:26 +01:00
parent 669edc1df5
commit 762844f8f6
2 changed files with 38 additions and 47 deletions

View file

@ -83,8 +83,11 @@ xy-pad .xy-pad__value-entry .selection {
xy-pad__handle {
background-color: #e5e5e5;
border-color: #0a0a0a;
border-width: 1px;
border-radius: 50%;
border-width: 1px;
height: 20px;
translate: -50% -50%;
width: 20px;
}
.xy-pad__handle--modulated {
background-color: #a4eafc69;

View file

@ -25,10 +25,6 @@ use crate::params;
/// normalized parameter.
const GRANULAR_DRAG_MULTIPLIER: f32 = 0.1;
// TODO: Vizia doesn't let you do this -50% translation programmatically yet, so this is hardcoded
// for now
const HANDLE_WIDTH_PX: f32 = 20.0;
/// An X-Y pad that controlers two parameters at the same time by binding them to one of the two
/// axes. This specific implementation has a tooltip for the X-axis parameter and allows
/// Alt+clicking to enter a specific value.
@ -123,8 +119,8 @@ impl XyPad {
FMap2: Fn(&Params) -> &P2 + Copy + 'static,
{
Self {
x_param_base: ParamWidgetBase::new(cx, params.clone(), params_to_x_param),
y_param_base: ParamWidgetBase::new(cx, params.clone(), params_to_y_param),
x_param_base: ParamWidgetBase::new(cx, params, params_to_x_param),
y_param_base: ParamWidgetBase::new(cx, params, params_to_y_param),
frequency_range: params::filter_frequency_range(),
x_renormalize_display: Box::new(x_renormalize_display.clone()),
@ -143,7 +139,7 @@ impl XyPad {
// We need to create lenses for both the x-parameter's values and the y-parameter's
// values
ParamWidgetBase::build_view(
params.clone(),
params,
params_to_x_param,
move |cx, x_param_data| {
ParamWidgetBase::view(
@ -200,19 +196,19 @@ impl XyPad {
XyPad::text_input_active,
move |cx, text_input_active| {
if text_input_active.get(cx) {
Self::text_input_view(cx, x_display_value_lens.clone());
Self::text_input_view(cx, x_display_value_lens);
} else {
Self::xy_pad_modulation_handle_view(
cx,
modulated_x_position_lens.clone(),
modulated_y_position_lens.clone(),
modulated_x_position_lens,
modulated_y_position_lens,
);
Self::xy_pad_handle_view(
cx,
x_position_lens.clone(),
y_position_lens.clone(),
x_display_value_lens.clone(),
y_display_value_lens.clone(),
x_position_lens,
y_position_lens,
x_display_value_lens,
y_display_value_lens,
);
}
},
@ -255,11 +251,6 @@ impl XyPad {
.position_type(PositionType::SelfDirected)
.top(y_position_lens)
.left(x_position_lens)
// TODO: It would be much nicer if this could be set in the
// stylesheet, but Vizia doesn't support that right now
.translate((-(HANDLE_WIDTH_PX / 2.0), -(HANDLE_WIDTH_PX / 2.0)))
.width(Pixels(HANDLE_WIDTH_PX))
.height(Pixels(HANDLE_WIDTH_PX))
.hoverable(false);
// The stylesheet makes the tooltip visible when hovering over the X-Y
@ -282,7 +273,7 @@ impl XyPad {
// When a new parameter value causes the width of the tooltip to
// change, we must recompute its position so it stays anchored to
// the mouse cursor
if change_flags.intersects(GeometryChanged::WIDTH_CHANGED) {
if change_flags.intersects(GeoChanged::WIDTH_CHANGED) {
cx.emit(XyPadEvent::TooltipWidthChanged);
}
})
@ -301,9 +292,6 @@ impl XyPad {
.position_type(PositionType::SelfDirected)
.top(modulated_y_position_lens)
.left(modulated_x_position_lens)
.translate((-(HANDLE_WIDTH_PX / 2.0), -(HANDLE_WIDTH_PX / 2.0)))
.width(Pixels(HANDLE_WIDTH_PX))
.height(Pixels(HANDLE_WIDTH_PX))
.hoverable(false);
}
@ -370,23 +358,19 @@ impl XyPad {
/// space there, the tooltip will be pushed to the left or the right of the cursor.
fn update_tooltip_pos(&mut self, cx: &mut EventContext) {
let bounds = cx.cache.get_bounds(cx.current());
let relative_x = cx.mouse.cursorx - bounds.x;
let relative_y = cx.mouse.cursory - bounds.y;
let relative_x = cx.mouse().cursorx - bounds.x;
let relative_y = cx.mouse().cursory - bounds.y;
// These positions need to take DPI scaling into account
let dpi_scale = cx.style.dpi_factor as f32;
let dpi_scale = cx.scale_factor();
let padding = 2.0 * dpi_scale;
// If there's not enough space at the top right, we'll move the tooltip to the
// bottom and/or the left
// NOTE: This is hardcoded to find the tooltip. The Binding also counts as a child.
let binding_entity = cx
.tree
.get_last_child(cx.current())
.expect("Missing child view in X-Y pad");
let binding_entity = cx.last_child().expect("Missing child view in X-Y pad");
let tooltip_entity = cx
.tree
.get_last_child(binding_entity)
.with_current(binding_entity, |cx| cx.last_child())
.expect("Missing child view in X-Y pad binding");
let tooltip_bounds = cx.cache.get_bounds(tooltip_entity);
// NOTE: The width can vary drastically depending on the frequency value, so we'll
@ -463,11 +447,11 @@ impl View for XyPad {
event.map(|window_event, meta| match window_event {
WindowEvent::MouseDown(MouseButton::Left)
| WindowEvent::MouseTripleClick(MouseButton::Left) => {
if cx.modifiers.alt() {
if cx.modifiers().alt() {
// ALt+Click brings up a text entry dialog
self.text_input_active = true;
cx.set_active(true);
} else if cx.modifiers.command() {
} else if cx.modifiers().command() {
// Ctrl+Click, double click, and right clicks should reset the parameter instead
// of initiating a drag operation
self.begin_set_parameters(cx);
@ -483,18 +467,18 @@ impl View for XyPad {
// When holding down shift while clicking on the X-Y pad we want to granuarly
// edit the parameter without jumping to a new value
self.begin_set_parameters(cx);
if cx.modifiers.shift() {
if cx.modifiers().shift() {
self.granular_drag_status = Some(GranularDragStatus {
starting_x_coordinate: cx.mouse.cursorx,
starting_x_coordinate: cx.mouse().cursorx,
x_starting_value: self.x_param_base.unmodulated_normalized_value(),
starting_y_coordinate: cx.mouse.cursory,
starting_y_coordinate: cx.mouse().cursory,
y_starting_value: self.y_param_base.unmodulated_normalized_value(),
});
} else {
self.granular_drag_status = None;
self.set_normalized_values_for_mouse_pos(
cx,
(cx.mouse.cursorx, cx.mouse.cursory),
(cx.mouse().cursorx, cx.mouse().cursory),
false,
);
}
@ -532,9 +516,9 @@ impl View for XyPad {
self.update_tooltip_pos(cx);
if self.drag_active {
let dpi_scale = cx.style.dpi_factor as f32;
let dpi_scale = cx.scale_factor();
if cx.modifiers.shift() {
if cx.modifiers().shift() {
// If shift is being held then the drag should be more granular instead of
// absolute
// TODO: Mouse warping is really needed here, but it's not exposed right now
@ -577,13 +561,17 @@ impl View for XyPad {
self.set_normalized_values_for_mouse_pos(
cx,
(start_x + delta_x, start_y + delta_y),
cx.modifiers.alt(),
cx.modifiers().alt(),
);
} else {
// When alt is pressed _while_ dragging, the frequency parameter on the
// X-axis snaps to whole notes
self.granular_drag_status = None;
self.set_normalized_values_for_mouse_pos(cx, (*x, *y), cx.modifiers.alt());
self.set_normalized_values_for_mouse_pos(
cx,
(*x, *y),
cx.modifiers().alt(),
);
}
}
}
@ -596,8 +584,8 @@ impl View for XyPad {
self.granular_drag_status = None;
self.set_normalized_values_for_mouse_pos(
cx,
(cx.mouse.cursorx, cx.mouse.cursory),
cx.modifiers.alt(),
(cx.mouse().cursorx, cx.mouse().cursory),
cx.modifiers().alt(),
);
}
}
@ -613,7 +601,7 @@ impl View for XyPad {
|value| (self.x_renormalize_event)((self.x_renormalize_display)(value));
if remaining_scroll_x.abs() >= 1.0 {
let use_finer_steps = cx.modifiers.shift();
let use_finer_steps = cx.modifiers().shift();
// Scrolling while dragging needs to be taken into account here
if !self.drag_active {
@ -646,7 +634,7 @@ impl View for XyPad {
}
if remaining_scroll_y.abs() >= 1.0 {
let use_finer_steps = cx.modifiers.shift();
let use_finer_steps = cx.modifiers().shift();
// Scrolling while dragging needs to be taken into account here
if !self.drag_active {