slider: Improve Slider interaction to click on bar to drag. (#1544)
This pull request adds a drag event to the slider bar itself, analogous to the drag handles, in case the slider is not a range slider. This allows for a more intuitive interaction with the slider, where one can click and drag on any part of the slider bar container. https://github.com/user-attachments/assets/4d41ba10-2992-4a42-beb6-0bc376185c5e This doesn't change the behavior for range sliders, as it's ambiguous which slider should be dragged in case the event starts between the sliders. Though if desired, it wouldn't be difficult to implement the same behavior for clicks below the start or above the end slider.
This commit is contained in:
parent
a2c55dda46
commit
b899100d09
1 changed files with 36 additions and 0 deletions
|
|
@ -17,6 +17,15 @@ impl Render for DragThumb {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct DragSlider(EntityId);
|
||||
|
||||
impl Render for DragSlider {
|
||||
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
|
||||
Empty
|
||||
}
|
||||
}
|
||||
|
||||
/// Events emitted by the [`SliderState`].
|
||||
pub enum SliderEvent {
|
||||
Change(SliderValue),
|
||||
|
|
@ -387,6 +396,7 @@ impl Styled for Slider {
|
|||
impl RenderOnce for Slider {
|
||||
fn render(self, window: &mut Window, cx: &mut gpui::App) -> impl IntoElement {
|
||||
let axis = self.axis;
|
||||
let entity_id = self.state.entity_id();
|
||||
let state = self.state.read(cx);
|
||||
let is_range = state.value().is_range();
|
||||
let bar_size = state.bounds.size.along(axis);
|
||||
|
|
@ -440,6 +450,7 @@ impl RenderOnce for Slider {
|
|||
.text_color(cx.theme().foreground)
|
||||
.child(
|
||||
h_flex()
|
||||
.id("slider-bar-container")
|
||||
.when(!self.disabled, |this| {
|
||||
this.on_mouse_down(
|
||||
MouseButton::Left,
|
||||
|
|
@ -464,6 +475,31 @@ impl RenderOnce for Slider {
|
|||
),
|
||||
)
|
||||
})
|
||||
.when(!self.disabled && !is_range, |this| {
|
||||
this.on_drag(DragSlider(entity_id), |drag, _, _, cx| {
|
||||
cx.stop_propagation();
|
||||
cx.new(|_| drag.clone())
|
||||
})
|
||||
.on_drag_move(window.listener_for(
|
||||
&self.state,
|
||||
move |view, e: &DragMoveEvent<DragSlider>, window, cx| match e.drag(cx)
|
||||
{
|
||||
DragSlider(id) => {
|
||||
if *id != entity_id {
|
||||
return;
|
||||
}
|
||||
|
||||
view.update_value_by_position(
|
||||
axis,
|
||||
e.event.position,
|
||||
false,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
},
|
||||
))
|
||||
})
|
||||
.when(axis.is_horizontal(), |this| {
|
||||
this.items_center().h_6().w_full()
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue