egui/crates
Douglas Dwyer 73bb4cedb4
Prevent `ScrollArea` contents from exceeding the container size (#5006)
When a `ScrollArea` is added to a `Ui` or its contents change
dynamically, the contents will briefly escape the container. This occurs
because `ScrollArea` internally maintains `content_is_too_large` flags,
from which it determines when to clip. The `content_is_too_large` flags
are calculated after painting, so they always lag one frame behind. This
can lead to flickering.

To fix this, I have changed the `ScrollArea` so that it always clips
scrollable content. I believe that this should fix things without
negatively impacting other behavior. To see this, consider how
`ScrollArea` calculates the `content_is_too_large` flag:

```rust
// This calculates a new inner rect, after painting, from the initial clip rect
let inner_rect = {
  // At this point this is the available size for the inner rect.
  let mut inner_size = inner_rect.size();
  
  for d in 0..2 {
      inner_size[d] = match (scroll_enabled[d], auto_shrink[d]) {
          (true, true) => inner_size[d].min(content_size[d]), // shrink scroll area if content is small
          (true, false) => inner_size[d], // let scroll area be larger than content; fill with blank space
          (false, true) => content_size[d], // Follow the content (expand/contract to fit it).
          (false, false) => inner_size[d].max(content_size[d]), // Expand to fit content
      };
  }
  
  Rect::from_min_size(inner_rect.min, inner_size)
};

let outer_rect = Rect::from_min_size(inner_rect.min, inner_rect.size() + current_bar_use);

let content_is_too_large = Vec2b::new(
  scroll_enabled[0] && inner_rect.width() < content_size.x,
  scroll_enabled[1] && inner_rect.height() < content_size.y,
);
```
If `scroll_enabled[d] == true`, then the actual `inner_rect` (which is
calculated after painting contents) will always be smaller than the
original `inner_rect`. Hence, it is safe to unconditionally clip the
contents to `inner_rect` whenever `scroll_enabled[d] == true`.

<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

* Closes <https://github.com/emilk/egui/issues/4742>
* [x] I have followed the instructions in the PR template
2024-08-27 10:22:32 +02:00
..
ecolor Remove some debug asserts (#4826) 2024-07-15 11:20:22 +02:00
eframe Fix virtual keyboard on (mobile) web (#4855) 2024-08-27 09:42:35 +02:00
egui Prevent `ScrollArea` contents from exceeding the container size (#5006) 2024-08-27 10:22:32 +02:00
egui-wgpu Update to wgpu 22.1 (#4964) 2024-08-16 13:29:40 +02:00
egui-winit Fix CI (#5005) 2024-08-26 15:35:44 +02:00
egui_demo_app Update `web-sys` & `wasm-bindgen` (#4980) 2024-08-26 11:38:30 +02:00
egui_demo_lib Create a `UiBuilder` for building `Ui`s (#4969) 2024-08-26 08:51:18 +02:00
egui_extras `egui_extras`: Fix file mime from path (wrong feature name) (#4933) 2024-08-26 11:24:08 +02:00
egui_glow Unpin & upgrade winit to 0.30.5 (#4939) 2024-08-09 09:15:14 +02:00
egui_plot Move `egui_plot` to its own repo (#4828) 2024-07-15 18:45:19 +02:00
egui_web Fix typos (#2866) 2023-04-18 15:52:45 +02:00
emath Add `Rect::scale_from_center` (#4673) 2024-07-15 19:54:35 +02:00
epaint Deprecate `ahash` re-exports (#4979) 2024-08-26 10:41:16 +02:00
epaint_default_fonts Move default fonts to new crate `epaint_default_fonts` (#4853) 2024-07-31 09:50:02 +02:00