Nuklear icon indicating copy to clipboard operation
Nuklear copied to clipboard

Make slider behave like progress bar

Open aganm opened this issue 8 months ago • 6 comments

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

aganm avatar Apr 19 '25 19:04 aganm

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?

awschult002 avatar Jun 04 '25 23:06 awschult002

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 avatar Jun 07 '25 00:06 mlyszczek

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

mlyszczek avatar Jun 07 '25 00:06 mlyszczek

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.

mlyszczek avatar Jun 08 '25 00:06 mlyszczek

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

awschult002 avatar Jun 10 '25 11:06 awschult002

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));

kripesh101 avatar Jun 15 '25 12:06 kripesh101