Skip to content

Make slider behave like progress bar #802

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

aganm
Copy link
Contributor

@aganm aganm commented Apr 19, 2025

I thought that the slider widget was very annoying to use because you have to put your mouse exactly on the knob to drag it along the axis of the widget:

gif1

A much smoother behavior is the one of the progress bar, where you can click anywhere on the widget, and the knob will automatically be changed to this position. So I simply reused the progress bar behavior inside of the slider and it works perfectly smooth and is much more pleasant to use:

gif2

Copy link
Contributor

@RobLoach RobLoach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates. Looks pretty good to me, I'll leave this open for a couple others to review.

@awschult002
Copy link
Contributor

i fully support this PR. I think it is a wonderful addition; but the implementation of new behavior leaves me with a question for @RobLoach .

In my head, a progress bar is a visual output only. a status indicator. user input would have no place in a progress bar. Yet, we see with this PR that the update is for the slider bar to call the progress_bar_behavior function. to which, if I read it correctly, has the user input in it.

Why does the progress bar have user input? I find this very confusing. What makes a progress bar different than a slider if they both support input? I haven't made a progress bar using this framework yet... how do i disable the user input for the progress bar?

@mlyszczek
Copy link

To make it even more fluid you may consider adding this line to nk_progress_behavior()

@@ -26443,6 +26444,7 @@ nk_progress_behavior(nk_flags *state, struct nk_input *in,
     if (in && left_mouse_down && left_mouse_click_in_cursor) {
         if (left_mouse_down && left_mouse_click_in_cursor) {
             float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w;
+            ratio += 0.5 / (float)max;
             value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max);
             in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f;
             *state |= NK_WIDGET_STATE_ACTIVE;

rn, slider will work as this. Imagine slider with 3 values, 0, 1, and 2. When you move the mouse, value will change to 1, when mouse is at 50% of slider, 49% and value will go back down to 0. This is not how most sliders seem to be work. With this one line, value will jump to 1, at 25% of mouse, and will go back down at 24%.

I hope you get what I mean. Values will change in the middle between values, which I - personally - find to be more natural way to operate slider.

@mlyszczek
Copy link

This how slider will feel with that change: https://jsfiddle.net/guf6t9jy

@mlyszczek
Copy link

mlyszczek commented Jun 8, 2025

Did some digging, and it appears OPs behavior can be done in nk_slider_behavior, just need to change 1 line.

@@ -25948,7 +25948,7 @@ nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
nk_widget_state_reset(state);
left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
-            NK_BUTTON_LEFT, *visual_cursor, nk_true);
+            NK_BUTTON_LEFT, bounds, nk_true);

This also fixes some of the bad behavior with slider based on progress bar when steps!=1. I'd say - this is the way to go with it.

@awschult002
Copy link
Contributor

Would recommend updating PR to use the slider behavior instead of progress bar for consistency.

@kripesh101
Copy link

Thanks to mlyszczek the perfect slider is almost there... but bounds is not wide enough to accommodate the visual cursor when it is at either end, so checking for both like this yields perfect results:

-    left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
-            NK_BUTTON_LEFT, *visual_cursor, nk_true);
+    left_mouse_click_in_cursor = in && (
+        nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, *visual_cursor, nk_true)
+        || nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, bounds, nk_true));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants