Skip to content
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

Add clamp_to_range_on_drag option to DragValue and clamp_to_range_on_value_drag option to Slider #4882

Closed

Conversation

ishbosamiya
Copy link

Added egui::DragValue::clamp_to_range_on_drag and egui::Slider::clamp_to_range_on_value_drag to allow the user to determine if the value should be clamped while dragging.

The default for egui::DragValue::clamp_to_range_on_drag and egui::Slider::clamp_to_range_on_value_drag is set to true. This means the default behavior mimics 0.28.

If the default behavior must match 0.27, egui::DragValue::clamp_to_range_on_drag should be true and egui::Slider::clamp_to_range_on_value_drag should be false.

egui_slider_clamp_to_range_on_value_drag.mp4

Setting to allow user to determine if value should be clamped to range
on drag.

Previous behaviour always clamped the value to the sliding range on
drag. Due to this, the default is set to `true`.
Setting to allow user to determine if value should be clamped to range
on dragging the value.

Previous behaviour always clamped the value to the sliding range on
drag. Due to this, the default is set to `true`.
Add `egui::Slider::clamp_to_range_on_value_drag` option to the sliders
demo.
@emilk
Copy link
Owner

emilk commented Aug 27, 2024

Do we really need both this options?
It seems to me that clamp_to_range should clamp both drags and keyboard edits instead.

@ishbosamiya
Copy link
Author

I don't think both these options are required. This PR was made assuming that the regression was intentional, it seems like it is not.

I will update the PR soon to use just clamp_to_range.

Remove granularity option to clamp to range on drag. Using
`clamp_to_range` for drag and keyboard edit.

The behavior now mimics `0.27` instead of `0.28`.
@ishbosamiya
Copy link
Author

With the latest update, the behavior now mimics 0.27 where clamp_to_range is used to determine if the value should be clamped while dragging instead of always clamping.

The PR title will need to be updated, but I am not sure about the guidelines for this in egui, so I am leaving it up to you to edit when merging.

@emilk emilk added this to the Next Major Release milestone Sep 1, 2024
@emilk
Copy link
Owner

emilk commented Sep 1, 2024

I'm trying to refresh my memory of the last PR: #4728 by @Wumpf

It seems like we want is three modes:

A) no clamping
B) clamping only user input (dragging or editing text), but leave existing value intact
C) always clamp

The difference between mode B and C is:

let mut x = 42.0;
ui.add(DragValue::new(&mut x).range(0.0..=1.0));
// What will `x` be here?

I think the intention of #4728 was that you get the different modes via:

  • A): don't call .range()
  • B) call .range() and .clamp_to_range(false)
  • C) call .range()

At least, that's how I think both Slider and DragValue should work (it seems like the least surprising behavior). But obviously that's not how DragValue currently works, because it checks clamp_to_range too much. I believe the correct fix is to remove these ifs:

if clamp_to_range {

if clamp_to_range {

Ping @Wumpf

@Wumpf
Copy link
Collaborator

Wumpf commented Sep 17, 2024

Went through it again and can confirm the behavior of the Slider as described by your comment. It is also reflected in the doc strings just fine.

On how to fix it:
The effect of clamping programmatic input if clamp_to_range is false is done early on here

if clamp_to_range {

So afterwards, all clamping is about user input. Since we earlier asserted that user input is always clamped against the set range (which may be infinite in either direction, thus not clamping!), we have to apply clamping to range indiscriminately to user input, but not if no user input occurred. Both pieces of code linked by @emilk are about keyboard user input and indeed this means that there we should apply clamping always.
The last piece where we have to clamp to range is when dragging. That happens here
let rounded_new_value = clamp_value_to_range(rounded_new_value, range.clone());
and already does the right thing

So, yes! What @emilk said :)

Furthermore, documentation on clamping should be equalized between Slider and DragValue, as in both cases the semantics should be the exact same after this change.

@emilk
Copy link
Owner

emilk commented Sep 17, 2024

Then I'll make a new PR to get us the desired behavior

@emilk emilk closed this Sep 17, 2024
emilk added a commit that referenced this pull request Sep 17, 2024
When using a `DragValue`, there are three common modes of range clamping
that the user may want:

A) no clamping
B) clamping only user input (dragging or editing text), but leave
existing value intact
C) always clamp

The difference between mode B and C is:

```rs
let mut x = 42.0;
ui.add(DragValue::new(&mut x).range(0.0..=1.0));
// What will `x` be here?
```

With this PR, we now can get the three behaviors with:

* A): don't call `.range()` (or use `-Inf..=Inf`)
* B) call `.range()` and `.clamp_existing_to_range(false)`
* C) call `.range()`

## Slider clamping
Slider clamping is slightly different, since a slider always has a
range.

For a slider, there are these three cases to consider:

A) no clamping
B) clamp any value that the user enters, but leave existing values
intact
C) always clamp all values

Out of this, C should probably be the default.

I'm not sure what the best API is for this yet. Maybe an `enum` 🤔 


I'll take a pass on that in a future PR.

## Related
* #4728
* #4881
* #4882
emilk added a commit that referenced this pull request Sep 17, 2024
This deprecates `.clamp_to_range` in favor of more control using
`.clamping`.

## Related
* #4728
* Closes #4881
* #4882
* #5118
hacknus pushed a commit to hacknus/egui that referenced this pull request Oct 30, 2024
When using a `DragValue`, there are three common modes of range clamping
that the user may want:

A) no clamping
B) clamping only user input (dragging or editing text), but leave
existing value intact
C) always clamp

The difference between mode B and C is:

```rs
let mut x = 42.0;
ui.add(DragValue::new(&mut x).range(0.0..=1.0));
// What will `x` be here?
```

With this PR, we now can get the three behaviors with:

* A): don't call `.range()` (or use `-Inf..=Inf`)
* B) call `.range()` and `.clamp_existing_to_range(false)`
* C) call `.range()`

## Slider clamping
Slider clamping is slightly different, since a slider always has a
range.

For a slider, there are these three cases to consider:

A) no clamping
B) clamp any value that the user enters, but leave existing values
intact
C) always clamp all values

Out of this, C should probably be the default.

I'm not sure what the best API is for this yet. Maybe an `enum` 🤔 


I'll take a pass on that in a future PR.

## Related
* emilk#4728
* emilk#4881
* emilk#4882
hacknus pushed a commit to hacknus/egui that referenced this pull request Oct 30, 2024
This deprecates `.clamp_to_range` in favor of more control using
`.clamping`.

## Related
* emilk#4728
* Closes emilk#4881
* emilk#4882
* emilk#5118
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.

Regression: dragging value of slider no longer supports out of range values
3 participants