Commit Graph

850 Commits

Author SHA1 Message Date
Lucas Meurer 2b62c68598
Add `egui::Sides` `shrink_left` / `shrink_right` (#7295)
This allows contents (on one of the sides) in egui::Sides to shrink. 

* related https://github.com/rerun-io/rerun/issues/10494
2025-07-03 14:31:35 +02:00
Emil Ernerfeldt ba577602a4
Fix crash when using infinite widgets (#7296)
* Closes https://github.com/emilk/egui/issues/7100
2025-07-03 13:40:02 +02:00
Blackberry Float db3543d034
Update area struct to allow force resizing (#7114)
This is a really small PR so I am skipping the issue (based on
contributing.md). This change adds an optional field and thus non
breaking for the API.

I ran into an issue during my development of an alerts manager widget
([see PR](https://github.com/blackberryfloat/egui_widget_ext/pull/2))
where I needed a scrollable overlay that did not block clicking areas of
a parent widget when my alerts did not take up the entire parent. To
achieve this I detect the sizing pass via the invisible flag and only
render the alerts content and then on the next pass I add the scroll bar
in around the alert content. Whenever the alert content changed though I
would need to create a new Area with a new id to get proper sizing. That
is a memory leak so I wanted to reset the size state to trigger a sizing
pass. Memory is rightfully protected enough that the path to remove
memory was dropped and I just added a hook to set a resize flag.

I am sure there are better ways but this is what made sense to me.
Looking forward to thoughts.

~~Logistics wise, I have proposed it as a patch because I was based off
0.31.1 for testing. I was also thinking it could be released quickly. I
am happy to cherry pick onto main after. If that is not allowed I can
rebase to main and pull against that.~~ (rebased on main)

---------

Co-authored-by: Wesley Murray <murraywj97@gmail.com>
2025-07-03 13:14:07 +02:00
Lucas Meurer 6d312cc4c7
Add support for scrolling via accesskit / kittest (#7286)
I need to scroll in a snapshot test in my app, and kittest had no
utilities for this. Event::MouseWheel is error prone. This adds support
for some accesskit scroll actions, and uses this in kittest to add
helpers to scroll to a node / scroll the scroll area surrounding a node.

The accesskit code says down/up/left/right `Scrolls by approximately one
screen in a specific direction.`. Unfortunately it's difficult to get
the size of a "screen" (I guess that would be the size of the containing
scroll area)where I implemented the scrolling, so for now I've hardcoded
it to 100px. I think scrolling a fixed amount is still better than not
scrolling at all.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-07-03 12:02:05 +02:00
Emil Ernerfeldt 378e22e6ec Improve the `ThemePreference` selection UI slightly 2025-07-03 09:16:13 +02:00
Emil Ernerfeldt dc79998044
Improve text rendering in light mode (#7290)
This changes how we convert glyph coverage to alpha (and ultimately a
color), but only in light mode.

This is a bit of a hack, because it doesn't fix dark-on-light text in
_dark mode_ (if you have any), but for the common case this PR is a huge
improvement.

You can also tweak this yourself now using
`Visuals::text_alpha_from_coverage` or from the UI (bottom of the
image):


![image](https://github.com/user-attachments/assets/350210d4-c0bb-44b6-84cc-47c2e9d4b9f0)



## Before / After

![widget_gallery_light_x1](https://github.com/user-attachments/assets/21f5a2a0-6b4e-4985-b17f-cd1c7cc01b46)
![widget_gallery_light_x1](https://github.com/user-attachments/assets/5dfec04a-c81c-43ef-8d86-fc48ef7958f1)


## Black text Before/after
If you think the text above looks too weak, it's only because of the
default text color. Here's how it looks like with perfectly `#000000`
black text:


![image](https://github.com/user-attachments/assets/56a4a4f3-c431-4991-b941-a566a4ae94ed)
![Screenshot 2025-07-02 at 13 59
30](https://github.com/user-attachments/assets/df5a91ad-0bb8-4a0f-81a2-50852e7556c1)
2025-07-02 14:58:37 +02:00
Emil Ernerfeldt 0857527f1d
Add `Visuals::weak_text_alpha` and `weak_text_color` (#7285)
* Closes https://github.com/emilk/egui/issues/7262

This also makes the default weak color slightly less weak in most cases.
2025-07-01 20:42:54 +02:00
Emil Ernerfeldt 9d1dce51eb
Extend .typos.toml to enforce american english (#7284)
More or less the same list we use at Rerun
2025-07-01 15:54:00 +02:00
Emil Ernerfeldt 737c61867b
Add `Visuals::text_edit_bg_color` (#7283)
* Closes https://github.com/emilk/egui/issues/7263
2025-07-01 15:13:16 +02:00
Emil Ernerfeldt 9e021f78da
Change `ui.disable()` to modify opacity (#7282)
* Closes https://github.com/emilk/egui/pull/6765


Branched off of https://github.com/emilk/egui/pull/6765 by @tye-exe.

I needed to branch off to update snapshot images

---------

Co-authored-by: tye-exe <tye@mailbox.org>
Co-authored-by: Tye <131195812+tye-exe@users.noreply.github.com>
2025-07-01 14:05:53 +02:00
Emil Ernerfeldt b2995dcb83
Use Rust edition 2024 (#7280) 2025-06-30 14:01:57 +02:00
Emil Ernerfeldt 962c8e26a8
Update MSRV to 1.85 (#7279) 2025-06-30 13:43:27 +02:00
Emil Ernerfeldt 8ba42f322d
Add `Context::cumulative_frame_nr` (#7278) 2025-06-30 13:29:56 +02:00
Emil Ernerfeldt d770cd53a6
Add `Context::current_pass_index` (#7276)
This can be used by developers who wants to add diagnostics when there
is a multi-pass egui frame.
2025-06-30 10:41:27 +02:00
Lukas Rieger c943720eed
Slider: move by at least the next increment when using fixed_decimals (#7066)
fixes https://github.com/emilk/egui/issues/7065
2025-06-29 13:30:39 +02:00
Nicolas ab9f55ab01
Fix crash in `egui_extras::FileLoader` after `forget_image` (#6995)
This pull request modifies the `BytesLoader` implementation for
`FileLoader` in `crates/egui_extras/src/loaders/file_loader.rs` to
improve thread safety and handle unexpected states more gracefully.

### Changes to thread safety and state handling:
* Updated the cache logic to check if the `uri` exists in the cache
before inserting the result. If the `uri` is not found, a log message is
added to indicate the loading was canceled. This change prevents
overwriting cache entries unexpectedly.

* Closes <https://github.com/emilk/egui/issues/6755>
* [x] I have followed the instructions in the PR template
2025-06-27 11:27:03 +02:00
Lucas Meurer 78a8de2e8f
Respect `StyleModifier` in popup `Frame` style (#7265)
This makes it possible to style the Popup's frame using a StyleModifier
2025-06-25 14:26:36 +02:00
Lucas Meurer c8b844cd83
Use the new Popup api for the color picker button (#7137)
The color picker popup is now aligned to the bottom left edge (instead
of the bottom right), but I think this makes more sense and is aligned
with ComboBox etc. It also gets the new nice auto positioning.

* closes #5832 
* [x] I have followed the instructions in the PR template
2025-06-18 19:19:05 +02:00
Emil Ernerfeldt 8c2df4802c
Add back old `Tooltip::new` (#7156)
I was a bit too hasty in https://github.com/emilk/egui/pull/7151 and
changed a public API in a breaking way, for no good reason
2025-06-16 19:36:19 +02:00
Lucas Meurer 5194c0df3e
Minor atoms improvements (#7145)
Improve some lifetime bounds and add some convenience constructors
2025-06-16 08:42:17 +02:00
Emil Ernerfeldt 06760e1b08
Change API of `Tooltip` slightly (#7151)
We try to be consistent with our parameter order to reduce surprise for
users.

I also renamed a few things to clarify what is what
2025-06-16 08:30:46 +02:00
Azkellas 96c34139fd
Select all text in DragValue when gaining focus via keyboard (#7107)
Previously, the `DragValue` widget selected all text when focus was
gained via a mouse click, but didn't when focus was gained via keyboard.


https://github.com/user-attachments/assets/5e82ca2c-0214-4201-ad2d-056dabc05e92

This PR makes both gained focus behaving the same way by selecting the
text on focus gained via keyboard.


https://github.com/user-attachments/assets/f246c779-3368-428c-a6b2-cec20dbc20a6

- [x] I have followed the instructions in the PR template

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-06-16 02:11:26 +02:00
valadaptive 54fded362d
Clamp text cursor positions in the same places where we used to (#7081)
Closes #7077.

This fixes the problem shown in #7077 where clearing a `TextEdit`
wouldn't reset its cursor position. I've fixed that by adding back the
`TextCursorState::range` method, which clamps the selection range to
that of the passed `Galley`, and calling it in the same places where it
was called before #5785.

(/cc @juancampa)

* [x] I have followed the instructions in the PR template
2025-06-16 01:53:00 +02:00
ardocrat 742da95bd7
Support for Back button Key on Android (#7073)
When your press a Back button on Android (for example at
`native-activity`), [Winit translates this
key](47b938dbe7/src/platform_impl/android/keycodes.rs (L237C42-L237C53))
as `NamedKey::BrowserBack`. Added convertion to `Key::Escape` at
`egui-winit` module.

---------

Co-authored-by: Advocat <advocat@ogr.local>
2025-06-16 01:28:27 +02:00
Lucas Meurer 4c04996a72
Fix missing repaint after `consume_key` (#7134)
Usually input events automatically trigger a repaint. But since
consume_key would remove the event egui would think there were no events
and not trigger a repaint. This fixes it by setting a flag on InputState
on consume_key.

* related: https://github.com/rerun-io/rerun/issues/10165
2025-06-13 14:06:50 +02:00
Lucas Meurer 5bc19f3ca3
Report image alt text as text if widget contains no other text (#7142)
- Same as https://github.com/emilk/egui/pull/7136 but now for atomics
2025-06-13 13:54:07 +02:00
Lucas Meurer 6eb7bb6e08
Add `AtomLayout`, abstracing layouting within widgets (#5830)
Today each widget does its own custom layout, which has some drawbacks:
- not very flexible
- you can add an `Image` to `Button` but it will always be shown on the
left side
  - you can't add a `Image` to a e.g. a `SelectableLabel`
- a lot of duplicated code

This PR introduces `Atoms` and `AtomLayout` which abstracts over "widget
content" and layout within widgets, so it'd be possible to add images /
text / custom rendering (for e.g. the checkbox) to any widget.

A simple custom button implementation is now as easy as this:
```rs
pub struct ALButton<'a> {
    al: AtomicLayout<'a>,
}

impl<'a> ALButton<'a> {
    pub fn new(content: impl IntoAtomics) -> Self {
        Self { al: content.into_atomics() }
    }
}

impl<'a> Widget for ALButton<'a> {
    fn ui(mut self, ui: &mut Ui) -> Response {
        let response = ui.ctx().read_response(ui.next_auto_id());

        let visuals = response.map_or(&ui.style().visuals.widgets.inactive, |response| {
            ui.style().interact(&response)
        });

        self.al.frame = self
            .al
            .frame
            .inner_margin(ui.style().spacing.button_padding)
            .fill(visuals.bg_fill)
            .stroke(visuals.bg_stroke)
            .corner_radius(visuals.corner_radius);

        self.al.show(ui)
    }
}

```

The initial implementation only does very basic layout, just enough to
be able to implement most current egui widgets, so:
- only horizontal layout
- everything is centered
- a single item may grow/shrink based on the available space
- everything can be contained in a Frame


There is a trait `IntoAtoms` that conveniently allows you to construct
`Atoms` from a tuple
```
   ui.button((Image::new("image.png"), "Click me!"))
```
to get a button with image and text.


This PR reimplements three egui widgets based on the new AtomLayout:
 - Button
   - matches the old button pixel-by-pixel
- Button with image is now [properly
aligned](https://github.com/emilk/egui/pull/5830/files#diff-962ce2c68ab50724b01c6b64c683c4067edd9b79fcdcb39a6071021e33ebe772)
in justified layouts
   - selected button style now matches SelecatbleLabel look
- For some reason the DragValue text seems shifted by a pixel almost
everywhere, but I think it's more centered now, yay?
 - Checkbox
- basically pixel-perfect but apparently the check mesh is very slightly
different so I had to update the snapshot
   - somehow needs a bit more space in some snapshot tests?
 - RadioButton
   - pixel-perfect
   - somehow needs a bit more space in some snapshot tests?

I plan on updating TextEdit based on AtomLayout in a separate PR (so
you could use it to add a icon within the textedit frame).
2025-06-13 09:39:52 +02:00
Emil Ernerfeldt f0abce9bb8
`Button` inherits the `alt_text` of the `Image` in it, if any (#7136)
If a `Button` has an `Image` in it (and no text), then the
`Image::alt_text` will be used as the accessibility label for the
button.
2025-06-11 23:00:59 +02:00
Nicolas 9f9153805d
lint: fix lints appearing in rust stable currently (#7118)
* [x] I have followed the instructions in the PR template
2025-06-11 17:38:06 +02:00
Rinde van Lon cfb10a04f5
Improve `ComboBox` doc example (#7116)
Improves the `ComboBox` example with some code that shows how to handle
changes in the `ComboBox`’s selection. The approach is based on the
advice given in https://github.com/emilk/egui/discussions/923 . I hope
this saves future me (and hopefully others) a web search for how to do
this.

* [x] I have followed the instructions in the PR template
2025-06-11 12:01:34 +02:00
Emil Ernerfeldt 209e818bd8 Improve deprecation message for old `egui::menu` 2025-06-07 10:24:28 -07:00
Emil Ernerfeldt 6e34152fa0
Add `Context::format_modifiers` (#7125)
Convenience
2025-06-07 19:22:16 +02:00
Emil Ernerfeldt 53098fad7b
Support vertical-only scrolling by holding down Alt (#7124)
* Closes https://github.com/emilk/egui/issues/7120

You can now zoom only the X axis by holding down shift, and zoom only
the Y axis by holding down ALT.

In summary

* `Shift`: horizontal
* `Alt`: vertical
* `Ctrl`: zoom (`Cmd` on Mac)

Thus follows:
* `scroll`: pan both axis (at least for trackpads and mice with two-axis
scroll)
* `Shift + scroll`: pan only horizontal axis
* `Alt + scroll`: pan only vertical axis
* `Ctrl + scroll`: zoom all axes
* `Ctrl + Shift + scroll`: zoom only horizontal axis
* `Ctrl + Alt + scroll`: zoom only vertical axis

This is provided the application uses `zoom_delta_2d` for its zooming
needs.

The modifiers are exposed in `InputOptions`, but it is strongly
recommended that you do not change them.

## Testing
Unfortunately we have no nice way of testing this in egui.
But I've tested it in `egui_plot`.
2025-06-07 19:18:13 +02:00
Emil Ernerfeldt 1d5b011793
Add `OperatingSystem::is_mac` (#7122)
* Part of https://github.com/emilk/egui/issues/7120
2025-06-07 18:36:23 +02:00
Emil Ernerfeldt cbd9c60399
Add `Modifiers::matches_any` (#7123)
* Part of https://github.com/emilk/egui/issues/7120
2025-06-07 18:36:16 +02:00
Emil Ernerfeldt 9681644936
Move all input-related options into `InputOptions` (#7121) 2025-06-07 18:25:19 +02:00
Emil Ernerfeldt 92fea8a18f
Remove things that have been deprecated for over a year (#7099)
Removes all things that were marked `#[deprecated]` more than 12 months
ago
2025-05-28 09:47:15 +02:00
Emil Ernerfeldt 2cf6a3a9a6
Track original SVG size (#7098)
This fixes bugs related to how an `Image` follows the size of an SVG.

We track the "source size" of each image, i.e. the original width/height
of the SVG, which can be different from whatever it was rasterized as.
2025-05-28 08:33:01 +02:00
Emil Ernerfeldt da67465a6c
Add `Response::clicked_with_open_in_background` (#7093)
Useful for buttons that should act as Hyperlinks
2025-05-26 19:44:55 +02:00
Emil Ernerfeldt 87de733da3
Better define the meaning of `SizeHint` (#7079) 2025-05-23 13:52:36 +02:00
Emil Ernerfeldt ec8b41f7ec
Make `Image::paint_at` pixel-perfect crisp for SVG images (#7078) 2025-05-23 10:15:17 +02:00
Emil Ernerfeldt b8334f365b
Fix sometimes blurry SVGs (#7071)
* Closes https://github.com/emilk/egui/issues/3501

The problem occurs when you want to render the same SVG at different
scales, either at the same time in different parts of your UI, or at two
different times (e.g. the DPI changes).

The solution is to use the `SizeHint` as part of the key.

However, when you have an SVG in a resizable container, that can lead to
hundreds of versions of the same SVG. So new eviction code is added to
handle this case.
2025-05-21 20:01:40 +02:00
Emil Ernerfeldt b05a40745f
Bug fix: make sure `end_pass` is called for all loaders (#7072)
None of the built-in loaders does any cache eviction (yet), but 3rd
party ones might have
2025-05-21 19:52:59 +02:00
Abdellatif EL MIZEB cb4acbc262
Fix typo in deprecation message for `ComboBox::from_id_source` (#7055)
This PR corrects the deprecation note on ComboBox::from_id_source:

Changed:
`#[deprecated = "Renamed id_salt"]`

To:
`#[deprecated = "Renamed from_id_salt"]`
2025-05-18 13:02:58 +02:00
Emil Ernerfeldt 81b7e7f05a
Make the default spinner more high-res (#7044)
Make it nice and smooth when big
2025-05-11 22:15:07 +02:00
Lucas Meurer 120d736cfc
Add `ImageLoader::has_pending` and `wait_for_pending_images` (#7030)
With kittest it was difficult to wait for images to be loaded before
taking a snapshot test.
This PR adds `Harness::with_wait_for_pending_images` (true by default)
which will cause `Harness::run` to sleep until all images are loaded (or
`HarnessBuilder::with_max_steps` is exceeded).

It also adds a new ImageLoader::has_pending and
BytesLoader::has_pending, which should be implemented if things are
loaded / decoded asynchronously.

It reverts https://github.com/emilk/egui/pull/6901 which was my previous
attempt to fix this (but this didn't work since only the tested crate is
compiled with cfg(test) and not it's dependencies)
2025-05-08 09:27:52 +02:00
Emil Ernerfeldt d0876a1a60
Rename `master` branch to `main` (#7034)
For consistency with other repositories, i.e. so I can write `git
checkout main` without worrying which repo I'm browsing.
2025-05-08 09:15:42 +02:00
Emil Ernerfeldt 7216d0e386
Use mimalloc for benchmarks (#7029)
`mimalloc` is a _much_ faster allocator, especially important when doing
a lot of small allocations (which egui does).

We use `mimalloc` in Rerun, and I recommend everyone to use it.

## The difference it makes

![image](https://github.com/user-attachments/assets/b22e0025-bc5e-4b3c-94e0-74ce46e86f85)
2025-05-06 17:54:06 +02:00
Lucas Meurer 5bb20f511e
Fix links and text selection in horizontal_wrapped layout (#6905)
* Closes <https://github.com/emilk/egui/issues/6904>
* [x] I have followed the instructions in the PR template

This was broken in https://github.com/emilk/egui/pull/5411. Not sure if
this is the best fix or if `PlacedRow::rect` should be updated, but I
think it makes sense that PlacedRow::rect ignores leading space.
2025-05-06 17:40:18 +02:00
Lucas Meurer 71e0b0859c
Make `WidgetText` smaller and faster (#6903)
* In preparation of #5830, this should reduce the performance impact of
that PR

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
2025-05-06 17:35:56 +02:00